《汇编语言》(王爽)补充笔记,第 14 ~ 17 章

第十四章 CALL 和 RET 指令

● 与总线相连的各设备芯片中均有一组可供 CPU 访问的寄存器,总线除了连接存储器芯片外还有:① 各种接口卡(网卡、显卡、声卡)的芯片;② 主板接口芯片,用于访问部分外设;③ 其他芯片,用于存储相关系统信息及处理输入输出

● CPU 定位设备地址范围为 0 ~ 65535,共 64 KB。端口读写指令只有两条,in 和 out,分别用于读取和写入,用 ax 或 al 来存放转移数据。

● 地址 0 ~ 255 设备读写时可以使用立即数作地址,地址 256 ~ 65536 设备读写时端口号放在 dx 中

1     in  al, 20h     ; 20h 端口读取 1 Byte 数据,放入 al
2     out 20h, al     ; 20h 端口写入 1 Byte 数据,来自 al,注意操作数顺序
3 
4     mov dx, 0100h   ; 大地址读写
5     in  al, dx
6     out dx, al

● CMOS RAM 芯片,特性:

  ① 包含一个实时钟

  ② 靠纽扣电池供电

  ③ 包含128 Byte 的 RAM 存储器,00h ~ 0dh 单元存储时间信息,其他部分存储系统配置信息供启动时 BIOS 读取,BIOS 中有相关例程可以编辑 CMOS 信息。

  ④ 端口地址 70h 和 71h,前者存放目标 RAM 地址,后者存放读写数据。CPU 读写分两步,先向 70h 写入地址,再对 71h 进行读写操作。

● shl 和 shr 命令,当位移数大于 1 时 要将位移数放入 cl 中

● BCD 码:用四位二进制数表示两位十进制数码的方法,每两位十进制数(如36)分别写成二进制后拼成 1 Byte(00110110)

● CMOS 中,年月日时分秒 6 个信息长度均为 1 Byte,存放地址:秒(0)分(2)时(4)日(7)月(8)年(9),

● 代码,从 CMOS 中读取时间,在屏幕上动态输出(之前一直不能用的输出方式,现在能用了)

 1 assume cs:code
 2 code segment
 3     s1: db 9, 8, 7, 4, 2, 0             ; 各数据的位置
 4     s2: dw 0, 0, 0, 0, 0, 0            
 5     s3: db '/', '/', ' ', ':', ':', ' ' ; 用于输出的字符串
 6 
 7 start:
 8     mov ax, cs
 9     mov ds, ax
10     mov bx, offset s1
11     mov si, offset s2
12 
13     mov cx, 6           ; 一个时间要读 6 次得到
14 reads: 
15     push cx
16     mov al, [bx]        ; 取所需数据的地址
17     out 70h, al         ; 读取数据
18     in al, 71h
19     mov ah, al          ; ah 存十位数,al 存个位数
20     mov cl, 4
21     shr ah, cl
22     and al, 00001111b
23 
24     add ah, 30h         ; 十六进制数转 ASCII 码
25     add al, 30h
26     mov [si], ah        ; 保存读取的数据
27     mov [si+1], al
28     inc bx              ; 指向下一个数据
29     add si, 2
30     pop cx
31     loop reads
32 
33     mov ax, 0b800h      ; 数据移动到特定内存用于显示,es : bx 表示终端第 12 行 10 列
34     mov es, ax
35     mov bx, 160 * 12 + 10 * 2
36     mov si, offset s2
37     mov di, offset s3
38 
39     mov ah, 2           ; 指定颜色
40     mov cx, 6
41 show:   
42     mov al, [si]        ; 每读两位 s2(用 si ),读一位 S3(用 di)
43     mov es:[bx], al 
44     mov es:[bx+1], ah
45     add bx, 2
46     mov al, [si+1]
47     mov es:[bx], al 
48     mov es:[bx+1], ah
49     add bx, 2
50     mov al, [di]
51     mov es:[bx], al 
52     mov es:[bx+1], ah
53 
54     add bx, 2           ; 移动指针 
55     add si, 2
56     inc di
57     loop show
58 
59     in al, 60h          ; 键盘输入
60     cmp al, 10h         ; 检查输入是否为 'q'
61     jne start           ; 循环
62 
63     mov ax, 4c00h
64     int 21h
65 code ends
66 
67 end start

第十五章 外中断

● CPU 在执行完一条指令后可以检测外中断信息,引发中断过程,处理外设输入

● 标志寄存器 IF =1 时 CPU 响应外中断,IF = 0 时 CPU 屏蔽外中断不响应

● 指令 sti 置标志寄存器 IF 为 1;cti 置标志寄存器 IF 为 0

● 8086 CPU 中,几乎所有外设引发的终端都是可屏蔽中断,不可屏蔽中断的终端类型码固定为 2

