x86_64 nasm read 系统调用不是以 null 终止的

问题描述 投票:0回答:1

x86_64 nasm read 系统调用不是空终止的

装配新手。事实上,这是我的第一个 hello world 程序。 操作系统:Arch Linux(64位)

逻辑

我有三个功能。

strlen
stdin
stdout
strlen
: 通过循环字节直到找到空字节来查找字符串的长度。

stdin
stdout
只需使用读写系统调用。

首先,我用

stdout
请求用户输入(不重要) 然后我使用
stdin
创建输入提示
stdin
将输入放入字符串中
rl
最后,
stdout
尝试打印输入。

问题

如果您还记得

strlen
的工作原理。它循环直到找到空字节。 然而
stdin
不会以空终止它的输入。 因此,当
stdout
查找输入的长度时,它不会在输入末尾停止,并将继续收集垃圾,直到遇到空字节。但到那时你会看到像这样的东西:

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�!'

简单的解决方法应该是在字符串末尾添加一个空字节。我该怎么做呢?正如我一开始所说的,对于装配来说非常陌生......所以你花哨的行话只会吓到我。

完整节目

            global    _start

            section     .data
str:        db          "What is your name?", 10, 0     ; db: Define byte (8 bits)
                                                        ; Declare hw to be "Hello, world!"
                                                        ; 10 = "\n" (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

linux assembly x86-64 nasm stdin
1个回答
0
投票

必须进行两项更改: 首先,我需要修复

strlen
功能。 (我已将其重命名为
_strlen
) 问题是我在开始计数之前忘记将
rcx
设置为零, 最后,在我们执行
syscall
中的
stdin
之后,我们会在缓冲区末尾添加一个空字节。

;##################################################################################################################################
;
; 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 "\n[Process finished with exit code $?]\n"
;
;   All in one command:
;   $ nasm -f elf64 hello.asm; ld -m elf_x86_64 hello.o -o hello; ./hello; printf "\n[Process finished with exit code $?]\n"
;
;##################################################################################################################################

            global    _start

            section     .data
str:        db          "What is your name?", 10, 0     ; db: Define byte (8 bits)
                                                        ; Declare hw to be "Hello, world!"
                                                        ; 10 = "\n" (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
            push        rcx             ; Save whatever rcx has to the stack
            mov         rcx,    0
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         rcx             ; Load whatever from the stack
            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], 0
            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
© www.soinside.com 2019 - 2024. All rights reserved.