User input and output doesn't work in my assembly code

后端 未结 1 1368
渐次进展
渐次进展 2020-12-04 03:00

The following program compiles without errors, but when run it doesn\'t prompt for any input and nothing prints. What\'s the problem, and how can I fix it?

I use the

相关标签:
1条回答
  • 2020-12-04 03:31

    There are signs in your code that you may have been using a Linux tutorial when producing code for OS/X(BSD). Linux and OS/X have differing SYSCALL calling conventions. In OS/X 32-bit programs int 0x80 requires parameters (except the syscall in EAX) to be passed on a stack.

    The important things to be aware of with 32-bit SYSCALLs via int 0x80 on OS/X are:

    • arguments passed on the stack, pushed right-to-left
    • you must allocate an additional 4 bytes (a DWORD) on the stack after you push all the arguments
    • syscall number in the eax register
    • call by interrupt 0x80

    After pushing arguments on the stack in reverse order for int 0x80 you must allocate an additional 4 bytes (a DWORD) on the stack. The value in that memory location on the stack doesn't matter. This requirement is an artifact from an old UNIX convention.

    A list of the SYSCALL numbers and their parameters can be found in the APPLE header files. You'll need these SYSCALLs:

    1 AUE_EXIT    ALL { void exit(int rval); }
    3 AUE_NULL    ALL { user_ssize_t read(int fd, user_addr_t cbuf, user_size_t nbyte); } 
    4 AUE_NULL    ALL { user_ssize_t write(int fd, user_addr_t cbuf, user_size_t nbyte); } 
    

    I have commented some example code that would be similar in functionality to what you may have been attempting to achieve:

    section .data
        ;New line string
        NEWLINE: db 0xa, 0xd
        LENGTH: equ $-NEWLINE
    
    section .bss
        INPT: resd 1
    
    global _start
    
    section .text
    _start:
        and     esp, -16      ; Make sure stack is 16 byte aligned at program start
                              ;     not necessary in this example since we don't call 
                              ;     external functions that conform to the OS/X 32-bit ABI
    
        push    dword 1       ; Read 1 character
        push    dword INPT    ; Input buffer
        push    dword 0       ; Standard input = FD 0
        mov     eax, 3        ; syscall sys_read
        sub     esp, 4        ; Extra 4 bytes on stack needed by int 0x80
        int     0x80
        add     esp, 16       ; Restore stack
    
        push    dword 1       ; Print 1 character
        push    dword INPT    ; Output buffer = buffer we read characters into
        push    dword 1       ; Standard output = FD 1
        mov     eax, 4        ; syscall sys_write
        sub     esp, 4        ; Extra 4 bytes on stack needed by int 0x80
        int     0x80
        add     esp, 16       ; Restore stack
    
        push    dword LENGTH  ; Number of characters to write
        push    dword NEWLINE ; Write the data in the NEWLINE string
        push    dword 1       ; Standard output = FD 1
        mov     eax, 4        ; syscall sys_write
        sub     esp, 4        ; Extra 4 bytes on stack needed by int 0x80
        int     0x80
        add     esp, 16       ; Restore stack
    
        push    dword 0       ; Return value from program = 0
        mov     eax, 1        ; syscall sys_exit
        sub     esp, 4        ; Extra 4 bytes on stack needed by int 0x80
        int     0x80
    

    The and esp, -16 is only necessary if you need to align the stack to a 16-byte boundary as a baseline for future stack operations. If you intend to call external functions that conform to the OS/X 32-bit ABI the stack is expected to be 16-byte aligned immediately preceding a function CALL. This alignment is not necessary for system calls via int 0x80.

    You should be able to assemble and link it with:

    nasm -f macho32 test.asm -o test.o
    ld -macosx_version_min 10.9.0 -o test test.o -e _start -lSystem
    

    And run it with:

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