繁体   English   中英

组装印刷星形三角形

[英]Printing star triangle in assembly

我想打印一个三角形是这样的: 在组装 查找每行星星数的公式是:2 * x +1。这是到目前为止的代码。 我似乎无限循环。

.data
prompt BYTE "Please enter the number of rows in the pyramid: ", 0
numRows DWORD ?
count DWORD 0

.code
main PROC
    mov edx, OFFSET prompt
    call WriteString
    call ReadInt

    mov numRows,eax                         
    mov ecx,numRows + 1                 ; Let ecx = numRows + 1
L1:
    inc count                           ; Increment count
    mov eax,ecx

    L2:
        sub eax,count                   ; eax = eax - count
        mov al, ' '                     ; Print spaces
        call WriteChar
        loop L2
    L3:
        mov ebx,count                   ; ebx = count
        add ebx,count                   ; ebx = ebx + count
        sub ebx,1                       ; 2x - 1
        mov al, '*'                     ; Printing the star pattern
        call WriteChar
        loop L3

    call CrLf
    loop L1

exit
main ENDP
END main

我要去哪里错了?

尽管这还不是完整的答案,但评论的时间太长了,它应该为您提供极大的帮助,因为:

http://kipirvine.com/asm/debug/index.htm

基本上,这是您应该首先学习的内容(并且太宽泛,太长,无法成为此答案的一部分)。


在知道如何使用调试器之后,您可以看一下代码在做什么,例如,您将遇到的第一个问题:

mov ecx,numRows + 1并没有实现您想像的那样,不能在汇编中使用数学表达式,您必须将它们编写为单个指令。

只有一些指令允许某种非常严格且有限的数学表达式,例如mov用于寻址内存模式,这实际上是在编译时得到的: mov ecx,[numRows + 1] =从+1地址获取值。 numRows是DWORD,因此,如果用户输入了10,则内存看起来像这样(从numRows地址开始: 0A 00 00 00 00 00 00 00前4个字节由mov numRows,eax (Irvine编写时不带[]在内存引用周围,这是IMO的非常不好的风格/味道)第5个字节位于count地址,由count DWORD 0行定义,因此为4个零字节。现在mov ecx,[numRows + 1]将因此获取4个零从内存开始,从0A字节之后开始,然后“泄漏”一个字节count

同样,在编译时允许使用数学表达式,即, add eax,12+13*14可以,在组装过程中生成单个常数。 但您应该通读此类文档,以了解哪种参数组合是合法的, mov ecx,label + 1可以是立即常量加载(在NASM中)=“ address + 1”,也可以是内存加载(来自address +的值1)在MASM中,都不执行“值+ 1”。

要执行您想要的操作,您需要:

mov ecx,[numRows]  ; load the VALUE numRows back into ecx
inc ecx            ; ecx = numRows+1

但是由于eax已经包含numRows值,因此可以避免获取内存,因此在这种特殊情况下,这就足够了:

mov ecx,eax        ; copy the numRows value from eax into ecx
inc ecx            ; ecx = numRows+1

但是由于此数学表达式足够简单,无法适合可能的寻址模式之一,因此您可以利用LEA指令认为它正在计算内存地址,而它将只计算您的表达式:

lea  ecx,[eax+1]   ; ecx = value_numRows + 1

即使eax + 1是非法的地址进入内存,此方法仍然有效,但是LEA不会尝试读取该地址,它只会对其进行计算并存储到目标寄存器中。

...等等,这里的重点是:

1)学习调试您的代码(这对于进一步发展它是绝对必要的)

2)放弃Irvine风格,并在每个内存取消引用时都严格使用[] ,即在“变量”周围,如果您要编写mov ecx,[numRows]+1 (如果您知道mov操作数是合法的,您应该认为这看起来不太好)。

3)尝试将“变量”方面的思考移向较低级别的“内存->地址->内容(字节)”,“变量”方式有时会限制您看到如何以字节/位操作数据的机会级别以更简单的方式获得所需的结果。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM