【问题标题】:Confuse about Assembly CALL,RET Statement对汇编 CALL,RET 语句感到困惑
【发布时间】:2014-10-04 03:08:05
【问题描述】:

我想知道“CALL”指令何时执行。它首先在堆栈或函数参数上推送返回地址?

谢谢

【问题讨论】:

    标签: assembly stack nasm masm


    【解决方案1】:

    CALL 根本不推送参数。它只推送返回地址。您有责任自行推动论点,这显然发生在CALL 之前。例如:

        push 2
        push 1
        push "%d"
        call printf
    next_instruction:
        add esp, 12
    

    当进入printf函数时,假设在32位的near call,栈是这样的:

    esp+0:  address of next_instruction
    esp+4:  address of "%d"
    esp+8:  1
    esp+12: 2
    

    编辑:关于参数的顺序,扩展@Martin所说的:

    对堆栈上的内容的解释是调用者和被调用者之间的契约(称为“调用约定”),它取决于很多东西,包括语言、体系结构、编译器等等。对于 x86 上的 C,参数从最后一个推到第一个。所以上面的汇编sn -p对应翻译后的C语句:

    printf("%d", 1, 2);
    

    如果您查看上面的堆栈,您会看到,由于我们以相反的顺序推送参数,它们相对于esp 从第一个到最后一个排序。这样printf 可以读取第一个参数"%d",而无需知道后面有多少参数,然后从格式字符串中确定其余参数。此外,由于在 C 调用约定中,调用者负责从堆栈中删除参数(next_instruction),因此传递过多的参数是无害的(尽管根据标准这是未定义的行为)。

    【讨论】:

    • 所以这意味着先生,如果我调用 blah_blah('bye' , 'dare').first 参数被推入堆栈(dare and bye)。然后返回地址。对吗?
    • 正确。调用函数对两个参数(dare 和 bye)执行“push”,然后执行“call”。推送参数的顺序取决于调用约定。对于 C 编程语言,最后一个参数首先推送,第一个参数最后推送。
    【解决方案2】:

    如果函数返回的对象太大而无法放入寄存器,则为返回的对象预先分配空间:

            sub     esp,sizeof object
            push    ecx
            push    eax
            call    example
            add     esp,8     ;restore stack
    ;                         ;esp is now pointer to object
            add     esp,sizeof object    ;restore stack once object no longer needed
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多