How to print argv[0] in NASM?

前端 未结 1 1179
失恋的感觉
失恋的感觉 2020-12-06 03:21

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 ma         


        
相关标签:
1条回答
  • 2020-12-06 04:05

    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).

    0 讨论(0)
提交回复
热议问题