汇编语言PROTO伪指令:指定程序的外部过程
ExitProcess PROTO
.code
mov ecx, 0
call ExitProcess
MASM 要求 INVOKE 调用的每个过程都有原型。PROTO 必须在 INVOKE 之前首先岀现。换句话说,这些伪指令的标准顺序为:
MySub PROTO ;过程原型
.
INVOKE MySub ;过程调用
.
MySub PROC ;过程实现
..
MySub ENDP
MySub PROC ;过程定义
..
MySub ENDP
.
INVOKE MySub ;过程调用
- 将关键字 PROC 改为 PROTO。
- 如有 USES 运算符,则把该运算符连同其寄存器列表一起删除。
比如,假设已经创建了 ArraySum 过程:
ArraySum PROC USES esi ecx, ptrArray:PTR DWORD, ;指向数组 szArray:DWORD ;数组大小 ;省略其余代码行…… ArraySum ENDP下面是与之对应的 PROTO 声明:
ArraySum PROTO,
ptrArray:PTR DWORD, ;指向数组
szArray:DWORD ;数组大小
Example1 PROTO C,
parm1:DWORD, parm2:DWORD
汇编时参数检查
PROTO 伪指令帮助汇编器比较过程调用和过程定义的参数列表。但是这个错误检查没有如 C 和 C++ 语言中那样重要。相反,MASM 检查参数正确的数量,并在某些情况下,匹配实际参数和形式参数的类型。比如,假设 Sub1 的原型声明如下:Sub1 PROTO, p1:BYTE, p2:WORD, p3:PTR BYTE
现在定义变量:
.data
byte_1 BYTE 10h
.word_1 WORD 2000h
word_2 WORD 3000h
dword_1 DWORD 12345678h
INVOKE Sub1, byte_1, word_1, ADDR byte_1
MASM 为这个 INVOKE 生成的代码显示了参数按逆序压入堆栈:
push 404000h ;指向 byte_1 的指针
sub esp, 2 ;在栈项填充两个字节
push word ptr ds:[00404001h] ;word_1 的值
mov al, byte ptr ds:[00404000h] ;byte_1 的值
push eax
call 00401071
MASM 会检测的错误
如果实际参数超过了形式参数声明的大小,MASM 就会产生一个错误:INVOKE Sub1, word_1, word_2, ADDR byte_1 ;参数 1 错误
如果调用 Sub1 时参数个数太少或太多,则 MASM 会产生错误:
INVOKE Sub1, byte_1, word_2 ;错误:参数个数太少
INVOKE Sub1, byte_1, ;错误:参数个数太多
word_2, ADDR byte_1, word_2
MASM 不会检测的错误
如果实际参数的类型小于形式参数的声明,那么 MASM 不会检测出错误:INVOKE Sub1, byte_1, byte_1, ADDR byte_1
相反,MASM 会把实际参数扩展为形式参数声明的类型大小。下面是 INVOKE 示例生成的代码,其中第二个实际参数 (byte_1) 入栈之前,在 EAX 中进行了扩展:
push 404000h ;byte_1 的地址
mov al,byte ptr ds:[00404000h] ;byte_1
movzx eax,al ;在 EAX 中扩展
push eax ;入栈
mov al,byte ptr ds:[00404000h] ;byte_1 的值
push eax ;入栈
call 00401071 ;调用 Sub1
INVOKE Sub1, byte_1, word_2, dword_1 ;无错误检出
ArraySum 示例
过程用寄存器传递参数,现在,可以用 PROC 伪指令来声明堆栈参数:ArraySum PROC USES esi ecx, ptrArray:PTR DWORD, ;指向数组 szArray:DWORD ;数组大小 mov esi, ptrArray ;数组地址 mov ecx, szArray ;数组大小 mov eax, 0 ;和数清零 cmp ecx, 0 ;数组长度=0? je L2 ;是:退出 L1: add eax, [esi] ;将每个整数加到和数中 add esi, 4 ;指向下一个整数 loop L1 ;按数组大小重复 L2: ret ;和数保存在EAX中 ArraySum ENDPINVOKE 语句调用 ArraySum,传递数组地址和元素个数:
.data array DWORD 10000h, 20000h, 30000h, 40000h, 50000h theSum DWORD ? .code main PROC INVOKE ArraySum, AD DR array, ;数组地址 LENGTHOF array ;元素个数 mov theSum, eax ;保存和数