2012-10-01 46 views
3

我想將argv[0]存儲在一個寄存器中,然後將其打印出來,但是當我運行我的彙編程序時出現段錯誤。如何在NASM中打印argv [0]?

跟蹤:

$ nasm -f macho -o scriptname.o --prefix _ scriptname.asm 
$ ld -o scriptname scriptname.o -arch i386 -lc -macosx_version_min 10.6 -e _start -no_pie 
$ ./scriptname 
Segmentation fault: 11 

scriptname.asm:

[bits 32] 

section .data 

program: db "Program: %s", 0 

section .text 

global start 
extern printf 
extern exit 

start: 

; skip argc 
add esp, 4 

; ebx := argv[0] 
pop ebx 

push ebx 
push program 
call printf 
add esp, 8 

push 0 
call exit 

規格:

  • LD 64-134.9
  • NASM 0.98.40
  • 的Xcode 4.5
  • 的Mac OS X 10.8.2
  • 的MacBook Pro 2009年
+0

您確定生成的二進制文件只有32位嗎? – Macmade

+0

如果它運行在64位,那麼調用約定不是cdecl,而是系統V. – Macmade

+0

@Macmade,感謝您的信息!如果我想製作64位程序,我會記住這一點。程序*應該*只能是x86,因爲我指定'-arch i386'爲'ld'。當您嘗試在您的機器上構建和運行相同的代碼時會發生什麼? – mcandre

回答

4

段故障來源於壞棧對齊misaligned_stack_error)。
當你有這樣的問題時,總是嘗試運行你的程序與GDB。它通常會爲您提供更多信息。

但要恢復,當您從C庫調用函數時,堆棧需要對齊16字節的邊界
這是Mac OS X 32位ABI(注意對於使用SYS V調用約定的64位ABI也是這種情況)的要求。

因此,這裏是你的程序的工作版本,將打印可執行文件的名稱,以及對CLI參數的數量(解釋只是後):

[bits 32] 

section .data 

    hello db "Program name: %s (%i CLI args)", 10, 0 

section .text 

global start 
extern _exit 
extern _printf 

start: 

    ; Store 'argc' into EAX 
    pop  eax 

    ; Store 'argv' into EBX 
    pop  ebx 

    ; Align stack on a 16 bytes boundary, 
    ; as we'll use C library functions 
    mov  ebp,    esp 
    and  esp,    0xFFFFFFF0 

    ; Stack space for local variables 
    ; A little more space than needed, but that will 
    ; ensure the stack is still aligned 
    sub  esp,    16 

    ; Call 'printf': printf(hello, ebx, eax); 
    mov  dword[ esp ],  hello 
    mov  dword[ esp + 4 ], ebx 
    mov  dword[ esp + 8 ], eax 
    call _printf 

    ; Call 'exit': exit(0); 
    mov  dword[ esp ],  0 
    call _exit 

使用編譯:

nasm -f macho -o test.o test.asm 
ld -o test test.o -arch i386 -lc -macosx_version_min 10.6 

說明:

我們第一家店argcargv在一些REGIST ERS:

pop  eax 
    pop  ebx 

然後我們對齊在16個字節邊界堆棧:

mov  ebp,    esp 
    and  esp,    0xFFFFFFF0 

你可以做到這一點只有一次,在start開始,假設你保持一致堆棧,爲本地變量創建空間時。

然後我們爲局部變量創建必要的空間,確保堆棧保持對齊。
在這裏,我們只需要3個堆棧參數的空間,但我們爲4創建空間,以保持堆棧對齊。

sub  esp,    16 

然後,您可以在該空間中移動值,爲備調用參數:

mov  dword[ esp ],  hello 
    mov  dword[ esp + 4 ], ebx 
    mov  dword[ esp + 8 ], eax 

然後簡單地調用C庫函數,你會好起來的。

請注意,您還可以在this answer (x86 Assembly on a Mac)找到一些有用的信息。

+0

即使使用這些宏,我仍然收到對齊錯誤。你能爲我重寫原始代碼嗎? – mcandre

+0

@ JaggedO'Neill你是對的。還有性能方面的原因。 – Macmade

+0

@mcandre請參閱編輯:)您應該立即開始工作。 – Macmade