组装中打印星形三角形 [英] Printing star triangle in assembly

查看:96
本文介绍了组装中打印星形三角形的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试打印这样的三角形:组装. 查找每行星星数的公式是: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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