linux - 使用 x86 程序集 (GNU/Linux) 读取和打印用户输入

标签 linux assembly x86 nasm

我正在学习 GNU/Linux 上的 x86 汇编,我正在尝试编写一个程序,从 stdin 读取用户输入并将其打印到 stdout。

以下代码确实有效,但如果用户输入的字符串的大小小于 100 个字节,它会打印额外的字符。

section .data
    str: db 100    ; Allocate buffer of 100 bytes

section .bss

section .text

global _start

_start:
    mov eax, 3          ; Read user input into str 
    mov ebx, 0          ; |
    mov ecx, str        ; | <- destination
    mov edx, 100        ; | <- length
    int 80h             ; \

    mov eax, 4          ; Print 100 bytes starting from str
    mov ebx, 1          ; |
    mov ecx, str        ; | <- source
    mov edx, 100        ; | <- length
    int 80h             ; \ 

    mov eax, 1          ; Return
    mov ebx, 0          ; | <- return code
    int 80h             ; \

如何可靠地计算用户输入字符串的长度?

如何避免打印多余的字符?

最佳答案

str: db 100 是错误的。您分配了值为 100 的 一个 字节。正确的是:str: times 100 db 0 以分配值为 0 的 100 个字节。

你有两个问题:

1) 要获取输入的字节数,您可以计算 EAX 中读取函数 (int 80h/fn 3) 的返回值。

2) 如果您输入的字符多于“允许”的字符,则其余字符将存储在您必须清空的输入缓冲区中。执行此操作的可能方法是在以下示例中:

global _start

section .data
    str: times 100 db 0 ; Allocate buffer of 100 bytes
    lf:  db 10          ; LF for full str-buffer

section .bss
    e1_len resd 1
    dummy resd 1

section .text

_start:
    mov eax, 3          ; Read user input into str
    mov ebx, 0          ; |
    mov ecx, str        ; | <- destination
    mov edx, 100        ; | <- length
    int 80h             ; \

    mov [e1_len],eax    ; Store number of inputted bytes
    cmp eax, edx        ; all bytes read?
    jb .2               ; yes: ok
    mov bl,[ecx+eax-1]  ; BL = last byte in buffer
    cmp bl,10           ; LF in buffer?
    je .2               ; yes: ok
    inc DWORD [e1_len]  ; no: length++ (include 'lf')

    .1:                 ; Loop
    mov eax,3           ; SYS_READ
    mov ebx, 0          ; EBX=0: STDIN
    mov ecx, dummy      ; pointer to a temporary buffer
    mov edx, 1          ; read one byte
    int 0x80            ; syscall
    test eax, eax       ; EOF?
    jz .2               ; yes: ok
    mov al,[dummy]      ; AL = character
    cmp al, 10          ; character = LF ?
    jne .1              ; no -> next character
    .2:                 ; end of loop

    mov eax, 4          ; Print 100 bytes starting from str
    mov ebx, 1          ; |
    mov ecx, str        ; | <- source
    mov edx, [e1_len]   ; | <- length
    int 80h             ; \

    mov eax, 1          ; Return
    mov ebx, 0          ; | <- return code
    int 80h             ; \

关于linux - 使用 x86 程序集 (GNU/Linux) 读取和打印用户输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23468176/

相关文章:

sql-server - Powershell x86 : Could not load file or assembly Microsoft. SqlServer.BatchParser

linux - Crontab 不通过管道传送到文件 (LINUX)

linux - 从 x86 中的特定位置读取文件

linux - 不同进程如何共享文件描述符?

arrays - 在 RISC-V 中遍历数组的不同方法

assembly - 为什么 MOV CR0 和 JMP 指令必须来自切换到保护模式时进行身份映射的页面?

assembly - 是否存在使用 MOVDQU 和 MOVUPD 优于 MOVUPS 的情况?

c++ - 如何在 C++ 中使用 thunk 将此指针绑定(bind)到静态成员函数

Linux 时间和日期

c - 为什么 Linux 内核模块符号不能正确地全局导出?