汇编语言到伪C语言,汇编语言PROTO伪指令:指定程序的外部过程

PROTO伪指令在MASM汇编语言中用于定义过程的原型,包括参数列表。在32位模式下,它允许检查参数数量和类型。MASM要求每个INVOKE过程都有PROTO原型。错误检查包括参数数量过多或过少,以及类型不匹配。如果参数类型小于声明类型,MASM不会报错,但会自动扩展。示例展示了如何使用PROTO声明过程及调用过程。
摘要由CSDN通过智能技术生成

64 模式中,PROTO 伪指令指定程序的外部过程,示例如下:

ExitProcess PROTO

.code

mov ecx, 0

call ExitProcess

然而在 32 位模式中,PROTO 是一个更有用的工具,因为它可以包含过程参数列表。可以说,PROTO 伪指令为现有过程创建了原型 (prototype)。原型声明了过程的名称和参数列表。它还允许在定义过程之前对其进行调用,并验证参数的数量和类型是否与过程的定义相匹配。

MASM 要求 INVOKE 调用的每个过程都有原型。PROTO 必须在 INVOKE 之前首先岀现。换句话说,这些伪指令的标准顺序为:

MySub PROTO        ;过程原型

.

INVOKE MySub       ;过程调用

.

MySub PROC          ;过程实现

..

MySub ENDP

还有一种情况也是可能的:过程实现可以出现在程序的前面,先于调用该过程的 INVOKE 语句。在这种情况下,PROC 就是它自己的原型:

MySub PROC           ;过程定义

..

MySub ENDP

.

INVOKE MySub       ;过程调用

假设已经编写了一个特定的过程,创建其原型也是很容易的,即复制 PROC 语句并做如下修改:

将关键字 PROC 改为 PROTO。

如有 USES 运算符,则把该运算符连同其寄存器列表一起删除。

比如,假设已经创建了 ArraySum 过程:

ArraySum PROC USES esi ecx,

ptrArray:PTR DWORD, ;指向数组

szArray:DWORD ;数组大小

;省略其余代码行……

ArraySum ENDP

下面是与之对应的 PROTO 声明:

ArraySum PROTO,

ptrArray:PTR DWORD,         ;指向数组

szArray:DWORD                   ;数组大小

PROTO 伪指令可以覆盖 .MODEL 伪指令中的参数传递协议。但它必须与过程的 PROC 声明一致:

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

那么,下面是 Sub1 的一个有效调用:

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

EAX 被覆盖,sub esp,2 指令填充接下来的两个堆栈单元,以扩展到 32 位。

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 ENDP

INVOKE 语句调用 ArraySum,传递数组地址和元素个数:

.data

array DWORD 10000h, 20000h, 30000h, 40000h, 50000h

theSum DWORD ?

.code

main PROC

INVOKE ArraySum,

AD DR array, ;数组地址

LENGTHOF array ;元素个数

mov theSum, eax ;保存和数

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值