English 中文(简体)
页: 1
原标题:x86_64 nasm read syscall isn t null-terminated

x86_64 nasm read syscall isn t null-terminated

New to assembly. In fact this is my first hello world program. OS: Arch Linux (64-bit)

Logic

I have three functions. strlen, stdin and stdout. strlen: Find s the length of a string by looping through bytes until it finds a null-byte.

www.un.org/spanish/ecosoc 仅使用读写的回忆。

First, I ask for the user s input with stdout (not important) Then I create an input prompt using stdin stdin puts the input inside the string rl Lastly, stdout attempts to print the input.

The issue

If you recall how strlen works. It loops until it finds a null-byte. However stdin doesn t null-terminate it s input. Therefore when stdout goes to find the length of the input it won t stop at the end of the input and will continue collecting garbage until it comes across a null-byte. But by then you will have something looking like this:

What is your name?
Logan
Logan
��
   @ @@%)@1+@7L@>a@O@J @V @]▒ @hello.asmstrrlstrlenstrlen_nextstrlen_nullstdinstdoutExitSuccess__bss_start_edata_end.symtab.strtab.shstrtab.text.datam! @ ▒ P
▒       h!b�! 

简单的办法应当是在扼杀结束时只增加一个无尽的字句。 我怎么办? 而且,正如我在开始时所说的那样,聚集起来还有很多新东西...... 因此,你的ancy子只会恐吓我。

Full program

            global    _start

            section     .data
str:        db          "What is your name?", 10, 0     ; db: Define byte (8 bits)
                                                        ; Declare hw to be "Hello, world!"
                                                        ; 10 = "
" (newline character)
rl:         db          0

            section     .text
_start:
            mov         rsi,    str
            call        stdout          ; Write to STDOUT
            call        stdin
            call        stdout

            jmp         ExitSuccess     ; Return with exit code 0
strlen:
            push        rsi             ; Save string to stack
strlen_next:
            cmp         [rsi], byte 0   ; Compare char to null byte
            jz          strlen_null     ; Jump if null byte

            inc         rcx             ; Char wasn t null, increment rcx (string length)
            inc         rsi             ; Next char
            jmp         strlen_next     ; Repeat, until we get a null byte
strlen_null:
            pop         rsi             ; Load string from the stack
            ret                         ; Return to call
stdin:
            mov         rax,    0
            mov         rdi,    0
            mov         rsi,    rl
            mov         rdx,    strlen
            syscall
            ret
stdout:
            mov         rax,    1       ; syscall write
            mov         rdi,    1       ; File descriptor STDOUT
            call        strlen          ; String length of rsi
            mov         rdx,    rcx     ; Move strlen of rsi into rdx
            syscall

            ret
ExitSuccess:
            mov         rax,    60      ; syscall exit
            mov         rdi,    0       ; Move exit code into rdi
            syscall

问题回答

Two changes had to be made: Firstly, I needed to fix the strlen function. (which I have renamed to _strlen) The issue was that I forgot to set rcx to zero before I began the counting, Lastly, directly after we do the syscall in stdin we then add a null-byte at the end of the buffer. (mov byte [rsi+rax-1], 0)

;##################################################################################################################################
;
; hello.asm
;
; 15/09/2023
;
; Logan Seeley
;
; Compiling:
;   Create object file:     $ nasm -f elf64 hello.asm
;   Link object file:       $ ld -m elf_x86_64 hello.o -o hello
;   Execute file:           $ ./hello
;   Print exit code:        $ printf "
[Process finished with exit code $?]
"
;
;   All in one command:
;   $ nasm -f elf64 hello.asm; ld -m elf_x86_64 hello.o -o hello; ./hello; printf "

[Process finished with exit code $?]
"
;
;   TODO:  Use call-preserved registers RBX, RBP, RSP, and R12-R15 for functions instead of using RDI, RSI, RDX, RCX, R8, R9
;           RBX, RBP and RSP should be used for args
;           R12-15 should be used for return values
;
;##################################################################################################################################

            global    _start

            section     .data
prompt:     db          "What is your name?", 10, 0     ; db: Define byte (8 bits)
                                                        ; Declare prompt to be "What is your name?"
                                                        ; 10 = "
" (newline character)
                                                        ; 0  = null-byte (for zero-termination)
hello:     db         "Hello, ", 0

bufsize     equ         2048
rl:         resb        bufsize

            section     .text
_start:
            mov         rsi,    prompt  ; Move string into rsi to be written to STDOUT
            call        stdout          ; Write to STDOUT
            call        stdin
            mov         rsi,    hello
            call        stdout
            mov         rsi,    rl      ; Move input into rsi
            call        stdout

            jmp         ExitSuccess     ; Return with exit code 0
_strlen:
            xor         rcx,    rcx     ; Move 0 into rcx so we count up from 0
            push        rsi             ; Save string to stack
strlen_next:
            cmp         [rsi], byte 0   ; Compare char to null byte
            jz          strlen_null     ; Jump if null byte

            inc         rcx             ; Char wasn t null, increment rcx (string length)
            inc         rsi             ; Next char
            jmp         strlen_next     ; Repeat, until we get a null byte
strlen_null:
            pop         rsi             ; Load string from the stack
            ret                         ; Return to call
stdin:
            mov         rax,    0
            mov         rdi,    0
            mov         rsi,    rl
            mov         rdx,    _strlen
            syscall
            mov         byte [rsi+rax-1], 0     ; Setting last character of buffer to null-byte
                                                ; Replacing last character instead of concatting,
                                                ; because last character is a newline from user pressing enter
            ret
stdout:
            mov         rax,    1       ; syscall write
            mov         rdi,    1       ; File descriptor STDOUT
            call        _strlen         ; String length of rsi
            mov         rdx,    rcx     ; Move strlen of rsi into rdx
            syscall

            ret
ExitSuccess:
            mov         rax,    60      ; syscall exit
            mov         rdi,    0       ; Move exit code into rdi
            syscall




相关问题
Signed executables under Linux

For security reasons, it is desirable to check the integrity of code before execution, avoiding tampered software by an attacker. So, my question is How to sign executable code and run only trusted ...

encoding of file shell script

How can I check the file encoding in a shell script? I need to know if a file is encoded in utf-8 or iso-8859-1. Thanks

How to write a Remote DataModule to run on a linux server?

i would like to know if there are any solution to do this. Does anyone? The big picture: I want to access data over the web, using my delphi thin clients. But i´would like to keep my server/service ...

How can I use exit codes to run shell scripts sequentially?

Since cruise control is full of bugs that have wasted my entire week, I have decided the existing shell scripts I have are simpler and thus better. Here is what I have so far svn update /var/www/...

Good, free, easy-to-use C graphics libraries? [closed]

I was wondering if there were any good free graphics libraries for C that are easy to use? It s for plotting 2d and 3d graphs and then saving to a file. It s on a Linux system and there s no gnuplot ...

热门标签