2011-11-18 43 views
4

有時,正確的值會返回,有時候是0,有時候(看似)是隨機數......都來自同一個可執行文件。FreeBSD/amd64程序集 - 如何閱讀「ARGC」?

.section .text 
.global _start 
_start: 
    movq $1, %rax 
    popq %rdi 
    syscall 

例如:

%as -o this.o this.s ; ld -o this this.o 

%./this; echo $? 
1 

%./this 1; echo $? 
0 

%./this 1 2; echo $? 
3 

%./this 1 2 a; echo $? 
4 

%./this 1 2 a f; echo $? 
0 

%_ 

我一種新的組裝,但我非常有信心獲得參數計數是因爲它彈出關閉堆棧一樣容易。 我做錯了什麼,還是這真的搞砸了?

+0

嘗試在調試器中運行它以查看堆棧佈局是否符合您的期望。 – user786653

+0

謝謝,我已經有一段時間了,通常8(%esp)有argc,但有時候不會,我想我會繼續努力吧! :) – timmmay

回答

3

我感到困惑在FreeBSD 9.0/amd64上也是如此。 (我使用NASM的彙編),我所做的是:

$ cat foo.asm 
global _start 
_start: 
     mov  rax, 4   ; write 
     mov  rdi, 1   ; stdout 
     mov  rsi, rsp  ; address 
     mov  rdx, 16   ; 16bytes 
     syscall 

     mov  rax, 1   ; exit 
     syscall 
$ nasm -f elf64 foo.asm && ld -o foo foo.o 
$ ./foo | hd 
00000000 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 |................| 
00000010 
$ ./foo 2 | hd 
00000000 02 00 00 00 00 00 00 00 b8 dc ff ff ff 7f 00 00 |................| 
00000010 
$ ./foo 2 3 | hd 
00000000 00 00 00 00 00 00 00 00 03 00 00 00 00 00 00 00 |................| 
00000010 
$ ./foo 2 3 4 | hd 
00000000 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 |................| 
00000010 
$ ./foo 2 3 4 5 | hd 
00000000 05 00 00 00 00 00 00 00 b0 dc ff ff ff 7f 00 00 |................| 
00000010 

我預期的argc在RSP,但事實並非如此。

我猜想內核(圖像激活器)設置寄存器。我搜索了源代碼樹,在/usr/src/sys/amd64/amd64/machdep.c(exec_setregs)中找到了以下代碼。

 regs->tf_rsp = ((stack - 8) & ~0xFul) + 8; 
     regs->tf_rdi = stack;   /* argv */ 

這些行看起來是說rsp是對齊的,實際數據是rdi。我改變了我的代碼,並獲得了預期的結果。

$ cat foo.asm 
global _start 
_start: 
     push rdi 
     mov  rax, 4   ; write 
     mov  rdi, 1   ; stdout 
     pop  rsi 
     mov  rdx, 16   ; 16bytes 
     syscall 

     mov  rax, 1   ; exit 
     syscall 
$ nasm -f elf64 foo.asm && ld -o foo foo.o 
$ ./foo | hd 
00000000 01 00 00 00 00 00 00 00 b0 dc ff ff ff 7f 00 00 |................| 
00000010 
$ ./foo 2 | hd 
00000000 02 00 00 00 00 00 00 00 a8 dc ff ff ff 7f 00 00 |................| 
00000010 
$ ./foo 2 3 | hd 
00000000 03 00 00 00 00 00 00 00 a8 dc ff ff ff 7f 00 00 |................| 
00000010 
$ ./foo 2 3 4 | hd 
00000000 04 00 00 00 00 00 00 00 a8 dc ff ff ff 7f 00 00 |................| 
00000010 
$ ./foo 2 3 4 5 | hd 
00000000 05 00 00 00 00 00 00 00 a8 dc ff ff ff 7f 00 00 |................| 
00000010 

你可以試試偏下?

1

對於FreeBSD的標準調用約定,你想:

movl %edi, %eax 

最短的完整的程序,其返回的狀態將等於它傳遞參數的個數是:

movl %edi, %eax 
ret 
+0

嗯......那個seg在我身上發生了故障。我使用64位而不是32位,所以我不知道這是否有所作爲。 – timmmay

+1

這將用於'main'函數,它被調用並返回到'_start'。他正在嘗試編寫一個'_start'函數,它接收堆棧中的參數並且不能返回。 – ughoavgfhw

+0

謝謝,它在主函數中工作正常,但沒有啓動。我已經重讀了amd64 abi並嘗試了幾次調試(儘管我沒有經驗過使用調試器)。如果有人能夠協助,我將不勝感激。謝謝! :) – timmmay