2017-07-25 5 views
1

Ich versuche, ein Dreieck wie folgt zu drucken: in assembly. Die Formel, um die Anzahl der Sterne in jeder Zeile zu finden ist: 2 * x + 1. Hier ist mein Code so weit. Ich scheine endlos zu schleifen.Drucken Stern Dreieck in Assembly

.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 

Wohin gehe ich falsch?

Antwort

2

Während dies nicht die volle Antwort ist, wurde es zu lang für einen Kommentar, und es soll Ihnen helfen enorm, denn:

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

Diese im Grunde die Sache ist, sollten Sie zuerst studieren (und zu breit + lang, um ein Teil dieser Antwort zu sein).


Nachdem Sie wissen, wie Debugger zu verwenden, kann nehmen Sie einen Blick, was Ihr Code tut, zum Beispiel eines der ersten Probleme werden Sie getroffen:

mov ecx,numRows + 1 nicht tut, was Sie denken, es Wenn Sie mathematische Ausdrücke nicht in der Assembly verwenden möchten, müssen Sie sie als einzelne Anweisungen schreiben.

Nur einige Anweisungen erlauben eine sehr strenge und begrenzte mathematische Ausdruck, wie mov hat für die Adressierung-Speicher-Modi, was ist eigentlich, was Sie bekommen, wenn Sie das kompilieren: mov ecx,[numRows + 1] = Wert von +1 Adresse abrufen. numRows ist DWORD, also, wenn der Benutzer 10 eingegeben hat, sieht der Speicher so aus (beginnend mit numRows Adresse: 0A 00 00 00 00 00 00 00 - die ersten 4 Bytes wurden von mov numRows,eax (die Irvine schreibt ohne [] um Speicherreferenz, die IMO ist sehr schlecht Stil/Geschmack) 5. Byte ist count Adresse, die durch count DWORD 0 Linie definiert ist, so 4 Byte auf Null gesetzt. Nun ist die mov ecx,[numRows + 1] wird die 4 Nullen aus dem Speicher so holen, beginnend kurz nach dem 0A Byte und „undichten“ einen Byte in count.

Auch mathematische Ausdrücke sind im Sinne der Kompilierung erlaubt, dh add eax,12+13*14 ist in Ordnung, es entsteht eine einzige Konstante während der Assemblierung, aber Sie sollten Dokumente wielesen, um eine Idee zu haben, welche Kombination von Argumenten legal ist, kann mov ecx,label + 1 entweder eine sofortige konstante Last (in NASM) = "Adresse + 1" oder Speicherlast (Wert von Adresse + 1) in MASM sein, weder "Wert + 1" tun .

zu tun, was Sie wollen, müssen Sie:

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

Aber wie das EAX bereits numRows Wert enthält, können Sie vermeiden, dass die Speicher zu holen, so dass in diesem speziellen Fall das genug ist:

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

Da dieser mathematische Ausdruck jedoch trivial genug ist, um in einen der möglichen Adressierungsmodi zu passen, können Sie die LEA instruction verwenden, um zu denken, dass er die Speicheradresse berechnet, während er stattdessen nur Ihren Ausdruck berechnet:

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

Dies funktioniert, auch wenn die EAX + 1 ist illegal Adresse in dem Speicher, aber LEA wird nicht versuchen, die Adresse zu lesen, wird es einfach berechnen und speichern in Zielregister.

... etc, etc ...der Punkt ist für Sie da:

1) lernen Sie den Code zu debuggen (dies absolut notwendig ist überall weiter zu kommen)

2) den Irvine Stil Graben und [] rigoros um jeden Speicher dereferenzieren zu verwenden, also um " Variablen ", das würde Sie wahrscheinlich schneller Ihren Kopf kratzen, wenn Sie schreiben würden (wenn Sie eine Idee haben, welche mov Operanden legal sind, sollten Sie das Gefühl nicht gut aussehen).

3) versuchen Sie, Ihr Denken in Begriffen von "Variablen" zu niedrigeren Ebene "Speicher -> Adresse -> Inhalt (Bytes)" zu bewegen, wird die "Variablen" Art Sie manchmal Möglichkeiten sehen, wie Sie Ihre Daten manipulieren auf Byte/Bit-Ebene, um Ergebnisse zu erzielen, die Sie auf einfachere Weise benötigen.

+1

Ich wünschte, ich könnte eine andere Upvote tun, nur für den Kommentar "Graben Sie den Irvine-Stil und verwenden [] rigoros" – Tommylee2k