1. 子程序的定义
如同C语言一样,汇编语言也具备结构化的能力。
首先说子程序的定义格式:
子程序名 PROC [NEAR | FAR]
… ;子程序体
子程序名 ENDP
… ;子程序体
子程序名 ENDP
PROC和ENDP是子程序的首尾标识,子程序名必须是相同的,子程序可以分为NEAR近调用和FAR远调用,所谓近调用就是只能在同一段内的其他程序调用,而远待用可以被不同段的程序调用。
2. 子程序的调用
所以,根据NEAR和FAR,也有相应的调用方式,NEAR的子程序调用的时候只需要把偏移量压栈即可,FAR的子程序要把段地址和偏移量压栈(分别压入CS和IP寄存器),然后即可调用。
调用的方式:
CALL DISPLAY |
;DISPLAY是子程序名 |
CALL BX |
;BX的内容是子程序的偏移量 |
CALL WORD1 |
;WORD1是内存字变量,其值是子程序的偏移量 |
CALL DWORD1 |
;DWORD1是双字变量,其值是子程序的偏移量和段值 |
CALL word ptr [BX] |
;BX所指内存字单元的值是子程序的偏移量 |
CALL dword ptr [BX] |
;BX所指内存双字单元的值是子程序的偏移量和段值 |
3. 子程序的返回
当子程序执行完了之后,需要返回到主调指令上下文中,并不像跳转指令那样不会返回,为了实现这个功能,指令系统提供了一条专用指令RET.
RET/RETN/RETF [imm]
子程序的返回在功能上来说是子程序的调用的逆操作,为了与子程序的远/近调用相对应,子程序的返回也分为远返回和近返回。
返回指令在堆栈方面是调用指令的逆操作。
在近类型的子程序中,返回指令RET是近返回,功能是把栈顶的值弹出到指令指针寄存器IP中,SP会被加2。
在远类型的子程序中,返回指令RET是远返回,功能是:先弹出栈顶的值到IP中,再弹出栈顶的值到CS中,SP总共向后移动了4位(当然80386+的CPU是ESP向后移动了两个四位)
如果返回指令后面加入了立即数,那么表示返回地址之后,SP还要增加的偏移量。并不是高级语言中return的值。
在masm5.0+的环境中可以直接使用RETN和RETF来显示告诉编译器本子程序是近返回还是远返回。
RET |
;可能是近返回,也可能是远返回 |
RETN |
;近返回指令 |
RETF |
;远返回指令 |
RET 6 |
;子程序返回后,(SP)←(SP) + 6 |