汇编语言向堆栈传递8位和16位参数


32 位模式中,向过程传递堆栈参数时,最好是压入 32 位操作数。虽然也可以将 16 位操作数入栈,但是这样会使得 EBP 不能对齐双字边界,从而可能导致出现页面失效、降低运行时性能。因此,在入栈之前,要把操作数扩展为 32 位。下面的 Uppercase 过程接收一个字符参数,并用 AL 返回其大写字母:
Uppercase PROC
    push ebp
    mov ebp, esp
    mov    al, [esp+8 ]          ;AL=字符
    cmp    al, 'a'               ;小于'a' ?
    jb L1                        ;是:什么都不做
    cmp    al, 'z'               ;大于'z' ?
    ja L1                        ;是:什么都不做
    sub    al, 32                ;否:转换字符
L1:
    pop ebp
    ret 4                        ;清除堆栈
Uppercase ENDP
当向 Uppercase 传递一个字母字符时,PUSH 指令自动将其扩展为 32 位:

push 'x'
call Uppercase

如果传递的是字符变量就需要更小心一些,因为 PUSH 指令不允许操作数为 8 位:

.data
charVal BYTE 'x'
.code
push charVal                                  ;语法错误!
call Uppercase

相反,要用 MOVZX 把字符扩展到 EAX:

movzx eax,charVal                         ;扩展并传送
push eax
call Uppercase

16 位参数示例

假设现在想向之前给出的 AddTwo 过程传递两个 16 位整数。由于该过程期望的数值为 32 位,所以下面的调用会发生错误:
.data
word1 WORD 1234h
word2 WORD 4111h
.code
push word1
push word2
call AddTwo                    ;错误!
因此,可以在每个参数入栈之前进行全零扩展。下面的代码将会正确调用 AddTwo:
movzx eax,word1
push eax
movzx eax,word2
push eax
call AddTwo                    ; EAX 为和数
一个过程的主调者必须保证它传递的参数与过程期望的参数是一致的。对堆栈参数而言,参数的顺序和大小都很重要!