2016-10-11 14 views
-3

Ich lerne Assembler-Sprache zu meiner Zeit und versuche, das folgende Problem zu lösen. Ich habe den Code geschrieben, aber es wird nicht funktionieren.Assembly Language Code Ausgabe

Schreiben eines Programms, das eine Schleife verwendet, um die ersten sieben Werte der Fibonacci-Zahl-Sequenz durch die folgende Formel beschrieben zu berechnen: Fib (1) = 1, Fib (2) = 1, Fib (n) = Fib (n-1) + Fib (n-2).

Ich brauche dieses Programm in Assembler geschrieben. Verwenden Sie die Kommentare in der Programmvorlage als Anweisungen, um den Code in Assemblersprache zu schreiben. Ich möchte das Programm im Anschluss an diese Programmierlogik in Assembler geschrieben werden:

.data 
;declare an array 
.code 
main proc 
;move 0 into ebx to initialize 
;move 1 into edx to store the first Fib value 
;move edx into an array ; store the first Fib value 

; prepare to loop 
; loop counter for 6 more values 
; move esi,4 
; array index for 3rd Fib value 

L1: 
;move ebx into eax 
;add edx and eax 
;move edx into the array of esi 
; eax = ebx 
; eax = eax + edx 
; store the Fib value 
;move edx into ebx 
; prepare for next iteration 
;move eax into edx 
;add 4 to esi 
;Loop L1 

invoke ExitProcess,0 

mein Code:

ExitProcess PROTO 

.data 

numbers DWORD 10 DUP (?) 

.code 
main PROC 
    mov ebx,0 
    mov edx,1 
    mov numbers,edx 

    mov ecx,6 
    mov esi,4 

L1: 
    mov eax,ebx 
    add eax,edx 
    mov esi,OFFSET numbers 
    mov [esi],edx 
    mov eax,ebx 
    add eax,edx 
    mov edx,ebx 
    mov eax,edx 
    add esi,4 
Loop L1 

    call ExitProcess 
main ENDP 
END 

ich meinen Code auf die folgende Änderung:

ExitProcess PROTO 

.data 

numbers DWORD 10 DUP (?) 

.code 
main PROC 
    mov ebx,0 
    mov edx,1 
    mov numbers,edx 

    mov ecx,10 
    mov esi,4 
    mov esi,OFFSET numbers 

L1: 
    mov eax,ebx 
    add eax,edx 
    mov [esi],edx 
    mov ebx,edx 
    mov edx,eax 
    add esi,4 
    Loop L1 

    call ExitProcess 
main ENDP 
END 

Als ich Beim schritt durch den code zeigen das eax-register und das edx-register die Fibonacci-Sequenzwerte an: 1, 2, 3, 5, 8, 13 usw. Allerdings speichert der code das eax-register oder den edx-registerwert in den Zahlen a fetzen? Wenn nicht, wie mache ich das.

Ist dies eine gültige Codezeile? Wird der Wert für edx im Zahlen-Array gespeichert?

Wie speichere ich den EAX- oder EDX-Wert im Zahlen-Array?

+0

Stack-Überlauf ist keine "Bitte gib mir die Codez" Art der Website. – fuz

+1

Nächstes Mal nicht Kommentare entfernen, wenn Sie Ihren Code eingeben. Vielleicht können Sie sie ein wenig komprimieren, aber halten Sie sie für Referenz und Debugging. – Ped7g

+0

'MOV-Nummern, edx' ist in MASM (TASM emuliert MASM auch). Es kompiliert zu 'mov DWORD PTR [ds: OFFSET-Nummern], edx' (ausführliche technische Art, es genau zu beschreiben). Es ist gültig, aber verwirrend und fugig, weil es den '[]' (Speicherzugriff) vom Leser der Quelle versteckt!Ihre neue Bearbeitung ist fast korrekt, mit leichtem Haken, wenn Sie sie debuggen und die Speicher- und 'esi'-Werte ansehen und mit' OFFSET-Nummern' vergleichen, werden Sie es bald beheben, Sie sind in der Nähe. – Ped7g

Antwort

0

Einige Probleme im Code:

mov esi,OFFSET numbers 
mov [esi],edx 

Dies wird esi vor jeder init schreiben, so dass Sie das Element "numers [0]" Überschreiben werden die ganze Zeit.

mov eax,ebx 
add eax,edx 
mov edx,ebx 
mov eax,edx 

Das macht nicht viel Sinn machen ... erste berechnen Sie eax = ebx+edx ... zweiten Mal (EAX bereits dieser Wert aus früheren Zeilen enthält).

Dann tun Sie eax = edx = ebx; (dh Sie kopieren ebx in beide EAX und EDX.) Sie wollten wahrscheinlich es anders herum tun, wie: mov ebx,edx mov edx,eax.

Das „move esi, 4“ von der ursprünglichen Kommentare wenig Sinn machen, wäre es ein Gefühl wie add esi,4 machen, würden Sie hatte bereits numbers Adresse in esi (wie der nächste Code der Fall ist).

