我想用x86-32位汇编编写一个程序,输入由3个整数组成的字符串,即30 40 2。然后将其转换为整数,将其放置到单独的寄存器中。最后,以字符串形式输出,格式为“数字 1:(num1),数字 2:(num2),数字 3:(num3)。”
这是我的代码:
section .data
num db '0' ; Initialize for number with value 0 of ASCII
res db 0 ; decalre a byte res with value 0
numStrSize equ 12
section .bss
input resb 30 ; Reserves a buffer input of 10 bytes for user input.
num1 resd 1
num2 resd 1
opCode resd 1
str_buffer resb numStrSize
section .text
global _start
_start:
; Read input from user
mov eax, 3 ; Sets up a sys_read system call (system call number 3).
mov ebx, 0 ; Specifies file descriptor 0 (standard input).
mov ecx, input ; Points ecx to the input buffer.
mov edx, 10 ; Increase to match buffer size
int 80h ; Executes the system call (reads user input into input buffer).
; Convert string to integer
mov esi, input ; ESI points to the start of input
call convertToInt
mov [num1], eax
call NextInt
call convertToInt
mov [num2], eax
call NextInt
call convertToInt
mov [opCode], eax
mov eax, [num1]
mov ecx, str_buffer
call IntegerToString
mov eax, 4
mov ebx, 1
mov ecx, str_buffer
mov edx, numStrSize
int 80h
mov eax, [num2]
mov ecx, str_buffer
call IntegerToString
mov eax, 4
mov ebx, 1
mov ecx, str_buffer
mov edx, numStrSize
int 80h
mov eax, [opCode]
mov ecx, str_buffer
call IntegerToString
mov eax, 4
mov ebx, 1
mov ecx, str_buffer
mov edx, numStrSize
int 80h
exit:
mov eax, 1
xor ebx, ebx
int 80h
convertToInt:
xor eax, eax ; Clear EAX for storing result
.Loop:
movzx ebx, byte [esi] ; Move one byte of input into EBX
test ebx, ebx ; Test if byte is null terminator (end of string)
jz .end
cmp ebx, ' ' ; Check if the character is a whitespace
je .end ; If whitespace, jump to skip_character
sub ebx, '0' ; Convert ASCII to integer (subtract ASCII value of '0')
imul eax, eax, 10 ; Multiply current result by 10 (shift left by one decimal place)
add eax, ebx ; Add new digit to result
inc esi
jmp .Loop
.end:
ret
IntegerToString:
mov ebx, 10 ; Set divisor to 10
mov edi, ecx ; Set EDI to point to the start of the buffer
mov byte [edi], 0 ; Null-terminate the string
.convert:
add edi, numStrSize - 1 ; Move EDI to the end of the buffer
.convert_loop:
dec edi ; Move back one byte in the buffer
xor edx, edx ; Clear EDX for division
div ebx ; Divide EAX by 10, result in EAX, remainder in EDX
add dl, '0' ; Convert remainder to ASCII character
mov [edi], dl ; Store ASCII character in buffer
test eax, eax ; Check if EAX is zero
jnz .convert_loop ; If not zero, continue loop
.reverse:
mov esi, ecx
dec edi ; Decrement EDI to exclude null terminator
jmp .start_reverse
.start_reverse:
.reverse_loop:
cmp esi, edi ; Check if pointers have crossed
jge .done ; If so, the string is reversed
mov al, [esi] ; Swap the characters
mov bl, [edi]
mov [esi], bl
mov [edi], al
inc esi ; Move to next characters
dec edi
jmp .reverse_loop
.done:
ret
NextInt:
.loop:
movzx ebx, byte [esi]
test ebx, ebx
jz .end
cmp ebx, ' '
je .skipSpace
inc esi
jmp .loop
.skipSpace:
inc esi
jmp .end
.end:
ret
我尝试打印我保存的 3 个整数。即我的输入是 100 999 1,但我得到的输出是:
100 999 99 1
我该如何解决这个问题?
为什么IntegerToString中有反转代码?
转换已按正确的顺序存储十进制字符。
这就是 12 字节 str_buffer 的样子:
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
mov edi, ecx ; Set EDI to point to the start of the buffer mov byte [edi], 0 ; Null-terminate the string
0, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
^
EDI
add edi, numStrSize - 1 ; Move EDI to the end of the buffer
0, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
^
EDI
.convert_loop: dec edi ; Move back one byte in the buffer add dl, '0' ; Convert remainder to ASCII character mov [edi], dl ; Store ASCII character in buffer
0, ?, ?, ?, ?, ?, ?, ?, ?, ?, '0', ?
^
EDI
.convert_loop: dec edi ; Move back one byte in the buffer add dl, '0' ; Convert remainder to ASCII character mov [edi], dl ; Store ASCII character in buffer
0, ?, ?, ?, ?, ?, ?, ?, ?, '0', '0', ?
^
EDI
.convert_loop: dec edi ; Move back one byte in the buffer add dl, '0' ; Convert remainder to ASCII character mov [edi], dl ; Store ASCII character in buffer
0, ?, ?, ?, ?, ?, ?, ?, '1', '0', '0', ?
^
EDI
您可以做的唯一后处理是将缓冲区中的字符向下移动,以便您每次打印的地址保持不变。但最好将字符保留在原处,然后将 ECX 设置为 EDI 中的地址并使用 EDX 保存实际长度(在 num1 = 100 的情况下为 3)返回。
所以我终于得到了我想要的输出。感谢那些帮助我的人。这是更正后的代码。
.text
global _start
_start:
; Read input from user
mov eax, 3 ; Sets up a sys_read system call (system call number 3).
mov ebx, 0 ; Specifies file descriptor 0 (standard input).
mov ecx, input ; Points ecx to the input buffer.
mov edx, 30 ; Increase to match buffer size
int 80h ; Executes the system call (reads user input into input buffer).
; Convert string to integer
mov esi, input ; ESI points to the start of input
call convertToInt
mov [num1], eax
call NextInt
call convertToInt
mov [num2], eax
call NextInt
call convertToInt
mov [opCode], eax
mov eax, [num1]
mov esi, str_buffer
call IntegerToString
mov ecx,eax
mov eax, 4
mov ebx, 1
mov edx, numStrSize
int 80h
mov eax, [num2]
mov esi, str_buffer
call IntegerToString
mov ecx,eax
mov eax, 4
mov ebx, 1
mov edx, numStrSize
int 80h
mov eax, [opCode]
mov esi, str_buffer
call IntegerToString
mov ecx,eax
mov eax, 4
mov ebx, 1
mov edx, numStrSize
int 80h
exit:
mov eax, 1
xor ebx, ebx
int 80h
convertToInt:
xor eax, eax ; Clear EAX for storing result
.Loop:
movzx ebx, byte [esi] ; Move one byte of input into EBX
test ebx, ebx ; Test if byte is null terminator (end of string)
jz .end
cmp ebx, ' ' ; Check if the character is a whitespace
je .end ; If whitespace, jump to skip_character
sub ebx, '0' ; Convert ASCII to integer (subtract ASCII value of '0')
imul eax, eax, 10 ; Multiply current result by 10 (shift left by one decimal place)
add eax, ebx ; Add new digit to result
inc esi
jmp .Loop
.end:
ret
IntegerToString:
add esi, 9
mov byte [esi], 0 ; String terminator
mov ebx, 10
.next_digit:
xor edx, edx ; Clear edx prior to dividing edx:eax by ebx
div ebx ; eax /= 10
add dl, '0' ; Convert the remainder to ASCII
dec esi ; store characters in reverse order
mov [esi], dl
test eax, eax
jnz .next_digit ; Repeat until eax==0
; return a pointer to the first digit (not necessarily the start of the provided buffer)
mov eax, esi
ret
NextInt:
.loop:
movzx ebx, byte [esi]
test ebx, ebx
jz .end
cmp ebx, ' '
je .skipSpace
inc esi
jmp .end
.skipSpace:
inc esi
jmp .end
.end:
ret
section .bss
input resb 30
numStrSize equ 10
num1 resd 1
num2 resd 1
opCode resd 1
str_buffer resb numStrSize