● 键盘中断特性:

  ① 按下或放开一个键,键盘产生相应的扫描码;

  ② 按下产生通码,松开产生断码,同一按键,断码 = 通码 + 20h;

  ③ 按下或放开一个键,键盘芯片向 60h 端口寄存器写入扫描码;

  ④ 相关芯片向 CPU 引发 9 号中断码;

  ⑤ BIOS 键盘缓冲区可以存储 15 个键盘输入等待 CPU 响应,每个键盘输入为 1 个字,高字节存放扫描码,低字节存放字符码;

  ⑥ 0400 : 0017 存放键盘状态字节,该字节的各位记录辅助按键的状态:Insert(7),CapsLock(6),NumLock(5),ScrollLock(4),Alt(3),Ctrl(2),左 Shift(1),右 Shift(0)

● 代码,在屏幕上逐个显示 a ~ z,期间按下 Esc 改变字体颜色

 1 assume cs:code
 2 
 3 stack segment
 4     db 128 dup (0)
 5 stack ends
 6 
 7 data segment
 8     dw 0, 0
 9 data ends
10 
11 code segment
12 start:
13     mov ax, stack
14     mov ss, ax
15     mov sp, 128
16     mov ax, data
17     mov ds, ax
18     mov ax, 0
19     mov es, ax
20 
21     push es:[9*4]                       ; 原 int 9 中断例程的入口地址保存到 0000 : 0200
22     pop ds:[0]                          ; 使用栈中转,把 es : [] 指向的内存放入 ds : []
23     push es:[9*4+2]
24     pop ds:[2]                          
25 
26     cli                                 ; 不需要等待键盘输入时,及时置屏蔽中断标志位 IF = 0
27 
28     mov word ptr es:[9*4], offset int9  ; 设置新的 int 9 程序的入口地址
29     mov es:[9*4+2], cs
30 
31     sti                                 ; 需要键盘输入时,置屏蔽中断标志位 IF = 1
32 
33     mov ax, 0b800h                      ; 最初显示
34     mov es, ax
35     mov ah, 'a'
36 s:
37     mov  es:[160*12+40*2], ah           ; 循环显示
38     call delay
39     inc ah
40     cmp ah, 'z'
41     jna s
42     mov ax, 0
43     mov es, ax
44 
45     cli                 
46 
47     push ds:[0]         ; 将中断向量表中 int 9 中断例程的入口恢复为原来的地址
48     pop es:[9*4]
49     push ds             ; [2]
50     pop es              ; [9*4+2]
51 
52     sti                 
53 
54     mov ax, 4c00h
55     int 21h
56 
57 delay:    
58     push ax             ; 延时
59     push dx
60     mov dx, 1h         ; 使用 dx : ax = 1000000000 向下递减,减到零时退出
61     mov ax, 0
62 s1:
63     sub ax, 1
64     sbb dx, 0
65     cmp ax, 0
66     jne s1
67     cmp dx, 0
68     jne s1
69     pop dx
70     pop ax
71     ret
72 
73 int9:    
74     push ax
75     push bx
76     push es
77 
78     in al, 60h                      ; 读取键盘
79 
80     pushf
81 
82     call dword ptr ds:[0]           ; 调用原 int 9 中断例程
83 
84     cmp al, 1
85     jne int9ret
86 
87     mov ax, 0b800h
88     mov es, ax
89     inc byte ptr es:[160*12+40*2+1] ; 属性值增加 1,从前景色开始改变颜色
90 
91 int9ret:
92     pop es
93     pop bx
94     pop ax
95     iret
96 
97 code ends
98 
99 end start

第十六章 直接址表(即表驱动查找)

● 地址标号与数据标号

 1 code segment
 2     a: db 1, 2, 3, 4, 5, 6, 7, 8    ; 地址标号,仅表地址,只能在代码段中使用    
 3 
 4     mov si, OFFSET a                ; 要用 OFFSET 来计算
 5     mov al, cs:[si]
 6 
 7     ...
 8 ;----------------------------------------------------------------
 9 code segment
10     a db 1, 2, 3, 4, 5, 6, 7, 8     ; 数据标号,表地址和内存单元长    
11     
12     mov si, 0                       ; 直接使用数组名和偏移地址来取            
13     mov al, a[si]
14 
15     ...
16 ;----------------------------------------------------------------
17 code segment
18     a db 1, 2, 3, 4, 5, 6, 7, 8
19     b dw 0, 0, 0, 0
20     c dw a, b                       ; c 中存储 a 和 b 的偏移地址
21                                     ; 等价于 c dw OFFSET a, OFFSET b
22     d dd a, b                       ; d 中存储 a 和 b 的短地址和偏移地址            
23                                     ; 等价于 d dd OFFSET a, SEG a, OFFSET b, SEG b 

第十七章 使用 BIOS 进行键盘输入和磁盘读写

● BIOS int 16h 中断例程 0 号子程序,从键盘缓冲区读取一个输入,并将其从缓冲区中删除,若缓冲区为空,则循环等待直到有数据。调用时 mov ah,0  int 16h ,返回 ah 为扫描码,al 为 ASCII 码

