How to print argv[0] in NASM?

馋奶兔 提交于 2019-11-26 21:04:25

问题


I want to store argv[0] in a register and then print it, but I'm getting a segfault when I run my assembly program.

Trace:

$ 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

Specs:

  • ld 64-134.9
  • nasm 0.98.40
  • Xcode 4.5
  • Mac OS X 10.8.2
  • MacBook Pro 2009

回答1:


The segmentation fault comes from a bad stack alignment (misaligned_stack_error).
When you have such an issue, always try running your program with GDB. It will usually provide you with more information.

But to resume, as you are calling functions from the C library, the stack needs to be aligned on 16 bytes boundaries.
This is a requirement for the Mac OS X 32 bits ABI (note this is also the case for the 64 bits ABI, which uses the SYS V calling convention).

So here's a working version of your program, that will print the executable name, as well as the number of CLI arguments (explanation is just after that):

[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

Compile it using:

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

Explanation:

We first store argc and argv in some registers:

    pop     eax
    pop     ebx

And then we align the stack on a 16 bytes boundary:

    mov     ebp,                esp
    and     esp,                0xFFFFFFF0

You can do this only once, at the beginning of start, assuming you keep the stack aligned, when creating space for your local variables.

Then we create the necessary space for local variables, ensuring the stack is kept aligned.
Here, we only need room for 3 stack arguments, but we create space for 4, to keep the stack aligned.

    sub     esp,                16

You can then move values on that space, to prepare arguments for the call:

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

Then simply call the C library function, and you'll be OK.

Note you may also find some useful informations in this answer (x86 Assembly on a Mac).



来源:https://stackoverflow.com/questions/12678230/how-to-print-argv0-in-nasm

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!