How to print a character in Linux x86 NASM?

后端 未结 2 1460
轮回少年
轮回少年 2020-12-04 02:54

I\'m trying to print a single character or a number using NASM, targeting an x86 GNU/Linux architecture.

Here\'s the code I\'m using:



        
相关标签:
2条回答
  • 2020-12-04 03:13

    The system call you are executing expects ecx to contain an address in memory. This can be an arbitrary literal address (i.e. in your code, "A" translates to the address 041h), an address on the stack, or an address defined by a label in the program.

    Here's an example of defining a byte in memory and writing it to the standard output stream of your terminal:

        section .rodata  ; This section contains read-only data
    buffer:    db 'A'    ; Define our single character in memory
    
        section .text
        global start
    _start:
        ; Prints the letter 'A', then exits
    
        mov eax, 4      ; sys_write()
        mov ebx, 1      ; ... to STDOUT
        mov ecx, buffer ; ... using the following memory address
        mov edx, 1      ; ... and only print one character
        int 80h         ; SYSCALL
    
        mov eax, 1      ; Return to system
        mov ebx, 0      ; Exit zero, success
        int 80h         ; SYSCALL
    
    0 讨论(0)
  • 2020-12-04 03:26

    ecx should contain a pointer to the start of your char buffer. So you have to have your buffer in memory. You can do the following:

    ; Print 'A' character 
    mov   eax, 4      ; __NR_write from asm/unistd_32.h (32-bit int 0x80 ABI)
    mov   ebx, 1      ; stdout fileno
    
    push  'A'
    mov   ecx, esp    ; esp now points to your char
    mov   edx, 1      ; edx should contain how many characters to print
    int   80h         ; sys_write(1, "A", 1)
    
    ; return value in EAX = 1 (byte written), or error (-errno)
    
    add   esp, 4      ; restore esp if necessary
    

    You can mov byte [esp], 'A' or whatever other address if it's OK to overwrite whatever is on the stack.

    Or you can have a character array in section .rodata instead of storing on the fly.


    Making a write() system call with the const void *buf arg being some small number (like 'A') will make it return -EFAULT without printing anything. The kernel has to check the pointer anyway, and system calls return an error instead of raising SIGSEGV on bad pointers.

    Use strace ./my_program to trace the system calls you actually made, including decoding the return values.

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