2009-08-19 11 views
16

Ich versuche assermbly zu lernen (so mit mir tragen), und ich bin auf dieser Linie einen Compiler-Fehler erhalten:Montage: Der Wechsel zwischen zwei Speicheradressen

mov byte [t_last], [t_cur] 

Der Fehler ist

error: invalid combination of opcode and operands 

Ich vermute, dass die Ursache dieses Fehlers einfach ist, dass es nicht möglich ist, dass eine mov-Anweisung zwischen zwei Speicheradressen wechselt, aber eine halbe Stunde googeln und ich konnte dies nicht bestätigen - ist das der Fall?

Auch vorausgesetzt, ich bin richtig, dass heiße, ich brauche ein Register als Zwischenpunkt zum Kopieren von Speicher zu verwenden:

mov cl, [t_cur] 
mov [t_last], cl 

Was ist das empfohlene Register zu verwenden (oder soll ich den Stapel statt)?

+3

Manchmal ist besser gehen Sie auf die * source * statt googeln, hier zum Beispiel ist Intel 64 & IA-32 Anweisungen AM, wo Sie Operand-Kombinationen für 'mov' sehen können http://www.intel.com/Assets/PDF/manual/253666.pdf –

+0

Es gibt Ausnahmen von der Regel, dass ein Befehl nicht zwei Speicheroperanden aufnehmen kann; siehe [hier] (http://stackoverflow.com/questions/14510280/why-cant-mov-have-both-operands-as-memory-locations?lq=1#comment20229305_14510280). – legends2k

Antwort

21

Ihr Verdacht ist richtig, Sie können nicht von Speicher zu Speicher wechseln.

Jedes allgemeine Register wird ausreichen. Denken Sie daran, das Register zu drücken, wenn Sie nicht sicher sind, was sich darin befindet, und es wieder herzustellen, sobald Sie fertig sind.

+0

Gibt es einen Vorteil, ein Register zu verwenden, um die Daten selbst auf den Stapel zu schieben? – Justin

+2

Durch Drücken auf und späteres Aufheben des Stapels werden zwei zusätzliche Speicherzugriffe hinzugefügt. – hirschhornsalz

3

Es gibt auch einen MOVS Befehl von Daten aus dem Speicher in den Speicher zu bewegen:

MOV SI, OFFSET variable1 
MOV DI, OFFSET variable2 
MOVS 
+0

Funktioniert, aber es erfordert besondere Vorsicht: Sie müssen si und di Register speichern. Ich denke, es lohnt sich nicht, ein Byte zu kopieren. – sharptooth

+5

Die String-Befehle auf x86 können als veraltet betrachtet werden. Benutze sie niemals. Sie sind nie schneller als das Kopieren "von Hand", aber in den meisten Fällen viel langsamer. – hirschhornsalz

+0

@hirschhornsalz, Entschuldigung zur Nekromanz, aber haben Sie detaillierte Informationen darüber, dass die String-Befehle im Wesentlichen veraltet sind? –

4

Es in 16-Bit wirklich einfach ist, machen Sie einfach folgendes:

 push  di 
    push  si 
    push  cx 
    mov  cx,(number of bytes to move) 
    lea  di,(destination address) 
    lea  si,(source address) 
    rep  movsb 
    pop  cx 
    pop  si 
    pop  di 

Hinweis: Die Schübe & Pops sind notwendig, wenn Sie den Inhalt der Register speichern müssen.

+0

+1, da es unter bestimmten Umständen gut ist, alle Werkzeuge in Ihrer Toolbox zu kennen.rep movsb/movsw sind 1 Byte Opcodes, IIRC –

+0

Abhängig von der Architektur können Sie pusha verwenden, anstatt alle Register einzeln zu drücken und popa, anstatt sie alle zu öffnen. – BalinKingOfMoria

+0

Dies funktioniert auch in 32 und 64 Bit, außer dass es die Register für dieses Bitsystem verwendet – Rahly

-2

Ich möchte nur "Speicherbarriere" mit Ihnen diskutieren. In c Code

a = b; 

würde

mov %eax, a # suppose %eax is used as the temp 
mov b, %eax 

Das System kann nicht garantieren, die Unteilbarkeit der Zuweisung zusammengebaut werden. Deshalb brauchen wir einen rmb (lesen Sie die Schranke)

+0

X86 kann nicht automatisch aus dem Speicher in den Speicher kopieren. Barrieren erzeugen keine Atomizität, sie hören nur mit der Neuordnung auf (Kompilierzeit oder Laufzeit oder beides, abhängig von der Barriere). –

Verwandte Themen