一、基本知识:
对于一个汇编程序员来说,CPU中的主要部件是寄存器。寄存器是CPU中程序员可以用指令读写的部件;程序员通过改变各种寄存器中的内容来实现对于CPU的控制。对于不同的CPU,寄存器个数、结构是不相同的。
8086CPU中有14个寄存器,每个寄存器都有一个对应的名称:AX、BX、CX、DX、SI、DI、SP、BP、IP、CS、SS、DS、ES、PSW。
8086CPU中所有的寄存器都是16位的,可以存放两个字节。
但是只有AX、BX、CX、DX这4个寄存器可以分为两个可独立使用的8位寄存器来使用;其他寄存器都不行!
二、通用寄存器:
数据寄存器:(AX、BX、CX、DX)
基本介绍:
AX、BX、CX、DX这4个寄存器通常用来存放一般性的数据。
因为8086CPU的上一代CPU中的寄存器都是8位的,为了保证兼容,使得原来基于上代CPU编写的程序稍加修改就可以在8086CPU上运行,故8086CPU的 AX、BX、CX、DX这4个寄存器都可以分为两个可独立使用的8位寄存器来使用。(注意:但是仅仅限于这四个寄存器,其他的寄存器都不能分成高低8位来使用。)
(以寄存器AX为例)AX的低八位构成了AL寄存器,高八位构成了AH寄存器;这两个寄存器都是可以分别独立使用的8位寄存器。
关于使用的一点注意:(以寄存器AX为例,其他数据寄存器也一样!)
mov ah,0
mov al,200
add al,60
200+60=260;但是因为al是一个8位的寄存器,所以它会发生溢出,所以在运算之后在al中实际存储的值是260-256=4;那么问题来了,溢出的那一位是否会存储在ah中呢?使用代码验证一下!
检验代码:
DATAS SEGMENT
;此处输入数据段代码
DATAS ENDS
STACKS SEGMENT
;此处输入堆栈段代码
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX
;此处输入代码段代码
mov ah,0
mov al,200
add al,60
mov dl,ah
add dl,48
mov ah,2
int 21h
MOV AH,4CH
INT 21H
CODES ENDS
END START
通过运行结果,我们可以发现那溢出的一位并没有存储在寄存器ah中,因此我们可以得出结论——单独使用寄存器al和寄存器ah时;他们均是作为一个8位独立的寄存器来使用的;彼此互不干扰。
但是当使用ax时就不一样了!
DATAS SEGMENT
;此处输入数据段代码
DATAS ENDS
STACKS SEGMENT
;此处输入堆栈段代码
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX
;此处输入代码段代码
mov ax,200
add ax,60
mov bx,ax
call output
MOV AH,4CH
INT 21H
;多位输出函数,入口参数为bx
output proc
push ax;数据入栈区
push cx
push dx
;初始化变量
mov ax,bx;数据放入准备除法
mov cl,10;作为除数
mov ch,0;用于计数便于后续出栈输出
divagain:;除法数字剥离部分
cmp ax,0;判断是否已经除尽
je divover
inc ch;计数器加1
div cl
push ax;入栈,提取的时候取用ah部分,存储余数(低位优先)
mov ah,0;调整ax
jmp divagain;再次除法剥离数字
divover:;出栈输出部分
cmp ch,0;判断数字是否已经出尽
je outputover
pop ax;取用ah部分
mov dl,ah;输出部分
add dl,48
mov ah,2
int 21h
dec ch
jmp divover
outputover:;收尾部分
pop dx
pop cx
pop ax;数据出栈区
ret
output endp
CODES ENDS
END START
因此我们可以知道使用ax寄存器时,al寄存器和ah寄存器是作为一个整体,彼此不再独立使用!
如果对于图中的多位输出函数——output不太理解的话;可以看我的往期内容,点击下方链接直达!
8086汇编语言:多位数据进行输出(👈点击这里(*^_^*)!)
①Ax(累加寄存器):
首先,AX寄存器作为一个数据寄存器,所以可以在AX寄存器中存放普通的数据,你可以把它作为一个整体使用,存放16位的数据;你可以把它“掰开”来用,分成低八位AL和高八位AH,分别单独存储8位数据。(此时AL和AH的是相互独立的,彼此不受影响,不明白的看上面的论证!)
AX寄存器除此之外,参与运算的频率是相当的高!
——除法运算:div指令
除法指令分为8位和16位两种,被除数默认放置在AX或者AX和DX中,除数放置在一个寄存器或者内存单元中:
-
除数为8位,被除数则为16位,默认放置在AX中。运算过后,AL存储除法的商,AH存放除法的余数。
-
除数为16位,被除数则为32位,默认放置在AX和DX中;其中DX存放高16位,AX存放低16位。运算过后,AX存储除法的商,DX存储除法的余数。
mov ax,10
mov dl,2
div dl
——乘法运算:mul指令
乘法指令也分为8位和16位两种,其中一个因数默认放置在AL或者AX中,另一个因数放置在寄存器中或者内存单元中:
-
因数都是8位时,其中一个因数默认放置在AL中;运算过后,运算的结果放置在AX中。
-
因数都是16位时,其中一个因数默认放置在AX中;运算过后,运算结果的高16位放置在DX中,低16位放置在AX中。
mov al,100
mov bl,10
mul bl
②BX(基址寄存器):
首先,BX寄存器作为一个数据寄存器,所以可以在BX寄存器中存放普通的数据,你可以把它作为一个整体使用,存放16位的数据;你可以把它“掰开”来用,分成低八位BL和高八位BH,分别单独存储8位数据。(此时BL和BH的是相互独立的,彼此不受影响,不明白的看上面的论证!)
BX寄存器除此之外,还可以表示偏移地址!
对于内存空间的访问,我们通过DS中给出的段地址以及“[...]”给出的偏移地址来确定;但是我们在未了解BX之前只能在“[...]”中置入常量来使用(譬如:mov al,[0]);这样的使用方式有着诸多限制;但是在引入BX之后,我们可以使用譬如mov al,[BX]