我想編寫一個程序,在工作方式如下:大會x86_64的:從用戶獲取輸入整數並打印
用戶->
鴻溝獲取多個輸入它,比方說,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
@ Tommylee2k這是什麼意思(?)我在上面的代碼中弄錯了什麼?我花了兩週的時間。幾乎不知道太少,我不明白你的意思): – Jazz
這意味着,如果您試圖證明代碼的正確性(除了立即出現任何編譯時失敗規則),源是否編譯幾乎完全不重要。實際上,即使運行可執行文件並收到預期結果仍然遠不足以證明正確性。爲了至少接近這個難以捉摸的烏托邦目標,您應該使用調試器按指令逐步執行您的代碼指令,根據您的期望/設計在每次執行的指令後測試當前機器狀態,並測試不同的輸入,如空/空/ large/... – Ped7g