尽管接受的答案绰绰有余,但我想给出一个明确的答案,因为还有其他一些可能会混淆的答案。
最重要的(更多信息,请参见下面的实施例):在x86-64的命令行参数通过堆栈传递:
(%rsp) -> number of arguments
8(%rsp) -> address of the name of the executable
16(%rsp) -> address of the first command line argument (if exists)
... so on ...
它是从通过在X86-64函数参数不同,它使用%rdi
,%rsi
等。
还有一件事:不应该从C main
功能的反向工程中推断出行为。 C运行时提供入口点_start
,将命令行参数包装并调用main
作为常用函数。要看到它,我们来考虑下面的例子。
与-nostdlib
没有C运行时/ GCC让我们来看看这个简单的x86-64汇编程序,它什么也不做,但返回42:
:
.section .text
.globl _start
_start:
movq $60, %rax #60 -> exit
movq $42, %rdi #return 42
syscall #run kernel
我们与它建立
as --64 exit64.s -o exit64.o
ld -m elf_x86_64 exit64.o -o exit64
或
gcc -nostdlib exit64.s -o exit64
运行在gdb与
./exit64 first second third
,并停止在断点_start
。让我们检查一下寄存器:
(gdb) info registers
...
rsi 0x0 0
rdi 0x0 0
...
没有。那堆栈呢?
(gdb) x/5g $sp
0x7fffffffde40: 4 140737488347650
0x7fffffffde50: 140737488347711 140737488347717
0x7fffffffde60: 140737488347724
所以堆栈中的第一个元素是4
- 预期argc
。接下来的4个值看起来很像指针。我们来看第二个指针:
(gdb) print (char[5])*(140737488347711)
$1 = "first"
正如所料,它是第一个命令行参数。
所以有实验证据表明命令行参数是通过x86-64中的堆栈传递的。但是,只有阅读ABI(正如接受的答案所暗示的那样),我们可以肯定的是,情况确实如此。
随着C运行时
我们必须稍微改变一下程序,重命名_start
为main
,因为入口点_start
是由C运行时提供。
.section .text
.globl main
main:
movq $60, %rax #60 -> exit
movq $42, %rdi #return 42
syscall #run kernel
我们与(C运行时的缺省设置是使用)构建它:用
./exit64gcc first second third
在gdb
gcc exit64gcc.s -o exit64gcc
运行在该断点处停止main
。什么是堆栈?
(gdb) x/5g $sp
0x7fffffffdd58: 0x00007ffff7a36f45 0x0000000000000000
0x7fffffffdd68: 0x00007fffffffde38 0x0000000400000000
0x7fffffffdd78: 0x00000000004004ed
它看起来并不熟悉。并注册?
(gdb) info registers
...
rsi 0x7fffffffde38 140737488346680
rdi 0x4 4
...
我们可以看到,rdi
包含argc
值。但是,如果我们现在rsi
奇怪的事情检查指针发生:
(gdb) print (char[5])*($rsi)
$1 = "\211\307???"
别急,在C main
函数的第二个参数不是char *
,但char **
也:
(gdb) print (unsigned long long [4])*($rsi)
$8 = {140737488347644, 140737488347708, 140737488347714, 140737488347721}
(gdb) print (char[5])*(140737488347708)
$9 = "first"
现在我们找到了我们的参数,这些参数是通过寄存器传递的,正如x86-64中的正常函数一样。
结论: 正如我们所看到的,是用C运行时和代码不涉及的命令行参数传递代码之间的差。
链接只有答案是脆弱的。该页面不适合我。 * www.x86-64.org没有发送任何数据。 ERR_EMPTY_RESPONSE * – doug65536 2017-10-30 10:26:40