本文已参与「新人创作礼」活动,一起开启掘金创作之路。
目录
call 和 ret都是转移指令,它们都修改IP,或同事修改CS和IP
10.1 ret和retf
ret指令用栈中的数据,修改IP的内容,从而实现近转移!
CPU执行ret指令时进行如下操作
retf用栈中的数据,修改CS和IP的内容,从而实现远转移
CPU执行ret相当于pop IP
执行retf相当于pop IP
pop CS
ret测试
这边将ax的值推入栈中
ret相当于pop IP
即把ax的值给了IP(0)
后执行mov ax ,4c00h
int 21h
程序终止
retf测试
相当于pop IP
pop cs
10.2 call指令
call 指令经常与ret指令配合使用,因此CPU执行call指令,进行两步操作:
call 标号
16位位移
10.3 依据位移进行转移的call指令
E8是call的机器码
05是偏移
(1)当前IP压入栈
注意:此处IP是读取完call s指令后,为05h
(2)转到标号处执行指令
10.4转移的目的地址在指令中的call指令
之前的call只是相对于当前IP的转移位移
call far ptr 标号:实现的是段间转移
CPU执行的操作
10.5转移地址在寄存器中的call指令(实现短转移)
call 16位寄存器
10.6 转移地址在内存中的call指令
call word ptr 内存单元地址(IP,近转移)
call dword ptr 内存单元地址(CS和IP,段间跳转)
高16位存放CS,低16位存放IP
10.7 call和ret的配合使用
bx=8
10.7call和ret的配合使用2
小结:
可以写一个具有一定功能的程序段,我们称之为子程序,在需要的时候,用call指令转去执行。子程序调用完之后再ret返回接着call指令向下执行
在C语言中实例使用:
调用printf函数
此时CPU跳转至love函数
love函数的结尾
返回至call指令接下来执行指令
10.8 mul指令
相乘的两个数:要么都是8位,要么都是16位
结果的存放
格式
mul reg
mul 内存单元
ATTENTION:
如果是八位乘上十六位
这边建议把八位强制转换成16位(填充0)
eg:
8位乘8位
8位乘16位(8位填充乘成16位)
Conclusion:
call和ret指令共同支持了汇编的模块化设计。程序的模块化设计必不可少
10.10 参数和结果传递的问题
一个参数
可用寄存器bx来存放参数
结果存放到dx和ax中
N个参数
可将批量数据存放到内存中
eg
放到内存中
10.12寄存器冲突的问题
实例
jcxz检验循环是否完成
若完成了直接跳转至ok,ret返回call接下来执行指令