Aber es sieht so aus, als ob Sie nicht verstanden haben, welche Adresse ist, also laden Sie die Adresse in "fib the fib value" immer wieder. Der springende Punkt besteht darin, esi nur einmal an den Anfang des Arrays zu setzen und dann den Zeiger nach jedem Schreibvorgang zu aktualisieren, um auf den nächsten freien Speicherplatz zu zeigen.


Insgesamt einige Debugger und beginnen die Register und Speicher Schritt für Schritt nach jeder Anweisung zu beobachten, vergleichen Sie es mit jedem Befehl Beschreibung, bis es Ihnen vertraut bekommen, was sie tun, sieht es aus dem Code Sie haben keine Ahnung, was diese Anweisungen tatsächlich tun.


Und nun versuchen, dies zu verstehen:

mov esi,OFFSET numbers ; esi = target array address 
    mov ecx,7 ; produce seven numbers 
    xor ebx,ebx ; ebx = 0 F(-1) 
    mov edx,1 ; edx = 1 F(0) 
    jmp store_number 
loop1: 
    add ebx,edx ; ebx: F(n) = edx: F(n-1) + ebx: F(n-2) 
    xchg ebx,edx ; ebx: F(n-1), edx: F(n) 
store_number: 
    mov [esi],edx ; array_pointer[0] = F(n) 
    add esi,4  ; ++array_pointer 
    loop loop1 

Beachten Sie auch, wie viele Anweisungen, um die reinen Papier Formel Arbeit tun ("F (n) = F (n-1) + F (n -2) ") und" 7 Zahlen "und wie viele Anweisungen gibt es nur, um die Sache zu unterstützen. Du magst dem nicht zustimmen, aber ich würde das sagen, cca. 50% ist "support cruft", das meiste davon ist direktes Papier -> Code-Neufassung.

Denken Sie daran beim Lernen der Montage, stellen Sie sicher, Sie haben zuerst sehr klare Idee, was Sie auf Formelebene erreichen wollen, dann versuchen Sie , dass ... fügen Sie Support-Code nur wenn absolut notwendig. Schreib nicht nur ein paar zufällige Anweisungen herum, denn es sieht nach einer guten Idee aus oder du hast es so geschrieben. Anweisung entweder "tut etwas, was Sie wollen", oder es ausschneiden.


bearbeiten auf Kommentar:

mov esi,OFFSET numbers speichert Adresse des Symbols "Zahlen" in esi. Es ist nicht wichtig, wenn Sie numbers als BYTE oder DWORD deklarierten, die Adresse zeigt an der ersten Speicherstelle (erstes Byte) des Speichers.

Das Byte/dword/dup ist wichtig, um genügend Speicherplatz zu reservieren, hat aber keinen Einfluss auf die Adresse selbst ("Symbol").

mov [aaa],vvv speichert den Wert "vvv" im Speicher unter der Adresse "aaa" (siehe die Bedienungsanleitung, um die möglichen Kombinationen zu sehen).

So mov [esi],edx direkt nach mov esi,OFFSET numbers speichert jeden Wert bei "Zahlen [0]". Schauen Sie im Debugger nach, wie esi jedes mal von diesem mov esi,OFFSET numbers zurückgesetzt wird.

Und bitte Marotte Syntax mov numbers,edx nicht verwenden, dass speichert Wert in „Zahlen“ Array nur in MASM (und TASM wenn MASM Quirks-Modus emuliert), in der richtigen Intel-Syntax die Verwendung von [] Signalen Dereferenzierung Zeiger/Adresse, So ist es beim Lesen der Quelle einfach zu sagen, ob der Befehl nur mit Register/Sofortwert arbeitet oder ob er auf den Speicher zugreift. (lea reg,[address] ist Ausnahme, die nicht auf Speicher zugreift, berechnet nur die Adresse). In NASM würde die mov numbers,edx überhaupt nicht kompilieren, und mov edx,numbers würde ersten Wert von Array nicht laden, aber die Adresse selbst (in MASM/TASM müssen Sie OFFSET vor Symbol schreiben).

So

"wird der Code speichert den EAX-Register Wert im Array Zahlen?"

Nein, es überschreibt nur den ersten Wert numbers[0].

+0

bearbeitet ich meinen Code auf die folgenden: (?) – ISM34

+0

Exitprocess PROTO .data Zahlen DWORD 10 DUP .code Haupt PROC \t mov ebx, 0 \t mov edx, 1 \t mov Zahlen, edx \t mov ECX, 10 \t mov esi, 4 L1: \t mov eax, ebx \t eax hinzuzufügen, EDX \t mov esi, OFFSET Zahlen \t mov [esi], EDX \t mov ebx, EDX \t mov EDX, eax \t hinzufügen esi, 4 \t Schleife L1 \t Anruf Exitprocess Haupt ENDP END – ISM34

+0

Wenn ich Wenn Sie durch den Code gehen, zeigt das EAX-Register die Fibonacci-Sequenzwerte an: 1, 2, 3, 5, 8, 13, usw. Aber speichert der Code den Wert des eax-Registers im Zahlen-Array? Wenn nicht, wie mache ich das. – ISM34