簡體   English   中英

我正在嘗試在組裝中創建一個點的三角形,但它不起作用

[英]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個點的行。 緊隨其后的是一行包含32767個點等的行。每行上的點數繼續減少,直到具有1個點的行為止。

我注意到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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM