Printing star triangle in assembly

2019-07-23 12:45发布

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

Where am I going wrong?

1条回答
叼着烟拽天下
2楼-- · 2019-07-23 12:56

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 doesn't do what you think it does, you can't use math expressions in assembly, you have to write them as single instructions.

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.

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".

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:

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  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.

...etc, etc... the point here for you is:

1) learn to debug your code (this is absolutely essential to get anywhere further)

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) 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.

查看更多
登录 后发表回答