在MASM 5(Microsoft Micro Assembler)的彙編體系中,子程序(Procedures)的定義和調用是非常重要的,就像C、pascal等的函數和方法一樣;且對深入理解高級語言裏函數的底層原理極其重要,如函數的參數傳遞、棧、變長參數等。但在網絡上許多教程及代碼都極其不規範且語焉不詳;有的代碼雖然可以運行,但都存在潛在Bug。我仔細閱讀了Microsoft的相關手冊後,像子程序的嚴格定義及調用分享如下:
一、子程序(Procedure)的定義和調用
方式1
定義:
label Proc [Far | Near]
...(語句)
Ret[n]
label Endp
調用:
Call label
方式2
定義:
label:
...(語句)
Retn[n]
調用:
Call Near Ptr label
方式3
label:
...(語句)
Retf[n]
調用:
Call Far Ptr label
注意事項:
1、方式1是官方推薦的,Call時不用關心near(段內調用)和far(跨段調用),編譯器會根據定義自動生成near call或far call。
2、方式2和方式3定義中Retn和Retf一定要與Call Near Ptr和Call Far Ptr對應,否則棧數據會被破壞
3、從MASM 6後還可通過Proc的定義中聲明參數(相當於C語言中函數的定義)。
4、ret、retn、retf後面的n(整數)表示調用返回後sp還需要加n(即還需要彈出n個字節),主要用於傳遞參數。
二、Call的語法補充
語法:Call oprd(操作數),可分爲直接調用或間接調用
1、直接調用
oprd爲子程序的地址,則可通過call [near或far]調用。
2、間接調用
oprd爲保存子程序的地址的寄存器或內存地址:
段內調用(near call)則可通過call bx或call word ptr [bx+si+20];
跨段調用(far call)則可通過call dword ptr [bx+si+20];