简体   繁体   English

组装印刷星形三角形

[英]Printing star triangle in assembly

I'm trying to print a triangle like this: in assembly . 我想打印一个三角形是这样的: 在组装 The formula to find the number of stars in each row is: 2 * x + 1. Here is my code so far. 查找每行星星数的公式是:2 * x +1。这是到目前为止的代码。 I seem to be looping infinitely. 我似乎无限循环。

.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

Where am I going wrong? 我要去哪里错了?

While this is not full answer, it got too long for a comment, and it should help you tremendously, because: 尽管这还不是完整的答案,但评论的时间太长了,它应该为您提供极大的帮助,因为:

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

This is basically the thing you should study first (and too broad+long to be part of this answer). 基本上,这是您应该首先学习的内容(并且太宽泛,太长,无法成为此答案的一部分)。


After you will know how to use debugger, you may take a look what your code is doing, for example one of first problems you will hit: 在知道如何使用调试器之后,您可以看一下代码在做什么,例如,您将遇到的第一个问题:

mov ecx,numRows + 1 doesn't do what you think it does, you can't use math expressions in assembly, you have to write them as single instructions. mov ecx,numRows + 1并没有实现您想像的那样,不能在汇编中使用数学表达式,您必须将它们编写为单个指令。

Only some instructions allow for some kind of very strict and limited math expression, like mov has for addressing-memory modes, which is actually what you get when you compile that: mov ecx,[numRows + 1] = fetching value from +1 address. 只有一些指令允许某种非常严格且有限的数学表达式,例如mov用于寻址内存模式,这实际上是在编译时得到的: mov ecx,[numRows + 1] =从+1地址获取值。 numRows is DWORD, so if the user did enter 10, the memory looks like this (starting at numRows address: 0A 00 00 00 00 00 00 00 - the first 4 bytes were set by mov numRows,eax (which Irvine writes without [] around memory reference, which is IMO very bad style/taste) 5th byte is at count address, which is defined by count DWORD 0 line, so 4 zeroed bytes. Now the mov ecx,[numRows + 1] will thus fetch the 4 zeroes from memory, starting just after the 0A byte, and "leaking" one byte into count . 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

Also math expressions are allowed in compile-time sense, ie add eax,12+13*14 is OK, producing single constant during assembling. 同样,在编译时允许使用数学表达式,即, add eax,12+13*14可以,在组装过程中生成单个常数。 But you should read through docs like this to have idea which combination of arguments is legal, mov ecx,label + 1 can be either an immediate constant load (in NASM) = "address + 1", or memory load (value from address+1) in MASM, neither doing "value + 1". 但您应该通读此类文档,以了解哪种参数组合是合法的, mov ecx,label + 1可以是立即常量加载(在NASM中)=“ address + 1”,也可以是内存加载(来自address +的值1)在MASM中,都不执行“值+ 1”。

To do what you want you need to: 要执行您想要的操作,您需要:

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

But as the eax already contains numRows value, you can avoid fetching the memory, so in this particular case this is enough: 但是由于eax已经包含numRows值,因此可以避免获取内存,因此在这种特殊情况下,这就足够了:

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

But as this math expression is trivial enough to fit one of possible addressing modes, you can exploit the LEA instruction to think it is calculating memory address, while it will just calculate your expression instead: 但是由于此数学表达式足够简单,无法适合可能的寻址模式之一,因此您可以利用LEA指令认为它正在计算内存地址,而它将只计算您的表达式:

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

This works, even if the eax+1 is illegal address into memory, but LEA will not try to read the address, it will just calculate it and store into destination register. 即使eax + 1是非法的地址进入内存,此方法仍然有效,但是LEA不会尝试读取该地址,它只会对其进行计算并存储到目标寄存器中。

...etc, etc... the point here for you is: ...等等,这里的重点是:

1) learn to debug your code (this is absolutely essential to get anywhere further) 1)学习调试您的代码(这对于进一步发展它是绝对必要的)

2) ditch the Irvine style and use [] rigorously around every memory dereference, ie around "variables", this would make you scratch your head probably sooner, if you would write mov ecx,[numRows]+1 (if you have idea which mov operands are legal, you should feel this doesn't look good). 2)放弃Irvine风格,并在每个内存取消引用时都严格使用[] ,即在“变量”周围,如果您要编写mov ecx,[numRows]+1 (如果您知道mov操作数是合法的,您应该认为这看起来不太好)。

3) try to move your thinking in terms of "variables" toward lower level "memory -> address -> content (bytes)", the "variables" way will sometimes limit you in seeing opportunities how to manipulate your data at byte/bits level to achieve results you need in simpler way. 3)尝试将“变量”方面的思考移向较低级别的“内存->地址->内容(字节)”,“变量”方式有时会限制您看到如何以字节/位操作数据的机会级别以更简单的方式获得所需的结果。

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

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