我正在学习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 ; \
如何可靠地计算用户输入字符串的长度?
如何避免打印额外字符?
答案 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
初始化为该值。