assembly 4
call & ret
ret与retf
ret用栈中数据修改IP内容实现近转移
retf修改CS和IP实现远转移
ret指令操作:
- (IP)=((ss)*16+(sp))
- (sp)+=2
retf指令操作:
- (IP)=((ss)*16+(sp))
- (sp)+=2
- (CS)=((ss)*16+(sp))
- (sp)+=2
由是观之,ret等于执行
pop IP
retf等于执行
pop IP
pop CS
call
格式:call 标号
操作:
- 将当前IP或CS以及IP压入栈
- 转移至标号
call不能短转移,跟jmp一样可以用三种方法获取偏移。
简单来讲call和ret就是高级语言中的调用函数和return。
mul
乘法,与div相似。两数要么都是8位,默认第一个乘数在al寄存器,结果在ax寄存器;要么都是16位,默认第一个乘数在ax。结果高位在dx,低位在ax。
如:
mov al,100
mov bl,10
mul bl ;结果:(ax)=1000
标志寄存器
功能:
-
用来存储相关指令的某些执行结果;
-
用来为 CPU 执行相关指令提供行为依据;
-
用来控制CPU的相关工作方式。
8086中,flag寄存器,16位,分为有效标志位和无效位。
ZF标志位
零校验,检测相关指令执行后结果是否是0,是0则zf=1,不是则zf=0。
例如:
mov ax,1
sub ax,1
;结果是0,此时zf=1
mov ax,1
or ax,0
;结果是1,此时zf=0
在8086中,add,sub,mul,div,and,or这类运算指令会改变标志位,而mov,push,pop这类传送指令不会。
PF标志位
奇偶校验,判断结果bit位中1的个数是否为偶数,是则pf=1,不是则pf=0。
SF标志位
符号校验,判断结果是否为负,实则sf=1,不是则sf=0。
对于同一个二进制数据而言,我们既可以把他当作有符号数,也可以当作无符号数,计算机存储了作为有符号数和无符号数两种情况,sf是在有符号数运算的情况下表示结果的符号。如:
mov al,10000001B
add al,1
执行后, 结果为 10000010B, sf=1, 表示: 如果指令进行的是有符号数运算, 那么结果为负(就是看最高位是不是1)。
CF标志位
记录了进位/借位,比如:
mov al,98H ;1001 1000B
add al,al ;0011 0000B
;超出8位范围,al仅保留8位,进位cf=1
add al,al ;0110 0000B
;未超出8位范围,没有进位,cf=0
mov al,97H
sub al,98H ;cf=1
sub al,al ;cf=0
OF标志位
溢出校验,是否超出对于该数据而言,机器所能表示的范围。
带进位运算adc和sbb
带进位加法,例如adc ax,bx
实现的是(ax)=(ax)+(bx)+cf
带进位减法,例如sbb ax,bx
实现的是(ax)=(ax)-(bx)-cf
cmp指令
操作
比较但是不存储结果,仅根据结果进行标志寄存器的设置。
比如:
mov ax,8
mov bx,3
cmp ax,bx
其中(ax)-(bx)答案是5,据此设置zf=0(不是0),pf=1(二进制为101,bit位1的个数是偶数),cf=0(没有进位)。
cmp ax,bx比较结果对寄存器标志位的影响:
如果( ax)=( bx) 则( ax)-( bx)=0, 所以: zf=1;
如果( ax)≠( bx) 则( ax)-( bx)≠0, 所以: zf=0;
如果( ax)<( bx) 则( ax)-( bx)将产生借位, 所以: cf=1;
如果( ax)≥( bx) 则( ax)-( bx)不必借位, 所以: cf=0;
如果( ax)>( bx) 则( ax)-( bx)既不必借位, 结果又不为0, 所以: cf=0并且 zf=0;
如果( ax)≤( bx) 则( ax)-( bx)既可能借位, 结果可能为0, 所以: cf=1或 zf=1。
由此可以形成对ax,bx大小关系的比较。
各种基于flag寄存器的条件跳转指令
je ;equal
jne ;not equal
jb ;below
jnb ;not below
ja ;above
jna ;not above
以上基于cmp ax,bx后flag寄存器的符号位来比较,决定是否跳转。
IDA Pro中经常见到jz,jnz
,查询后发现跟je,jne
是等价的。