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

时间:2014-05-05 08:35:43

标签: 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             ; \

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

如何避免打印额外字符?

2 个答案:

答案 0 :(得分:2)

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             ; \

答案 1 :(得分:1)

这是计算x86程序集中字符串长度的一种方法:

lea esi,[string]
mov ecx,-1    ; Start with ecx = -1
xor eax,eax   ; Clear eax
cld           ; Make scasb scan forward 
repne scasb   ; while (ecx != 0) { ecx--; if (*esi++ == al) break; }
; ecx now contains -1 - (strlen(string) + 1) == -strlen(string) - 2
not ecx       ; Inverting ecx gives us -(-strlen(string) - 2) - 1 == strlen(string) + 1 
dec ecx       ; Subtract 1 to get strlen(string)

这假设该字符串以NUL终止('\0')。如果字符串使用其他终结符,则必须在al之前将repne scasb初始化为该值。