装配 - (NASM 32位)打印星形三角形不能正常工作

时间:2013-08-10 05:10:54

标签: assembly printing geometry nasm

编辑:此问题已经解决。非常感谢mbratch。

我的代码输出:

Current output

但它应该显示:

Expected output

我认为问题在于内部循环,但我无法解决它,它在第一个循环上正常工作,但在后续循环中没有。

这是我的代码:

innerloop1: ;;for(j=n-i;j>0;j--)
mov bl, [i]
sub byte [num], bl
mov dl, [num]
mov byte [j], dl
cmp byte [j], 0
jle printStar

mov eax, 4
    mov ebx, 1
    mov ecx, space
    mov edx, spaceLen
    int 80h
dec dl
    jmp innerloop1

printStar:
mov eax, 4
    mov ebx, 1
    mov ecx, star
    mov edx, starLen
    int 80h

innerloop2: ;;for(k=0;k<(2*i)-1;k++)
mov al, [i]
mul byte [two]
dec al
cmp byte [k], al
jge printMe

mov eax, 4
    mov ebx, 1
    mov ecx, space
    mov edx, spaceLen
    int 80h

    inc byte [k]
    jmp innerloop2

printMe:
mov eax, 4
    mov ebx, 1
    mov ecx, star
    mov edx, starLen
    int 80h

    mov eax, 4
    mov ebx, 1
    mov ecx, newLine
    mov edx, newLineLen
    int 80h

    inc byte [i]
    jmp outerloop

    printSpace:
mov eax, 4
    mov ebx, 1
    mov ecx, space
    mov edx, spaceLen
    int 80h

1 个答案:

答案 0 :(得分:1)

您的代码中存在许多低效率,并且可以更清晰,更简洁地编写。但是,我只会解决导致功能问题的区域。

innerloop1存在一些问题。您每次循环修改[num]。相反,您希望在循环之前将其作为j的初始化程序。其次,你通过执行循环来指望dl的值是完整的,但是你的mov edx, spaceLen使它成为可能,就像调用int 80h一样。所以你可以通过这个来纠正它:

    mov dl, [num]       ; INITIALIZE j=n-i
    sub dl, byte [i]
innerloop1: ;;for(j=n-i;j>0;j--)
                        ; REMOVED modification of 'num' here
    mov byte [j], dl
    cmp byte [j], 0
    jle printStar

    mov eax, 4
    mov ebx, 1
    mov ecx, space
    push dx             ; SAVE dx
    mov edx, spaceLen
    int 80h
    pop dx              ; RESTORE dx
    dec dl
    jmp innerloop1

在你的第二个内循环(innerloop2)中,每次进入循环时都依赖于预先初始化的k值,在第一次遇到循环后它不再有效..所以你必须每次都初始化它:

    mov byte [k], 0   ; INITIALIZE k=0
innerloop2: ;;for(k=0;k<(2*i)-1;k++)
    mov al, [i]
    mul byte [two]
    dec al
    cmp byte [k], al
    jge printMe

这一切都使代码有效。一些额外的评论:

  • 您需要谨慎依赖寄存器的值并注意它们可能会被改变的地方
  • 您可能不应该依赖预先初始化的声明来初始化循环变量或其他可能因此而异的数据。如果您要定期更改它,通常可以在代码中显式初始化值
  • 考虑如何优化代码(使其更简洁明了),因为它基本上可以正常工作。
  • 在变量使用方面更加一致。您的asm程序使用num表示n,但也定义了值n,这有点令人困惑。
  • 在代码缩进和间距方面保持一致。这将使阅读更容易。
  • 在执行构造(例如for循环)时,尝试保持一致的方法来每次执行它们。它将减少错误的机会。例如,以相同或相似的方式管理循环变量。