gcc:命令行参数在汇编代码中引用不同
我习惯看到(约定(A))引用的命令行参数:
pushl %ebp movl %esp, %ebp movl (%ebp), %eax # argc movl 4(%ebp), %ebx # pointer to argv[0] string movl 8($ebp), %ecx # pointer to argv[1] string
有时,我看到列表的偏移量为8,这不是(主要)问题。 我在程序中注意到的是这个翻译和引用,我很困惑,得到argv[1]
(约定(B)):
movl 0xc(%ebp), %eax # pointer to a pointer to argv[0] (argc is at offset 8) addl $0x4, %eax # argv[1] is a pointer at offset 4 from the pointer to argv[0] movl (%eax), %eax # load where it points to, which is the argv[1] string
(在偏移量16(%ebp)
我看到一个指向环境变量的指针)
(1)这种不同的惯例有什么理由吗?
(2)是否有一个编译器选项强制gcc使用我认为是上面的标准约定(A)?
(3)gcc是否使用约定(B)?
(4)为什么附加偏移量为8?
系统信息:
– Ubuntu 12.04
– gcc 4.6.3
– 使用fno-stack-protector编译
如果您正在处理已链接到C运行时的程序,则传递argc
和argv
参数(假设为x86),其中argc
为ebp+8
, argv
为ebp+12
。 那是因为C运行时执行它自己的初始化并使用普通的C ABI将参数传递给main()
。
你说你习惯看到的调用约定(在堆栈顶部使用argc
,然后是argv[0]
.. argv[argc]
)是由Linux系统调用设置的堆栈状态开始一个新的计划。
请注意,面向程序集的代码示例:
pushl %ebp movl %esp, %ebp movl (%ebp), %eax # argc movl 4(%ebp), %ebx # pointer to argv[0] string movl 8($ebp), %ecx # pointer to argv[1] string
由于最初的pushl
指令,最后三行中的每一行看起来都是4。