指令讲解
每日一句诗词
loading...
loading...
指令
div指令
div除法指令,需要注意一下几点
- 除数:有8位和16位两种,存放在reg或内存单元中
- 被除数:默认放在AX或DX和AX中,如果除数为8位被除数则为16位,默认在AX中存放,如果除数为16位被除数则为32位默认在DX和AX中存放DX存放高16位AX存放低16位
- 结果:如果除数为 8 位,则 AL存储除法操作的商,AH 存储除法操作的余数;
如果除数为16位,则AX存储除法操作的商,DX存储除法操作的余数。例如100001/1001
2
3
4
5
6
7div byte ptr ds:[1]
al = (ax)/(ds*16+1)//地位存放商
ah = (ax)%(ds*16+1)//高位存放余
-----------------------------------------
div word ptr es:[1]
ax = (dx*10000H+ax)/(es*16+1)//ax存放商
dx = (dx*10000H+ax)%(es*16+1)//dx存放余 - 首先100001大于65535则需要32位寄存器
- 100小于255但是被除数为32位所以要16位寄存器
1
2
3
4mov dx,1
mov ax,86A1H
mov bx,100
div bx伪指令
- db定义字节型数据
- dw定义字型数据
- dd 是用来定义 dword(doubleword,双字)型数据的。
- dup 是一个操作符,在汇编语言中同 db、dw、dd 等一样,也是由编译器识别处理的符号。它是和 db、dw、dd 等数据定义伪指令配合使用的,用来进行数据的重复。
1
2
3
4db 3 dup (0)
定义了3个字节,它们的值都是0,相当于 db 0,0,0。
db 3 dup (0,1,2)
定义了 9个字节,它们是 0、1、2、0、1、2、0、1、2,相当于 db 0,1,2,0,1,2,0,1,2。jmp指令
- jmp指令无条件转移指令,可以修改ip也可以修改cs和ip
jmp 指令要给出两种信息: - 转移的目的地址
- 转移的距离(段间转移、段内短转移,段内近转移)
jcxz指令
jcxz 指令为有条件转移指令,所有的有条件转移指令都是短转移,在对应的机器码中包含转移的位移,而不是目的地址。对 IP 的修改范围都为:-128~127。loop指令
loop指令为循环指令,所有的有loop指令都是短指令,在对应的机器码中包含转移的位移,而不是目的地址。对 IP 的修改范围都为:-128~127。ret指令
- ret指令用栈中的数据,修改ip的内容,从而实现近转移
- retf指令用栈中的数据,修改ip的内容,从而实现远转移
指令转移的原理
可以修改IP,或同时修改CS和IP的指令统称为转移指令。概括地讲,转移指令就是可以控制CPU执行内存中某处代码的指令。
8086CPU的转移行为有以下几类。 - 只修改IP时,称为[段内转移]{.yellow},比如:jmp ax。
- 同时修改CS和IP时,称为[段间转移]{.yellow},比如:jmp 1000:0。
由于转移指令对IP的修改范围不同,段内转移又分为:短转移和近转移。 - [短转移]{.yellow}IP的修改范围为-128~127。
- [近转移]{.yellow}IP 的修改范围为-32768~32767。
8086CPU的转移指令分为以下几类。 - 无条件转移指令(如:jmp)
- 条件转移指令
- 循环指令(如:loop)
- 过程
- 中断
ret和retf
- ret指令用栈中的数据,修改IP的内容,从而实现近转移;
- retf指令用栈中的数据,修改CS和IP的内容,从而实现远转移。
CUP执行ret指令时,进行下面两步操作
(IP) = ((SS) 16)+SP
(SP) = (SP)+2
CUP执行retf指令时,进行下面四步操作
(CS) = (SS) 16+SP
(SP) = (SP) + 2
(IP) = (SS)* 16+SP
(SP) = (SP)+2
可以看出,如果我们用汇编语法来解释 ret和retf指令,则:
CPU 执行 ret 指令时,相当于进行:
pop IP
CPU 执行 retf指令时,相当于进行:
pop IP
pop CSCall
CPU执行call指令时,进行两步操作:
- 将当前的IP或CS和IP压入栈中;
- 转移。
call 指令不能实现短转移,除此之外,call 指令实现转移的方法和 jmp 指令的原理相
同。
call 标号(将当前的 IP 压栈后,转到标号处执行指令)
CPU 执行此种格式的 call 指令时,进行如下的操作:
(sp)=(sp)-2
(ss)* 16+(sp))=(IP)
(IP)=(IP)+16位位移。
可以看出,如果我们用汇编语法来解释 call指令,则:
CPU 执行 call 指令时,相当于进行:
push IP
CPU 执行 call far ptr指令时,相当于进行:
push IP
push CSmul
因下面要用到,这里介绍一下mul指令,mul是乘法指令,使用mul做乘法的时候,
注意以下两点。
(1) 两个相乘的数:两个相乘的数,要么都是8位,要么都是16位。如果是8位,一个默认放在AL中,另一个放在8位
reg或内存字节单元中;如果是16位,一个默认在AX中,另一个放在 16 位 reg 或内存字单元中。
(2) 结果:如果是8位乘法,结果默认放在 AX 中;如果是 16 位乘法,结果高位默认在DX中存放,低位在AX中放。1
2
3格式如下:
mul reg
mul 内存单元1
2
3
4
5
6
7内存单元可以用不同的寻址方式给出,比如:
mul byte ptr ds:[0]
含义:
(ax)=(al)*((ds)*16+0);
mul word ptr [bx+si+8]
含义:(ax)=(ax)*((ds)*16+(bx)+(si)+8)结果的低 16 位。
(dx)=(ax)*((ds)*16+(bx)+(si)+8)结果的高 16 位。abc指令
adc 是带进位加法指令,它利用了 CF 位上记录的进位值。
指令格式:adc 操作对象1,操作对象2
功能:操作对象1=操作对象1+操作对象2+CF
比如指令adc ax,bx 实现的功能是:(ax)=(ax)+(bx)+ CF1
2
3
4mov ax,2
mov bx,1
sub ax,bx(CF=1)
abc ax,1 ;(ax)+1+CF=2+1+1=4可以看出,adc指令比add指令多加了一个CF位的值。1
2
3
4mov ax,1
add bx,1
add ax,bx ;(CF=0)
abc ax,1 ;(ax)+1+CF=2+1+0=3
为什么要加上CF的值呢?CPU为什么要提供这样一条指令呢?
- 加法可以分两步来进行:
①低位相加;
②高位相加再加上低位相加产生的进位值。;
下面的指令和addax,bx具有相同的结果:编程,计算 1EF000H+201000H,结果放在ax(高16位)和bx(低16位)中。1
2add al,bl
adc ah,bh
先将低 16 位相加,然后将高 16 位和进位值相加。程序如下。1
2
3
4mov ax,001EH
mov bx,0F000H
add bx,1000H
adc ax,0020Hsbb指令
sbb 是带借位减法指令,它利用了CF位上记录的借位值。
指令格式:sbb操作对象1,操作对象2
功能:操作对象1=操作对象1-操作对象2-CF
比如指令 sbb ax,bx 实现的功能是:
(ax)=(ax)-(bx)-CF
sbb 指令执行后,将对 CF 进行设置。利用 sbb 指令可以对任意大的数据进行减法运算。
比如,计算003E1000H-00202000H,结果放在ax,bx中,程序如下::::warning1
2
3
4mov bx,1000H
mov ax,003EH
sub bx,2000H
sbb ax,0020H
乘除ax存放低位dx存放高位
abc和sbb运算ax存放高位,bx存放地位
:::cmp指令
cmp 是比较指令,cmp的功能相当于减法指令,只是不保存结果。cmp 指令执行后,将对标志寄存器产生影响。
其他相关指令通过识别这些被影响的标志寄存器位来得知比较结果。
下面的指令:其实,我们通过cmp指令执行后,相关标志位的值就可以看出比较的结果。1
2
3
4
5
6mov ax,8
mov bx,3
cmp ax,bx
执行后:
(ax)=8,zf=0,pf=1,sf=0,cf=0,of=0。
ZF=0(非零),PF=1(1的个数为偶数),SF(非负),CF(没借位),OF(没溢出)
- 如果 sf=1,而 of=0
of=0,说明没有溢出,逻辑上真正结果的正负=实际结果的正负;
因sf=1,实际结果为负,所以逻辑上真正的结果为负,所以(ah)<(bh)。 - 如果 sf=1,而 of=l:
of=1,说明有溢出,逻辑上真正结果的正负≠实际结果的正负;
因sf=1,实际结果为负。
实际结果为负,而又有溢出,这说明是由于溢出导致了实际结果为负,简单分析下,就可以看出,如果因为溢出导致了实际结果为负,那么逻辑上真正的结果必然为正。
这样,sf=1,of=1,说明了(ah)>(bh)。比较结果的条件转移指令
下面是常用的根据无符号数的比较结果进行转移的条件转移指令。这些指令比较常用,它们都很好记忆,它们的第一个字母都是 j,表示 jump;后面的1
2
3
4
5
6
7指令格式 含义 检测的相关标志位
je 等于则转移 zf=1
jne 不等于则转移 zf=0
jb 低于则转移 cf=1
jnb 不低于则转移 cf=0
ja 高于则转移 cf=0 且 zf=O
jna 不高于则转移 cf=1 或 zf=1
字母表示意义如下。
e:表示equal
ne:表示 not equal
b:表示 below
nb:表示 not below
a:表示above
na:表示 not above
案列1
2
3
4
5
6
7
8
9
10实现:如果ah=bh则ax+ax否则ax加bx
cmp ah,bh
je s
add ah,bh
jmp ok
s:
add ah,ah
ok:
mov ah,4ch
int 21hPushf和Popf
- pushf的功能是将标志寄存器的值压栈,而popf是从栈中弹出数据,送入标志寄存器中。
- pushf和popf,为直接访问标志寄存器提供了一种方法。
:::warning
标志寄存器与标志要分清
:::标志寄存器
ZF标志
flag 的第6位是ZF,零标志位。它记录相关指令执行后,其结果是否为0。如果结果
为0,那么zf=1;如果结果不为0,那么zf=0。1
2
3
4
5
6mov ax,1
sub ax,1
执行后ax为0则ZF = 1
mov ax,2
sub ax,1
执行后ax为1则ZF = 0PF标志
flag 的第2位是PF,奇偶标志位。它记录相关指令执行后,其结果的所有bit位中1的个数是否为偶数。如果1的个数为偶数,pf=1,如果为奇数,那么 pf=0。1
2
3
4
5
6
7
8比如,指令:
mov al,1
add al,10
执行后,结果为00001011B,
其中有 3(奇数)个 1,则 pf=0;
mov al,1
or al,2
执行后,结果为 00000011B,其中有 2(偶数)个 1,则 pf=1;SF标志
flag 的第 7 位是 SF,符号标志位。它记录相关指令执行后,其结果是否为负。如果
结果为负,sf=1;如果非负,sf=0。
计算机中通常用补码来表示有符号数据。计算机中的一个数据可以看作是有符号数,
也可以看成是无符号数。比如: - 00000001B,可以看作为无符号数1,或有符号数+1;
- 10000001B,可以看作为无符号数 129,也可以看作有符号数-127。
CF标志
flag 的第 0 位是 CF,进位标志位。一般情况下,在进行无符号数运算的时候,它记录了运算结果的最高有效位向更高位的进位值,或从更高位的借位值。
对于位数为 N 的无符号数来说,其对应的二进制信息的最高位,即第 N-1 位,就是
它的最高有效位,而假想存在的第 N 位,就是相对于最高有效位的更高位。1
2
3mov al,97h
sub al,98h ;执行后:(al)=FFH,CF=1,CF记录了向更高位的借位值
sub al,al ;执行后:(al)=0,CF=0,CF记录了向更高位的借位值OF标志
flag 的第 11 位是 OF,溢出标志位。一般情况下,OF 记录了有符号数运算的结果是否发生了溢出。如果发生溢出,OF=1;如果没有,OF=0。
一定要注意CF和OF的区别:CF是对无符号数运算有意义的标志位,而OF是对有符号数运算有意义的标志位。
比如:1
2mov al,98
add al,99 - 结果al为197超出了8位寄存器的范围(-128 ~ 127)发生溢出OF=1
- 对于无符号数运算,98+99 没有进位CF=0;对于有符号数运算,98+98发生溢出OF=1add 指令执行后:CF=1,OF=1。对于无符号数运算,0F0H+88H(101111000B) 有进位,CF=1;对
1
2mov al,0F0H
add al,88H
于有符号数运算,0F0H+88H发生溢出,OF=1。add 指令执行后:CF=1,OF=0。对于无符号运算,0F0H+78H(101101000B) 有进位,CF=1;对于1
2mov al,0F0H
add al,78H
有符号数运算,0F0H+78H不发生溢出,OF=0。 - 我们可以看出,CF 和OF所表示的进位和溢出,是分别对无符号数和有符号数运算
而言的,它们之间没有任何关系。DF标志
flag的第10位是DF,方向标志位。在串处理指令中,控制每次操作后si、di的增减。
df=0 每次操作后 si、di 递增;
df=1 每次操作后 si、di 递减。 - 如果df=0则:(si)=(si)+1 (di)=(di)+1
- 如果df=1则:(si)=(si)-1 (di)=(di)-1
- cld指令:将标志寄存器的df位置0
- std指令:将标志寄存器的df位置1
用汇编语言描述movsb了解movsb后复制字符串就变得简单多了1
mov es:[di],byte ptr ds:[si] ;汇编并不支持这种书写,这只是个描述
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20assume cs:codes,ds:datas
datas segment
db 'Welcome to masm!'
db dup (0)
datas ends
codes segment
mov ax,datas
mov ds,ax
mov si,0
mov es,ax
mov di,16
mov cx,16
cld ;将df设位0,正向传输
rep movsb
codes ends
enddebug对标志位的表示
| 标志 | 值为1 | 值为零 |
|-|-|-|
| OF | OV | NV |
| SF | NG | PL |
| ZF | ZR | NZ |
| PF | PE | PO |
| CF | CY | NC |
| DF | DN | UP |
Comment