[英]I'm trying to create a triangle of dots in assembly but it isn't working
我正在嘗試通過獲取用戶輸入的值(以更改所得三角形的大小)並使用它來編寫逐漸減少的點線,從而在屏幕上創建點的三角形。
這是代碼:
section .data
global _start
char db ' '
prompt_text db "Enter triangle size (2-99) "
prompt_length equ $-prompt_text
section .bss
tri_size resb 3
tri_size_length equ $-tri_size
section .text
_start:
call prompt
call insert_size
mov rax, [tri_size]
outer_loop:
mov rbx, [tri_size]
inner_loop:
call dot
dec bx
cmp bx, 0
jg inner_loop
call linefeed
call dec_length
dec ax
cmp ax, 0
jne outer_loop
call linefeed
call exit
prompt:
mov rax, 4
mov rbx, 1
mov rcx, prompt_text
mov rdx, prompt_length
int 80h
ret
insert_size:
mov rax, 3
mov rbx, 0
mov rcx, [tri_size]
mov rdx, tri_size_length
int 80h
ret
dot:
mov [char], byte '.'
call print_char
ret
linefeed:
mov [char], byte 10
call print_char
ret
print_char:
push rax
push rbx
push rcx
push rdx
mov rax, 4
mov rbx, 1
mov rcx, char
mov rdx, 1
int 80h
pop rdx
pop rcx
pop rbx
pop rax
ret
dec_length:
push rax
push rbx
push rcx
push rdx
mov rax, [tri_size]
dec ax
mov [tri_size], rax
pop rdx
pop rcx
pop rbx
pop rax
ret
exit:
mov rax, 1
mov rbx, 0
int 80h
問題:
我注意到32768是十六進制的10000000_00000000,但除此之外,我完全被卡住了,非常感謝您的幫助!
PS我正在使用x84-64 linux並與YASM組裝
您的代碼中有兩個問題,都在您閱讀輸入時遇到。 首先,解決。 然后,對當前結果進行解釋。
insert_size:
mov rax, 3
mov rbx, 0
mov rcx, [tri_size] ; issue 1
mov rdx, tri_size_length
int 80h
ret ; issue 2 (sort of)
首先, rcx
應該包含緩沖區的地址,但是您正在獲取tri_size
的內容,而不是其地址。 由於tri_size
在bss部分中,因此將使用0s進行初始化,因此您要告訴OS讀入NULL緩沖區。 如果要檢查系統調用的結果,則將看到一個錯誤代碼。
其次,當您讀取輸入內容時,您正在讀取的是字符串,而不是數字。 如果要將其用作數字,則需要先進行轉換。 這是已修復兩個問題的代碼:
insert_size:
mov rax, 3
mov rbx, 0
mov rcx, tri_size ; 1
mov rdx, tri_size_length
int 80h
mov dh, 0 ; 2
mov ah, 0
mov dl, [tri_size] ; 3
mov ah, [tri_size+1]
sub dl, '0' ; 4
cmp al, '0' ; 5
jb done
cmp al, '9' ; 6
ja done
imul dx, 10 ; 7
sub al, '0' ; 8
add dx, ax ; 9
done:
mov [tri_size], dx ; 10
ret
第一個問題是簡單的解決方法,只需刪除方括號即可獲取地址而不是內容。 第二個更復雜。 首先,我們將使用16位寄存器,但僅讀入8位,因此第2步將每個寄存器的高字節放入0。 然后,我們讀取字符串的前兩個字節。 接下來,我們將第一個字符從一個字符轉換為一個數字。 由於ASCII中的數字是連續的,因此我們可以通過減去字符“ 0”來實現。 請注意,這假設第一個字符是有效數字。
我們不能假設第二個字符是有效數字,因為可能只輸入了一個。 因此,第5步和第6步分別檢查它是否小於“ 0”和大於“ 9”,如果其中一個為真,則跳到最后。 如果我們都通過了,那么第二個字符是一個數字。 這意味着第一個數字應位於10的位置,因此我們將其乘以10。然后將第二個字符轉換為數字並將其添加到第一個數字。 現在兩個字符都已經過測試,我們可以將結果存儲回預期的位置並返回。
如修復程序中所述,您正在傳遞NULL緩沖區,因此它返回錯誤。 您的tri_size
變量從不更改,因此它仍包含0。這意味着您的兩個計數器都從0開始。由於不檢查此值,因此第一個點被打印並且bx
遞減,結果為-1。 由於-1不大於0,因此退出內部循環,並打印換行符,計數器和ax
遞減,結果為-1。 這不是零,因此它循環回到外循環。 這發生32768次,直到您的計數器達到-32768。
當您在此時減小bx
時,它變為-32769,但是使用16位2的補碼無法表示此數字。 相反,它將溢出,並且您得到的數字為32767。該數字大於0,因此您將繼續在內部循環中直到其變為0,才打印32768點。 退出內部循環並打印換行符后,計數器和ax
都會遞減,結果為32767。從這一點開始,您的程序就好像輸入為32767,這意味着您將從那里得到一個三角形到0點。
有趣的是,如果您的內部循環測試bx
是否等於0而不是大於0,您將得到一個從65536點到0的三角形,前面沒有1點線。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.