Frage

Ich versuche Montag zu lernen (so mit mir tragen), und ich bin auf dieser Linie einen Compiler-Fehler bekommen:

mov byte [t_last], [t_cur]

Der Fehler ist

error: invalid combination of opcode and operands

Ich vermute, dass die Ursache für diesen Fehler ist einfach, dass es nicht möglich, dass eine mov Anweisung zwischen zwei Speicheradressen zu bewegen, aber einem halben Stunde googeln und ich habe nicht in der Lage, dies zu bestätigen - ist dies der Fall?

Auch unter der Annahme, ich Recht habe, das bedeutet, dass ich ein Register als Zwischenpunkt zum Kopieren von Speichern verwenden muß:

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

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

War es hilfreich?

Lösung

Ihre Vermutung richtig ist, können Sie nicht aus dem Speicher in den Speicher bewegen.

Jedes Allzweckregister tun wird. Denken Sie daran, das Register zu drücken, wenn Sie nicht sicher sind, was drin ist und wiederherstellen es wieder einmal getan.

Andere Tipps

Es ist in 16-Bit wirklich einfach ist, einfach wie folgt vor:

     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 neceessary, wenn Sie die Inhalte der Register speichern müssen

.

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

MOV SI, OFFSET variable1
MOV DI, OFFSET variable2
MOVS

Es ist technisch möglich, aus dem Speicher in den Speicher zu bewegen.

Versuchen Sie es mit MOVS (move string) und Einstellung [E] SI und [E] DI , je nachdem, ob Sie wollen Byte übertragen (s), (e), etc.

mov si, t_cur    ; Load SI with address of 't_cur'
mov di, t_last   ; Load DI with address of 't_last'
movsb            ; Move byte from [SI] to [DI]

; Some dummy data
t_cur    db 0x9a ; DB tells NASM that we want to declare a byte
t_last   db 0x7f ; (See above)

Dies ist weniger effizient als eine normale Last + Shop mit einem temporären Register verwenden, aber es funktioniert mit einem einzigen Befehl die aktuelle Kopie tun.

Hier ist, wie MOVS verwendet werden soll, und wie es funktioniert: https://www.felixcloutier.com/x86/movs:movsb: MOVSW: movsd: movsq

Es ist normalerweise nur mit einem rep Präfix für Blockkopien, nicht für ein einzelnes Element verwendet. (Moderne CPUs haben ziemlich effizientes Mikro für rep movsb, dass es in der Nähe der Geschwindigkeit einer Schleife mit AVX Vektor Lade- / Speicherbefehlen.)

Das ist richtig, Code x86 Maschine kann nicht eine Anweisung mit zwei expliziter Speicheroperanden (beliebigen Adressen angegeben in [])

kodieren
  

Was ist das empfohlene Register

Alle registrieren Sie nicht speichern müssen / wiederherstellen.

In allen Mainstream-32-Bit- und 64-Bit-Aufrufkonventionen, EAX, ECX und EDX sind Call-clobbered, so AL, CL und DL sind eine gute Wahl. Für ein Byte oder ein Wort zu kopieren, mögen Sie in der Regel eine movzx Last in ein 32-Bit-Register, dann ein 8-Bit oder 16-Bit-Speicher. Dies vermeidet eine falsche Abhängigkeit von dem alten Wert des Registers. Nur eine schmale 16 oder 8-Bit-mov Last verwenden, wenn Sie aktiv wollen fusionieren in die Low-Bits eines anderen Wertes. x86 der movzx ist das Analogon von Anweisungen wie ARM ldrb.

    movzx   ecx,  byte [rdi]       ; load CL, zero-extending into RCX
    mov    [rdi+10], cl

In 64-Bit-Modus, SIL, DIL, R 8b, R 9b und so weiter ist auch feine Auswahl, erfordert aber einen REX-Präfix in dem Maschinencode für den Laden so gibt es einen kleinere Codegröße Grund, sie zu vermeiden.

Generell vermeiden Schreiben AH, BH, CH oder DH aus Performance-Gründen, es sei denn, Sie gelesen haben und verstanden die folgenden Links und keine falschen Abhängigkeiten oder Teilregisterstände Verschmelzung werden nicht ein Problem sein, oder überhaupt passieren in Ihrem Code.


  

(oder soll ich den Stapel statt)?

Zunächst einmal können Sie nicht ein einziges Byte an alle drücken, so gibt es keine Möglichkeit, ein Byte-Lade- / Byte Speicher vom Stapel tun könnte. Für ein Wort, dword oder qword (abhängig von der CPU-Modus), könnten Sie push [src] / pop [dst], aber das ist viel langsamer als über ein Register zu kopieren. Es stellt eine zusätzliche Speicher / Reload-Store-Weiterleitung Latenz, bevor die Daten aus dem endgültigen Bestimmungsort gelesen werden können, und mehr Uops nimmt.

Es sei denn, irgendwo auf dem Stapel ist das gewünschte Ziel und Sie können nicht, dass die lokale Variable in ein Register optimieren, wobei in diesem Fall push [src] gerade fein ist es dort zu kopieren und Stapelspeicherplatz für es zuweisen.

finden Sie unter https://agner.org/optimize/ und anderen x86-Performance-Links in die x86-Tag Wiki

Ich will nur „Memory-Barriere“ mit Ihnen besprechen. In C-Code

a = b;//Take data from b and puts it in a

würde zu montierenden

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

Das System kann die Unteilbarkeit der Abtretung nicht garantieren. Deshalb haben wir eine rmb brauchen (Lesesperre)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top