【发布时间】:2014-10-04 03:08:05
【问题描述】:
我想知道“CALL”指令何时执行。它首先在堆栈或函数参数上推送返回地址?
谢谢
【问题讨论】:
我想知道“CALL”指令何时执行。它首先在堆栈或函数参数上推送返回地址?
谢谢
【问题讨论】:
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),因此传递过多的参数是无害的(尽管根据标准这是未定义的行为)。
【讨论】:
如果函数返回的对象太大而无法放入寄存器,则为返回的对象预先分配空间:
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
【讨论】: