【发布时间】:2017-10-07 21:42:26
【问题描述】:
我正在尝试编写一个按以下方式工作的程序:
获取用户输入的数字 -> 除以 2 -> 打印结果(商)。
divide-by-the-number-2 部分似乎并没有太大的难度,所以我初步编写了一个程序,获取用户输入的整数并打印该整数。
这意味着我试图编写一个程序,将用户的字符串整数转换为实整数,然后将其转换回字符串并打印出来。
但是在编译之后我进入了一个无限循环(点击Enter 之后没有任何反应)。
我使用以下命令进行编译:
nasm -f elf64 ascii.asm -o ascii.o
ld ascii.o -o ascii
./ascii
在下面的代码中,子程序_getInteger 用于从字符串转换为整数,子程序_appendEOL 和_loopDigit 用于从整数到字符串的整个转换。
section .bss
ascii resb 16 ; holds user input
intMemory resb 100 ; will hold the endline feed
intAddress resb 8 ; hold offset address from the intMemory
section .data
text db "It's not an integer", 10
len equ $-text
section .text
global _start
_start:
call _getText
call _toInteger
call _appendEOL
mov rax, 60
mov rdi, 0
syscall
_getText:
mov rax, 0
mov rdi, 0
mov rsi, ascii
mov rdx, 16
syscall
ret
_toInteger:
mov rbx,10 ; for decimal scaling
xor rax, rax ; initializing result
mov rcx, ascii ; preparing for working with input
movzx rdx, byte [rcx] ; getting first byte (digit)
inc rcx ; for the next digit
cmp rdx, '0' ; if it's less than '0' is not a digit
jb _invalid
cmp rdx, '9' ; if it's greater than '9' is not a digit
ja _invalid
sub rdx, '0' ; getting decimal value
mul rbx ; rax = rax*10
add rax, rdx ; rax = rax + rdx
jmp _toInteger ; repeat
ret
_invalid:
mov rax, 1
mov rdi, 1
mov rsi, text
mov rdx, len
syscall
ret
_appendEOL:
; getting EOL
mov rcx, intMemory
mov rbx, 10 ; EOL
mov [rcx], rbx
inc rcx
mov [intAddress], rcx
_loopDigit:
xor rdx, rdx
mov rbx, 10
div rbx
push rax
add rdx, '0'
mov rcx, [intAddress]
mov [rcx], dl
inc rcx
mov [intAddress], rcx
pop rax
cmp rax, 0
jne _loopDigit
_printDigit:
mov rcx, [intAddress]
mov rax, 1
mov rdi, 1
mov rsi, rcx
mov rdx, 1
syscall
mov rcx, [intAddress]
dec rcx
mov [intAddress], rcx
cmp rcx, intMemory
jge _printDigit
ret
【问题讨论】:
-
听起来是时候了解 GDB(或其他调试器)了
-
@Tommylee2k 这是什么意思(:?我在上面的代码中有什么问题吗?我已经花了大约两周的时间使用 Assembly,所以我几乎一无所知。我没有完全明白你的意思):。
-
这意味着如果您试图证明代码的正确性,源代码是否编译几乎完全无关紧要(除非任何编译时失败立即排除)。实际上,即使运行可执行文件并收到预期的结果,距离证明正确性还有很长的路要走。为了至少更接近那个难以捉摸的乌托邦目标,您应该使用调试器逐条指令执行代码,根据您的期望/设计测试每条执行指令后的当前机器状态,并测试不同的输入,例如 null/empty /大/...