gcc: command line args referenced differently in a

2019-06-02 17:48发布

I am used to seeing command line arguments referenced by (convention (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

Sometimes, I've seen the list start at an offset of 8, and this is not the (main) question. What I've noticed in a program is this translation and reference which I am confused about, to get argv[1] (convention (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  

(at offset 16(%ebp) I see a pointer to an environmental variable)

(1) Is there any reason for this different convention?
(2) Is there a compiler option to force gcc to use what I believe to be the standard convention (A) above?
(3) Is there a reason gcc uses convention (B)?
(4) Why the additional offset of 8?

System info:
- Ubuntu 12.04
- gcc 4.6.3
- compiled with fno-stack-protector

1条回答
爷的心禁止访问
2楼-- · 2019-06-02 18:29

If you're dealing with a program that has been linked to the C runtime, then the argc and argv parameters are passed (assuming x86) with argc at ebp+8 and argv at ebp+12. that's because the C runtime performs it's own initialization and passes the arguments to main() using the normal C ABI.

The calling convention that you say you're used to seeing (with argc at the top of the stack, followed by argv[0]..argv[argc]) is the state of the stack as set up by the Linux system call that starts a new program.

Note that your assembly oriented code example:

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

looks to be off by 4 for each of the last three lines because of the initial pushl instruction.

查看更多
登录 后发表回答