汇编 (八) CALL 和 RET 指令
call 和 ret 都是转移指令,都修改IP,或同时修改 CS和IP.
1.1 ret 和 retf
CPU在执行ret指令的时候,进行下面2步操作:
(IP)=((ss)*16+(sp))(sp)=(sp)+2
相当于进行pop IP.
举例:
ret指令执行后,(IP)=0; CS:IP指向代码段的第一条指令。
CPU在执行retf指令的时候,进行下面4步操作:
(IP)=((ss)*16+(sp))(sp)=(sp)+2(CS)=((ss)*16+(sp))(sp)=(sp)+2
相当于:
pop IP
pop CS
举例:
retf指令执行之后,CS:IP指向代码段的第一条指令。
1.2 call 指令
CPU执行call指令时,进行两步操作:
将当前的 IP 或 CS和IP 压入栈中。 (这是记录,为了能够回来。)转移
1.2.1 依据位移进行转移的call指令
格式:
call 标号 (将当前IP压栈后,转到标号处执行指令)
CPU执行如下操作:
1.(sp)=(sp)-2 //栈向小伸展,腾出空间((ss)*16+(sp))=(IP) //将旧IP入栈,相当于 push IP2.(IP)=(IP)+16位位移 //转移到新IP处,相当于 jmp near ptr 标号。
1.2.2 转移的目的地址在指令中的call指令
格式:
call far ptr 标号 实现段间转移
CPU执行如下操作:
1. (sp)=(sp)-2 //栈向小生长,腾出空间((ss)*16+(sp))=(CS) //CS入栈,相当于,push CS(sp)=(sp)-2((ss)*16+(sp))=(IP) //IP入栈,相当于,push IP. 对当前CS IP进行记录2. (CS)=标号所在段的段地址 (IP)=标号所在段的偏移地址 //赋予新的CS IP,进行 jmp far ptr 标号
1.2.3 转移地址在寄存器中的call指令
格式:
call 16位reg
功能:
1.(sp)=(sp)-2((ss)*16+(sp)) = (IP) //入栈,记录旧IP ,相当于push IP2.(IP)=(16位reg) //赋予新IP ,相当于 jmp 16位reg
1.2.4 转移地址在内存中的call指令
CPU相当于执行
push IPjmp word ptr 内存单元地址
举例:
mov sp,10hmov ax,0123hmov ds:[0],axcall word ptr ds:[0]
执行后:
(IP) = 0123H
(sp)=0EH -->栈需要记录IP,需要向小生长空间,则sp=sp-2
CPU相当于执行:
push CSpush IPjmp dword ptr 内存单元地址
举例:
mov sp,10hmov ax,0123hmov ds:[0],axmov word ptr ds:[2],0call dword ptr ds:[0]
执行后,
(CS)=0,(IP)=0123H,
(sp)=0CH ---->栈需要记录CS & IP,需要向小生长两次,sp=sp-2-2
1.3 call 和 ret 的配合使用
1.4 mul指令
mul乘法指令:
1.两个相乘的数,要么是8位,要么是16位:
2.结果:
格式:
mul reg
mul 内存单元
其中,内存单元可以用不同的寻址方式给出。
mul byte ptr ds:[0] //含义:(ax)=(al)*((ds)*16+0) 其中一个值默认在al中。
mul word ptr [bx+si+8] //含义:(ax)=(ax)*((ds)*16+(bx)+(si)+8)结果的低16位;(dx)=(ax)*((ds)*16+(bx)+(si)+8)结果的高16位;