• 汇编语言向堆栈传递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 为和数

    一个过程的主调者必须保证它传递的参数与过程期望的参数是一致的。对堆栈参数而言,参数的顺序和大小都很重要!

更多...

加载中...