我正在尝试在装配中创建一个三角形点,但它不起作用

时间:2013-11-10 00:35:13

标签: linux assembly x86-64 yasm

我试图通过获取用户输入的值(以改变生成的三角形的大小)并使用它来写入递减的点线来在屏幕上创建一个三角形点。

以下是代码:

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的十六进制,但除此之外我完全被卡住了,我真的很感激任何帮助!

P.S。我正在使用x84-​​64 linux并与YASM组装

1 个答案:

答案 0 :(得分:2)

在您阅读输入时,代码中存在两个问题。首先,修复。然后,解释当前的结果。

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部分,因此它初始化为0,因此您告诉操作系统读入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' 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而不是大于,你只需要从65536点到0得到一个三角形,之前没有1点线。