儘管接受的答案綽綽有餘,但我想給出一個明確的答案,因爲還有其他一些可能會混淆的答案。
最重要的(更多信息,請參見下面的實施例):在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