● 代码,简单的字符串输入程序,能够输入、删除

  1 assume cs:code
  2 
  3 code segment
  4 start:    
  5     call getstr    
  6 
  7 return:    
  8     mov ax, 4c00h
  9     int 21h
 10 
 11 getstr:                 ; 接收字符串    
 12     push ax 
 13 
 14 getstrs:
 15     mov ah, 0
 16     int 16h
 17     
 18     cmp al, 20h
 19     jb nochar           ; ASCII < 0,不是字符
 20     mov ah, 0
 21     call charstack      ; 字符入栈
 22     mov ah, 2
 23     call charstack      ; 显示栈中的字符
 24     jmp getstrs
 25 
 26 nochar:                 ; 输入非字符键
 27     cmp ah, 0eh         ; 退格键
 28     je backspace
 29     cmp ah, 1ch         ; 回车键
 30     je enter
 31     jmp getstrs
 32         
 33 backspace:              ; 输入退格键
 34     mov ah, 1    
 35     call charstack      ; 字符出栈
 36     mov ah, 2
 37     call charstack      ; 打印栈中字符串
 38     jmp getstrs
 39 
 40 enter:                  ; 输入回车键
 41     mov al, 0
 42     mov ah, 0
 43     call charstack      ; 0 入栈
 44     mov ah, 2
 45     call charstack      ;显示栈中的字符
 46 
 47     pop ax
 48     ret
 49 
 50 charstack:                                  ; 实现与栈相关功能的程序
 51     jmp short charstart
 52     table dw charpush, charpop, charshow    ; 驱动表,0 入栈,1 出栈,2 打印栈
 53     top dw 0                                ; 栈顶
 54 charstart:
 55     push bx
 56     push dx
 57     push di
 58     push es
 59 
 60     cmp ah, 2
 61     ja sret                     ; >2 的非法输入,直接结束
 62     mov bl, ah                  ; [0, 1, 2] -> [0, 2, 4]
 63     mov bh, 0
 64     add bx, bx
 65     jmp word ptr table[bx]      ; 每个表项占 4 字节
 66 
 67 charpush:                       ; al 入栈
 68     mov bx, top
 69     mov [si][bx], al
 70     inc top
 71     jmp sret
 72 
 73 charpop:                        ; 出栈到 al
 74     cmp top, 0
 75     je sret
 76     dec top
 77     mov bx, top
 78     mov al, [si][bx]    
 79     jmp sret
 80 
 81 charshow:                       ; 显示栈中的内容
 82     mov bx, 0b800h
 83     mov es, bx
 84     mov al, 160
 85     mov ah, 0    
 86     mul dh
 87     mov di, ax
 88     add dl, dl
 89     mov dh, 0
 90     add di, dx
 91 
 92     mov bx, 0
 93 
 94 charshows:
 95     cmp bx, top
 96     jne noempty
 97     mov byte ptr es:[di], ' '    
 98     jmp sret
 99 
100 noempty:
101     mov al, [si][bx]
102     mov es:[di], al
103     mov byte ptr es:[di+2], ' '
104     inc bx
105     add di, 2
106     jmp charshows
107 
108 sret:    
109     pop es
110     pop di
111     pop dx
112     pop bx
113     ret
114 
115 code ends
116 end start

● 代码,从硬盘读取数据

 1 assume cs:code
 2 
 3 code segment
 4 start:    
 5     mov ax, 0
 6     mov es, ax
 7     mov bx, 200h    ; es : bx 指向接收数据的内存区
 8 
 9     mov al, 1       ; 要读取的扇区数,3.5 英寸盘一个扇区 512 Byte
10     mov ch, 0       ; 磁道号,从0开始
11     mov cl, 1       ; 扇区号,从1开始
12     mov dl, 1       ; 驱动器号,0:软驱A,1:软驱B,硬盘从 80h 开始,80h:硬盘C,81h:硬盘D
13     mov dh, 0       ; 磁头号,对于软盘即面号
14     mov ah, 2       ; int 13h 的 2 号子程序,读取数据
15     int 13h         ; 读取硬盘,操作成功:ah 为 0,al 为 读取的扇区数;操作失败:ah 为 出错代码
16                         
17 return:    
18     mov ax, 4c00h
19     int 21h
20 
21 code ends
22 end start

● 代码,内存数据写入硬盘

 1 assume cs:code
 2 
 3 code segment
 4 start:    
 5     mov ax, 0
 6     mov es, ax
 7     mov bx, 200h    ; es : bx 指向写入磁盘的数据的内存区
 8 
 9     mov al, 1
10     mov ch, 0
11     mov cl, 1
12     mov dl, 1
13     mov dh, 0
14     mov ah, 3       ; int 13h 的 3 号子程序,写入数据
15     int 13h         ; 写入硬盘
16     
17 return:
18     mov ax, 4c00h
19     int 21h
20 
21 code ends
22 end start

猜你喜欢

转载自www.cnblogs.com/cuancuancuanhao/p/9688290.html