一、参考
二、正文
可以修改IP,或者同时修改CS和IP的指令统称为转移指令
转移指令就是可以控制CPU执行内存中某处代码的指令
2.2 CALL和RET指令
call 和 ret指令都是转移指令,都修改IP, 或者同时修改CS和IP,它们经常被共同用于实现子程序的设计。
2.2.1 ret和retf
ret指令用栈中的数据,修改IP的内容,实现近转移;
retf指令用栈中的数据,修改CS和IP的内容,从而实现远转移;
CPU执行ret指令,相当于进行:
pop IP
实际变更为:
(IP) = ( (ss)*16 + (sp) )
(sp) = (sp) + 2
CPU执行retf指令,相当于进行:
pop IP
pop CS
实际变更为:
(IP) = ( (ss)*16 + (sp) )
(sp) = (sp) + 2
(CS) = ( (ss)*16 + (sp) )
(sp) = (sp) + 2
2.2.2 call
CPU执行call指令时候,进行两步操作:
(1)将当前的IP或者CS和IP压入栈中;
(2)转移
call指令不能实现短转移
2.2.3 call和ret配合使用
2.3 模块化程序设计
call和ret指令共同支持了汇编语言编程中的模块化设计,在实际的编程中,程序的模块化必不可少,
因为现实问题比较复杂,对现实问题进行分析,需要将其转化成为相互联系、不同层次的子问题,这是必须解决的方式,利用call和ret指令,可以用简洁的方法,实现多个相互联系、功能独立的子程序,用于解决一个复杂的问题。
2.3.2 寄存器冲突
子程序中使用的寄存器,很可能在主程序中也要使用,造成了寄存器使用上的冲突
如何避免这种冲突呢?可能存在以下两个方案:
(1)在编写子程序的程序时候,注意查看子程序中有没有用到会产生冲突的寄存器,如果有,调用者使用别的寄存器;
(2)在编写子程序时候,不要使用会产生冲突的寄存器
分析两个方案的可行性:
(1)这将给调用子程序的程序的编写造成很大的麻烦,因为必须要小心检查子程序中是否有将产生冲突的寄存器,例如:如果子程序中使用了寄存器bx和cx,则主程序(调用者)不能使用bx, cx寄存器
(2)该方案不能实现,因为编写子程序的时候,无法知道将来的调用情况
上面的设想都不可行,我们希望:
(1)编写调用子程序的程序的时候,不必关心子程序到底使用了哪些寄存器;
(2)编写子程序的时候,不必关心调用者使用了哪些寄存器;
(3)不会发生寄存器冲突
解决问题的简洁方法是:在子程序开始将子程序中所有用到的寄存器的内容都保存起来,在子程序返回前再恢复,可以使用栈来保存寄存器中的内容
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。