簡體   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