汇编语言PROC伪指令:过程定义
label PROC [attributes] [USES reglist], parameter_list
Label 是按照《LABEL伪指令》一节中说明的标识符规则、由用户定义的标号。Attributes 是指下述任一内容:[distance] [langtype] [visibility] [prologuearg]
下表对这些属性进行了说明。属性 | 说明 |
---|---|
distance | NEAR 或 FAR。指定汇编器生成的 RET 指令(RET 或 RETF)类型 |
langtype | 指定调用规范(参数传递规范),如 C、PASCAL 或 STDCALL。能覆盖由 .MODEL 伪指令指定的语言 |
visibility | 指明本过程对其他模块的可见性。选项包括 PRIVATE、PUBLIC (默认项)和 EXPORT。若可见性为 EXPORT,则链接器把过程名放入分段可执行文件的导出表。EXPORT 也使之具有了 PUBLIC 可见性 |
prologuearg | 指定会影响开始和结尾代码生成的参数 |
参数列表
PROC 伪指令允许在声明过程时,添加上用逗号分隔的参数名列表。代码实现可以用名称来引用参数,而不是计算堆栈偏移量,如 [ebp+8]:
label PROC [attributes] [USES reglist],
parameter_1,
parameter_2,
...
parameter_n
label PROC [attributes], parameter_1, parameter_2, ..., parameter_n
每个参数的语法如下:paramName: type
ParamName 是分配给参数的任意名称,其范围只限于当前过程(称为局部作用域(local scope))。同样的参数名可以用于多个过程,但却不能作为全局变量或代码标号的名称。Type 可以在这些类型中选择:BYTE、SBYTE、WORD、SWORD、DWORD、SDWORD、FWORD、QWORD 或 TBYTE。此外,type 还可以是限定类型(qualified type),如指向现有类型的指针。
下面是限定类型的例子:
PTR BYTE PTR SBYTE
PTR WORD PTR SWORD
PTR DWORD PTR SDWORD
PTR QWORD PTR TBYTE
【示例 1】AddTwo 过程接收两个双字数值,用 EAX 返回它们的和数:
AddTwo PROC, val1:DWORD, val2:DWORD mov eax,val1 add eax,val2 ret AddTwo ENDPAddTwo 汇编时,MASM 生成的汇编代码显示了参数名是如何被转换为 EBP 偏移量的。由于使用的是 STDCALL,因此 RET 指令附加了一个常量操作数:
AddTwo PROC push ebp mov ebp, esp mov eax, dword ptr [ebp+8] add eax, dword ptr [ebp+OCh] leave ret 8 AddTwo ENDP用指令 ENTERO, 0 来代替下面的语句,AddTwo 过程也一样正确:
push ebp
mov ebp,esp
FillArray PROC,
pArray:PTR BYTE
...
FillArray ENDP
Swap PROC, pValX:PTR DWORD, pValY:PTR DWORD Swap ENDP【示例 4】Read_File 过程接收一个字节指针 pBuffer,有一个局部双字变量 fileHandle,并把两个寄存器保存入栈(EAX 和 EBX):
Read_File PROC USES eax ebx,
pBuffer:PTR BYTE
LOCAL fileHandle:DWORD
mov esi,pBuffer
mov fileHandle,eax
...
ret
Read_File ENDP
Read_File PROC push ebp mov ebp,esp add esp, OFFFFFFFCh ;创建 fileHandle push eax ;保存 EAX push ebx ;保存 EBX mov esi, dword ptr [ebp+8] ; pBuffer mov dword ptr [ebp-4],eax ; fileHandle pop ebx pop eax leave ret 4 Read_File ENDP注意:尽管 Microsoft 没有采用这种方法,但 Read_File 生成代码的开始部分还可以是这样的:
Read_File PROC
enter 4,0
push eax
(etc.)
由 PROC 修改的 RET 指令
当 PROC 有一个或多个参数时,STDCALL 是默认调用规范。假设 PROC 有 n 个参数,MASM 将生成如下入口和出口代码:
push ebp
mov ebp,esp
...
leave
ret (n*4)
指定参数传递协议
一个程序可以调用 Irvme32 链接库过程,反之,也可以包含能被 C++ 程序调用的过程。为了提供这样的灵活性,PROC 伪指令的属性域允许程序指定传递参数的语言规范,并且能覆盖 .MODEL 伪指令指定的默认语言规范。下例声明的过程采用了 C 调用规范:
Examplel PROC C,
parm1:DWORD, parm2:DWORD
Examplel PROC STDCALL,
parm1:DWORD, parm2:DWORD