我习惯于看到(约定(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
- 海合会 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。
关于c - gcc:汇编代码中不同引用的命令行参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20204494/