CALL根本没有推论.它只推送返回地址.你有责任自己推动论证,这CALL显然发生在以前.例如:
push 2
push 1
push "%d"
call printf
next_instruction:
add esp, 12
Run Code Online (Sandbox Code Playgroud)
进入printf函数时,假设接近32位调用,堆栈将如下所示:
esp+0: address of next_instruction
esp+4: address of "%d"
esp+8: 1
esp+12: 2
Run Code Online (Sandbox Code Playgroud)
编辑:关于参数的顺序,延伸到@Martin所说的:
对堆栈中存在的内容的解释是调用者和被调用者之间的契约(称为"调用约定"),它取决于很多东西,包括语言,体系结构,编译器等等.对于x86上的C,参数从最后一个推送到第一个.所以上面的汇编代码段对应于翻译的C语句:
printf("%d", 1, 2);
Run Code Online (Sandbox Code Playgroud)
如果你看一下上面的堆栈,你会看到,因为我们按相反的顺序推送了参数,所以它们从第一个到最后一个相对于它排序esp.这种方式printf可以在"%d"不知道将跟随多少参数的情况下读取第一个参数,然后从格式字符串中确定其余参数.此外,由于在C调用约定中,调用者负责从堆栈中删除参数(next_instruction),传递多于必要的参数是无害的(尽管根据标准它是未定义的行为).
| 归档时间: |
|
| 查看次数: |
215 次 |
| 最近记录: |