我有这个C代码部分:
#include <stdio.h>
void main()
{
int n, array[1000], c, d, t, e;
char step;
puts("Enter a number\n");
scanf("%d", &n);
puts("any help? [y/n]");
scanf(" %c",&step);
puts("Enter integers\n");
}
我的相应汇编代码:
push prompt1
call _printf
add esp, 4 ;print and add 4 bytes to esp
push num
push sc1
call _scanf
add esp, 8 ;scan and add 8 bytes to esp
section .data
prompt1 db "Enter a number",13,10,0
sc2 db " %c",0 ;other constants
在命令提示符下将C文件转换为NASM格式后得到的汇编代码。
mov dword [esp], ?_001 ;?_001 is prompt1
call _puts
lea eax, [esp+0FBCH]
mov dword [esp+4H], eax
mov dword [esp], ?_002 ;?_002 is sc1
call _scanf
mov dword [esp], ?_003
call _puts
完整汇编代码:http://pastebin.com/R6UHRw8x 但是,我不理解转换后的汇编代码,因为mov dword [esp + 4H],eax使用[esp + 4]而下一行只使用[esp]。 不应该先[esp]然后[esp + 4]吗?我不明白,我在文件中看到了很多次出现。 除了push和mov之外,生成的代码与esp有什么不同?
答案 0 :(得分:3)
编译器输出将scanf
指针传递给堆栈空间,而不是静态存储。
它允许args在堆栈上构建而不是在每次调用后弹出(因此它可以使用mov
)。不幸的是,这两种方式都没有避免inserting stack-engine synchronization uops。
根据ABI /调用约定,第一个arg(按C顺序)位于最低地址,就在返回地址之上。将esp+0FBCH
放入[esp+0x4]
,将格式字符串指针放入[esp]
是正确的。有关链接,请参阅x86代码Wiki。