CALL和RET都是转移指令,它们都会修改IP,或者同时修改CS和IP,两个指令配合使用用来实现子程序

一:RET与RETF
RET
将栈中的数据,放到IP中,从而实现修改IP,达到近转移
RETF
将栈中的数据,放到CS和IP中,从而实现修改CS和IP,达到远转移

注意ret与jmp的区别,jmp可以通过标号,内存,寄存器三种方式实现转移,而ret是通过栈来实现转移

由于是使用栈中的数据,所以执行RET或者RETF的时候,会触发出栈操作(等同于POP),在8086这种16位CPU下,执行RET的时候会有下面两步操作

将栈顶的两个字节弹出,放到IP寄存器中
(IP)=(SS*16+SP)
栈顶位置向下降2个字节
SP=SP+2

同理,执行RETF的时候,会执行下面四个步骤(只是多出了CS)

将栈顶的两个字节弹出,放到IP寄存器中
(IP)=(SS*16+SP)
栈顶位置向下降2个字节
SP=SP+2
将栈顶的两个字节弹出,放到CS寄存器中
(CS)=(SS*16+SP)
栈顶位置继续向下降2个字节
SP=SP+2

由此可见,在栈中如果存放CS和IP,那么IP是处于低地址,而CS是处于高地址的

注意:8086是16位结构,所以+2,32位CPU则是+4

下面的代码会让CPU从代码段10000的物理地址执行指令

mov ax,1000H
push ax
mov ax,0
push ax
retf

二:CALL
call指令会分两个步骤

1.将当前的ip或者cs/ip压入栈保存
2.转移

1.call 标号
下面的代码会将当前IP的值压入栈

call abc;此处会push ip
mov ax,0
abc mov bx,0

1.call far ptr 标号
下面的代码会将当前CS和IP的值压入栈

call far ptr abc;先push cs,再push ip,注意顺序
mov ax,0
abc mov bx,0

三.CALL和RET配合

简单总结就是一句话,CALL将当前执行位置暂存(入栈),执行完毕之后,RET从栈中取出数据,返回之前执行的位置