CALL和RET指令
call和ret指令都是转移指令,它们都修改IP,或同时修改CS和IP,它们经常被同时用于实现子程序的设计
ret和retf
ret指令用栈中的数据,修改IP的内容,从而实现近转移
retf指令用栈中的数据,修改CS和IP的内容,从而实现远转移
如果我们用汇编语法来解释ret和retf指令,则:
- CPU执行ret指令时,相当于进行:
- pop IP
- CPU执行retf指令时,相当于进行:
- pop IP
- pop CS
call指令
CPU执行call指令,进行两步操作:
- 将当前的IP或CS和IP压入栈中
- 转移
- call指令不能实现短转移,除此之外,call指令实现转移的方法和jmp指令的原理相同
依据位移进行转移的call指令
- call标号(将当前的IP压栈后,转到标号处执行指令
- CPU执行“call 标号"时,相当于进行:
push IP
jmp near ptr 标号
转移的目的地址在指令中的call指令
- "call far ptr 标号"实现的是段间转移
- CPU执行"call far ptr“时,相当于进行:
push CS
push IP
jmp far ptr 标号
转移地址在寄存器中的call指令
- 指令格式:call 16位 reg
- 用汇编语法来种格式的call指令,相当于进行:
push IP
jmp 16位 reg
转移地址在内存中的call指令
转移地址在内存中的call指令有两种格式:
call word ptr内存单元地址:
- 用汇编语法来解释此种格式的call指令,则:
push IP
jmp word ptr 内存单元地址
- 比如,下面的指令:
mov sp,10h
mov ax,0123h
mov ds:[0],ax
call word ptr ds:[0]
- 执行后,(IP)=0123H,(sp)=0EH
call dword ptr 内存单元地址:
- 用汇编语法来解释此种格式的call指令:
- CPU执行"call dword ptr 内存单元地址时,相当于进行:
push CS
push IP
jmp dword ptr 内存单元地址
- 比如,下面的指令:
mov sp,10h
mov ax,0123h
mov ds:[0],ax
mov word ptr ds:[2],0
call dword ptr ds:[0]
- 执行后,(CS)=0,(IP)=0123H,(SP)=0CH
call和ret配合使用
assume cs:code
code segment
start: mov ax,1
mov cx,3
call s
mov bx,ax
mov ax,4c00h
int 21h
s: add ax,ax
loop s
ret
code ends
end start
我们来分析一下CPU执行这个程序的主要过程
- CPU将call s指令的机器码读入,IP指向了call s后的指令 mov bx,ax,然后COU执行call s指令,将当前的IP值(指令mov bx,ax的偏移地址)压栈,并将IP的值改变为标号s处的偏移地址
- CPU从标号s处开始执行指令,loop循环完毕后,(ax)=8
- CPU将ret指令的机器码读入,IP指向了ret指令后的内存单元,然后CPU执行ret指令,从栈中弹出一个值(即call s先压入的mov bx,ax指令的偏移地址)送入IP中。则CS:IP指向指令mov bx,ax
- CPU从mov bx,ax开始执行指令,直至完成
模块化程序设计
从上面我们看到,call与ret指令共同支持了汇编语言编程中的模块化设计,在世界编程中,程序的模块化是必不可少的,因为现实的问题比较复杂,对现实问题进行分析时,把它转化成为相互联系,不同层次的子问题,是必须的解决方法,而call与ret指令对这种分析方法提供了程序实现上的支持,利用call和ret指令,我们可以用简捷的方法,实现多个相互联系,功能独立的子程序来解决一个复杂的问题