2017-05-01 4 views
0

Ich habe versucht, eine Prozedur zu schreiben, die den größten Wert in einem Wortarray zurückgibt. Ich habe lokale Variable nach Konvention aufgeführt here zugeordnet. Aber wenn ich versuche, einen Wert in lokalen Variablen zu bewegen es gibt mir diese Fehlermeldung:Nasm Montage. Ein Wert kann nicht in eine lokale Variable auf dem Stapel verschoben werden

invalid combination of opcode and operands

Hier ist mein Code:

greatest: 

    push ebp 
    mov ebp, esp 
         ;allocate local variables here 
    sub esp, 4 
         ;push stuff 
    push esi 

    mov ecx, [ebp+12] ;size of the array 
    mov eax, [ebp+8] ;offset of the array 
    mov esi, 0   ;counter for accessing elements 
    mov ebp-4, eax  ;error here 
l1: 
    push ecx 
    mov ecx, [eax + 2*esi] ;get the variable 
    cmp [ecx], [ebp-4]  ;compare values 
    jb if_2     
    mov ebp-4, ecx  ;error here 
if_2: 
    inc esi 
    pop ecx 
    loop l1 

    mov eax, [ebp-4] 

    pop esi 
    mov esp, ebp 
    pop ebp 
    ret 

Jede Hilfe wäre sehr dankbar :)

+3

'cmp [ecx], [ebp-4]' Sie können Mem mit Mem nicht vergleichen –

+0

@Alexander Zhak Aber es ist in der Registrierung, richtig? Und Compiler scheint das nicht zu kümmern. Ich möchte anmerken, dass in einer bestimmten Verbindung MASM verwendet wird und da 'mov ebp-4, eax' funktioniert gut. In NASM scheint es nicht. Es hat wahrscheinlich mit der Syntax für die Speicher- und Wertadressierung zu tun. –

+0

Mein MASM weigert sich, 'mov ebp-4, eax' zu montieren. "* Fehler A2032: ungültige Verwendung von Register *". – rkhb

Antwort

0

Wie in den Kommentaren darauf hingewiesen, sind die Probleme in Ihrem Code mit dem Unterschied zwischen umgebenden Sachen von und nicht.

In den von nasm angegebenen Zeilen hat das Problem keine Klammern. ebp - 4 ist ein Speicherort im Speicher, in dem Sie die Daten speichern möchten. Sie müssen ihn also mit Klammern umgeben.

Ein anderes Problem ist mit der Linie cmp [ecx], [ebp - 4]. Dies wird nicht kompiliert, weil es versucht, zwei verschiedene Elemente im Speicher an den Positionen ecx und ebp - 4 zu vergleichen, und Sie können es nicht mit zwei verschiedenen Speicher-Dingen tun (mindestens eins muss ein Register/Konstante sein).

Dies ist jedoch nicht wirklich das, was Sie sowieso tun möchten. Da ecx den Wert speichert, nicht den Standort, möchten Sie wirklich cmp ecx, [ebp - 4]. Das ist richtig.

Sobald Sie diese Dinge ändern, wird Ihr Code kompilieren. Es wird jedoch nicht korrekt ausgeführt. Während nasm es mag, gibt es immer noch Probleme mit Klammern vs keine Klammern.

Die letzte Ausgabe, die ich sehe, ist wieder mit der (zuvor mov ebp - 4, eax) Linie. Während eax den Offset (Adresse) der Liste enthält und daher die Adresse des ersten Elements, enthält es dieses Element nicht selbst, also muss es auch in Klammern eingeschlossen sein.

Allerdings nur mov [ebp - 4], [eax] erzeugt einen ähnlichen Fehler wie zuvor: nasm schreit Sie an, weil Sie nicht zwei Speicher Dinge drin haben können.

Wir können dies beheben, indem Sie ein Register (z. B. esi) als temporären Speicher verwenden. (Ich wählte esi, weil wir es trotzdem sind überschreiben, so dass wir haben es nicht auf dem Stapel zu speichern.) So wird daraus:

mov esi, [eax] 
mov [ebp-4], esi 
mov esi, 0  ; moved this line from above so it's still 0 at the end 

Also alles in allem, mit den Änderungen wird daraus:

greatest: 

    push ebp 
    mov ebp, esp 
         ;allocate local variables here 
    sub esp, 4 
         ;push stuff 
    push esi 

    mov ecx, [ebp+12] ;size of the array 
    mov eax, [ebp+8] ;offset of the array 
    mov esi, [eax]  ;store in esi temporarily 
    mov [ebp-4], esi ;now we can move it to the local variable 
    mov esi, 0   ;counter for accessing elements 

l1: 
    push ecx 
    mov ecx, [eax + 2*esi] ;get the item from the list 
    cmp ecx, [ebp-4]  ;compare values 
    jb if_2     
    mov [ebp-4], ecx  
if_2: 
    inc esi 
    pop ecx 
    loop l1 

    mov eax, [ebp-4] 

    pop esi 
    mov esp, ebp 
    pop ebp 
    ret 
+0

Vielen Dank! Das wirft ein Licht auf die Speicher-/Registry-Handhabung. Ich habe mich mit der unterschiedlichen Syntax von MASM- und NASM-Speicherzugriff verwechselt und vergessen, wo was eigentlich gespeichert ist. Die Antwort ist sehr nützlich. Danke noch einmal! –

Verwandte Themen