call和ret指令
call和ret都是转移指令,都修改IP,或同时修改CS和IP。
ret和retf
- ret 指令用栈中数据,修改IP的内容,从而实现近转移
- retf 指令用栈中数据,修改CS和IP的内容,从而实现远转移
执行ret指令时,cpu执行以下2部操作:
- ip=ss*10H+sp
- sp=sp+2
相当于pop ip
执行retf指令时,进行下面4部操作:
- ip=ss*10H+sp
- sp=sp+2
- cs=ss*10H+sp
- sp=sp+2
相当于pop ip ;pop cs
call指令
执行call指令时,进行2部操作:
- 将当前ip或cs和ip压栈
- 转移
call不能实现短转移,除此之外,call实现转移的方法和jmp相同:
-
call 标号
:将当前ip压栈后,转到标号处执行,相当于:
push ip
jmp near ptr 标号
-
call far ptr 标号
:实现段间转移,相当于:
push cs
push ip
jmp far ptr 标号
-
call 16位寄存器
:相当于:
push ip
jmp 16位寄存器
-
call word ptr 内存单元地址
,相当于:
push ip
jmp word ptr 内存单元地址
-
call dword ptr 内存单元地址
,相当于:
push cs
push ip
jmp dword ptr 内存单元地址
mul指令
mul是乘法指令,要注意以下两点:
- 两个相乘的数:要么都是8位,要么都是16位。如果是8位,一个放在al,一个放在8位寄存器或内存字节单元中;若是16位,一个在ax,一个在16位寄存器中。
- 结果:如果是8位乘法,结果默认放在ax中;如果是16位,结果高位放在dx,低位放在ax。
解决除法溢出的方法:
X/N = int( H/N)65536 + [rem( H/N )65536 + L ] / N
X:被除数,N:除数,H:高16位,L:低16位,int:取商,rem:取余数
标志寄存器
ZF标志(zero flag)
flag第6位是ZF,零标志位。它记录执行相关指令后,其结果是否为0。为0则zf=1,否则zf=0。
注意:8086中,有些指令是影响flag的,比如:add、sub、mul、div、inc、or、and等,它们大多是运算指令(逻辑或算数运算);有一些则对flag没影响,如:mov,push,pop等,大多是传送指令。
PF标志(Parity flag)
flag第2位是PF,奇偶标志位。看执行结果的所有bit位中1的个数是否是偶数。是偶数则pf=1,否则pf=0。
可以理解成1偶标志位。
SF标志位(Sign Flag)
flag第7位是SF,符号标志位。记录相关指令执行后结果是否为负。如果为负,sf=1;否则sf=0
注意:sg是cpu默认将数据当成有符号运算结果的记录。如果我们将数据当做无符号时,sf时没有意义的,虽然相关指令可能影响了它的值。是不是有符号运算取决于我们。
CF标志位(Carry Flag)
flag第0位是CF标志位。一般情况下,在进行无符号数运算时,它记录了运算结果的最高有效位向更高位的进位值,或借位值。
inc和loop指令不影响cf
OF标志位(Overflow Flag)
flag第11位是OF,溢出标志位。记录了有符号运算的结果是否溢出。有溢出of=1,否则of=0;
注意和CF的区别:
cf是对无符号数运算有意义的标志位
of是对有符号数运算有意义的标志位
adc指令
adc是带进位加法指令,它利用了CF位上记录的进位值。(add +carry --> adc)如:
adc ax,bx
实现的功能是ax=ax+bx+cf
。
cpu提供adc的目的,就是来进行加法的第二步运算的。
sbb指令
sbb是带借位减法指令(sub borrow),利用cf记录的借位值。
sbb ax,bx
实现的功能是ax=ax-bx-cf
。
cpu提供dbb的目的,就是来进行减法的第二步运算的。
cmp指令
cmp是比较指令,相当于减法指令,只是不保留结果。cmp会对flag产生影响。如:
cmp ax,ax
做ax-ax
运算,但并不在ax中保存,仅影响flag。
进行·cmp ax,bx·比较后,通过flag可以看出比较结果
- zf=1:ax=bx
- cf=1:ax<bx
- cf=0:ax>=bx
- cf=0且zf=0:ax>bx
- cf=1或zf=1:ax<=bx
注意:单纯的看sf的值不能判断结果的正负,因为可能会发生溢出。
而通过sf和of的值可以判断。
- sf=1,of=0:没发生溢出,实际结果负,则逻辑结果也为负
- sf=0,of=0:同上,逻辑结果非负
- sf=1,of=1:有溢出,则实际与逻辑相反,逻辑为正。
- sf=0,of=1:实际结果非负,又of=1,则结果非0,所以实际为正,逻辑结果为负。
条件转移指令
通常配合cmp,由cmp先进行比较,改变了flag中的值,条件转移指令根据flag中的值执行。
下面根据无符号数的比较进行转移的有:
指令 | 含义 | 条件 |
---|---|---|
je | 等于则转移 | 由 zf=1 则转移 |
jne | 不等于则转移 | zf=0 |
jb | 低于则转移 | cf=1 |
jnb | 不低于则转移 | cf=0 |
ja | 高于则转移 | cf=0 且 zf=0 |
jna | 不高于则转移 | cf=1 或 zf=1 |
DF标志和串传送指令
flag第10位是DF,方向寄存器。在串处理指令中,控制每次操作后si、di的增减
- df=0:每次操作后si、di递增
- df=1:每次操作后si、di递减
movsb指令
格式:movsb
相当于:
mov es:[di],byte ptr ds:[si];(8086不支持这样的命令,这里只是描述)
if df = 0:
inc si
inc di
elif df = 1:
dec si
dec di
movsw
类似上面,就是si,di 每次加或减2
movsb
和movsw
进行的是串传送的一个步骤,通常配合rep
使用,如:
rep movsb
,相当于:
s:movsb
loop s
可见rep
是根据cx的值,重复执行后面的串传送指令。
- cld指令:可以将df置0
- std指令:可以将df置1
pushf和poopf
pushf功能是将标志寄存器的值压栈,popf是从栈中弹出数据给标志寄存器中。
通过pushf和popf,可以直接访问flag
网友评论