ret 用栈中数据改IP内容,近转移
retf用栈中数据同时改CS,IP,远转移
用汇编解释
- ret -> pop ip
- retf -> pop ip; pop cs
- push先修改sp再放数据,pop先取数据再修改sp
call指令
当执行call指令时,进行两步操作:
1)将当前的IP或CS和IP压入栈中
2)转移
call指令不能实现短转移,它的书写格式同jmp指令
- 依据标号进行转移的call指令
语法格式:call 标号
汇编解释:(1) push IP (2) jmp near ptr 标号 - 依据目的地址在指令中的call指令
语法格式:call far ptr 标号
汇编解释:(1) push CS (2) push IP (3) jmp far ptr 标号 - 转移地址在寄存器中的call指令
语法格式:call 16位reg
汇编解释:(1) push IP (2) jmp 16位reg - 转移地址在内存中的call指令
语法格式一:call word ptr 内存单元地址
汇编解释一:(1) push IP (2) jmp word ptr 内存单元地址 - 语法格式二:call dword ptr 内存单元地址
汇编解释二:(1) push CS (2) push IP (3) jmp dword ptr 内存单元地址
检测点10.2
下面的程序执行后,AX中的数值为多少?
assume cs:codesg
codesg segment
start:
mov ax,0 //b8 00 00
call s //e8 01 00
inc ax //40
s:pop ax //58
codesg ends
end start
走到call s 时,IP值已经完成自动增加,此时IP=6
执行call s之后,IP=6 被压入栈
执行pop ax,使得的 (ax)=6
检测点10.3
下面的程序执行后,AX中的数值为多少?
内存地址 机器码 汇编指令
1000:0 b8 00 00 mov ax,0
1000:3 9A 09 00 00 10 call far ptr s
1000:8 40 inc ax
1000:9 58 s: pop ax ;ax=8h
add ax,ax ;ax=10h
pop bx ;bx=1000h
add ax,bx ;ax=1010h
执行call far ptr s时,取IP为8,add ax,ax ax=16
BX=CS=1000H 相加转16进制ax=1010H
检测点10.4
下面的程序执行后,AX中的数值为多少?
内存地址 机器码 汇编指令
1000:0 b8 06 00 mov ax,6
1000:2 ff d0 call ax
1000:5 40 inc ax
1000:6 s: mov bp,sp
add ax,[bp]
call ax后栈顶的数据时0005,ip=0006,[bp]就是栈顶=0005,所以ax=0006+0005=000bh
检测10.5
01,下面程序执行后 , ax 中的值是什么 ?
assume cs:code,ss:stack
stack segment
dw 8 dup(0)
stack ends
code segment
start:
mov ax, stack
mov ss, ax
mov sp, 0010H
mov ds, ax
call word ptr ds:[0EH]
inc ax
inc ax
inc ax
code ends
end start
该题中的程序的数据段和栈段使用了同一段内存 , 也就是说 ds 和 ss 是相同的
执行到 call word ptr ds:[0EH] 的时候 , 具体的流程如下 :
1. CPU取指令 : (call word ptr ds:[0EH])
2. ip自增上述指令的长度 , 指向了下一条指令 (inc ax)
3. 开始执行该指令
3.1. push ip ; 将 ip=15 压入栈
3.2. jmp ds:[0EH]((ip) = ds:[0EH],也就是说程序又从ds:[0EH]中取出数据赋值给 ip
4. 现在其实就开始执行 ip 之前保存的地址的指令了 , 也就是三个 inc ax
5. 因此最终 ax 值为 3
02 下面的程序执行后 , ax 和 bx 的值是什么 ?
assume cs:code,ds:data
data segment
dw 8 dup(0)
data ends
code segment
start:
mov ax, data
mov ss, ax
mov sp, 16
mov word ptr ss:[0], offset s
mov ss:[2], cs
call dword ptr ss:[0]
nop
s:
mov ax, offset s
sub ax, ss:[0CH]
mov bx, cs
sub bx, ss:[0EH]
code ends
end start
mov word ptr ss:[0], offset s把ss的偏移地址保存到ss[0]和ss[1],
mov ss:[2], cs把cs保存到ss[2]和ss[3],
call dword ptr ss:[0]把cs和nop的偏移地址先后压栈,并跳转(ss[0])即s,
所以ax=s的偏移地址-nop的偏移地址=1,bx=cs-cs=0
ret n相当于pop ip;add sp,n
可以在调方法时把参数放进栈,执行完后设置适当的n,使得ret n之后正好把所有参数出栈。
assume cs:code
code segment
start: ;//sp=0000
call f1 ;//sp=FFFE
nop ;//sp=0004
mov sp,0 ;//sp=0000
call f2 ;//sp=FFFE
mov ax,4c00h ;//sp=FFFC
int 21h
f1:
ret 4
f2:
ret -4
code ends
end start