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运行时的程序,则传递argcargv参数(假设为x86),其中argcebp+8argvebp+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。