组装中打印星形三角形 [英] Printing star triangle in assembly
问题描述
我正在尝试打印这样的三角形:组装. 查找每行星星数的公式是:2 * x + 1. 到目前为止,这是我的代码.我似乎无限循环.
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. 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
我要去哪里错了?
推荐答案
虽然答案不完整,但发表评论的时间太长了,应该会为您提供极大的帮助,因为:
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
这基本上是您应该首先学习的内容(并且太宽泛,太长,无法成为此答案的一部分).
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
并没有按照您的想象做,您不能在汇编中使用数学表达式,而必须将它们作为单个指令编写.
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
具有寻址内存模式,这实际上是在编译时得到的: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
.
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. 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
.
在编译时也允许使用数学表达式,即add eax,12+13*14
可以,在汇编过程中生成单个常量.但是您应该通读此之类的文档,以了解哪种参数组合是合法的, mov ecx,label + 1
可以是立即恒定负载(在NASM中)=地址+ 1",也可以是MASM中的内存负载(在地址+ 1中的值),都不做值+ 1".
Also math expressions are allowed in compile-time sense, i.e. add eax,12+13*14
is OK, producing single constant during assembling. 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,[numRows] ; load the VALUE numRows back into ecx
inc ecx ; ecx = numRows+1
但是由于eax已经包含numRows
值,因此可以避免获取内存,因此在这种特殊情况下就足够了:
But as the eax already contains numRows
value, you can avoid fetching the memory, so in this particular case this is enough:
mov ecx,eax ; copy the numRows value from eax into ecx
inc ecx ; ecx = numRows+1
但是由于此数学表达式足够简单,无法适合可能的寻址模式之一,因此您可以利用 LEA
指令认为它正在计算内存地址,而只会计算您的表达式:
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 ecx,[eax+1] ; ecx = value_numRows + 1
这是可行的,即使eax + 1是非法的地址进入内存,但LEA
不会尝试读取该地址,它只会计算该地址并将其存储到目标寄存器中.
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.
...等等,这里的重点是:
...etc, etc... the point here for you is:
1)学习调试代码(这对于进一步开发它绝对是必不可少的)
1) learn to debug your code (this is absolutely essential to get anywhere further)
2)放弃Irvine风格,并在每个内存取消引用周围(即在变量"周围)严格使用[]
,如果您编写mov ecx,[numRows]+1
(如果您知道哪个mov
操作数是合法的,您应该觉得这不太好.
2) ditch the Irvine style and use []
rigorously around every memory dereference, i.e. 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).
3)尝试将您对变量"的思考移向较低级别的内存->地址->内容(字节)",变量"方式有时会限制您看到如何操作数据的机会字节/位级别以更简单的方式获得所需的结果.
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.
这篇关于组装中打印星形三角形的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!