2010-04-12 2 views
14

Ich beginne gerade ARM Assembler Sprache zu studieren, und bin nicht klar darüber, wie MOV verwendet wird, um eine unmittelbare Zahl in ein Register zu übertragen.So verwenden Sie MOV-Anweisung in ARM mit einer direkten Nummer als zweiter Operand

Sowohl aus dem ARM-Referenzhandbuch als auch aus meinem Lehrbuch wird gesagt, dass der Bereich der direkten Nummer nach MOV-Befehl 0-255 ist. Aber wenn ich auf meinem eigenen PC in ADS 1.2 IDE teste, funktioniert die Anweisung

gut. Ist die Nummer 0xFFFFFFFF laut Spezifikation nicht im zulässigen Bereich?

Hoffe jemand kann mir eine Hand geben.

Grüße.

Antwort

12

, dass der Arm einen bestimmten Satz von Manipulationen auf dem unmittelbaren Wert als Teil des barrel shifter durchführen kann, die in den Arm des Opcodes aufgenommen ist.

Dieser kleine Artikel hat eine der klarsten Erklärungen einige der Tricks, die ein ARM-Assembler verwenden können, eine große sofortige Zahl in den kleinen verfügbaren Raum einer ARM-Anweisung passen:

Der Artikel beschreibt den Trick, der wahrscheinlich in Ihrem speziellen Beispiel zum Generieren eines MVN-Opcodes verwendet wird, um das bitweise Komplement des unmittelbaren Werts zu laden.

Diese Art der Manipulation kann nicht mit allen unmittelbaren Werten durchgeführt werden, aber die ARM-Assembler sind angeblich ziemlich schlau (und C-Compiler sind es sicherlich). Wenn keine Shift-/Komplement-Tricks ausgeführt werden können, wird der Wert im Allgemeinen von einer PC-relativen Position geladen oder möglicherweise durch "Aufbauen" des Werts aus mehreren Anweisungen.

+0

@Michael Danke für Ihre Tipps. Das will ich wissen! :-) –

+0

Weiß jemand, warum der Assembler einige Werte aufbaut, aber andere direkt lädt? Beim Umsehen des Newton ROM-Codes (StrongArm 110) gibt es viele "one-instructon loads" (wie "MOV r1, 0x0c1b518"), aber mein gesamter Code kommt mit "Aufbauladungen" aus - wie der folgende Code: –

+0

.. (oops, früher Buchungsfehler) .. wie "MOV r1, 0x0C000000/ADD r1, r1,0x100000". Ich nehme an, dies könnte etwas damit zu tun haben, genau wie der Prozessor 32-Bit-Werte codiert. Ist es effizienter für den Prozessor-Mikrocode, Zahlen mit einem einzigen MOV und dann mit ADDs aufzubauen? –

-1

Eine Möglichkeit ist, dass der ARM-Assembler die signifikanten Bits der Zahl wegwirft und nur das niedrigste FF verwendet.

Die MOV-Anweisung ist eine Klammer in vielen CPU-Befehlssätzen, und normalerweise löst der Assembler die Größe des Zielregisters und den unmittelbar gelieferten Wert auf.

Zum Beispiel die folgenden MOV Anweisungen von der x86-Reihe sind

MOV BL, 80h, ; 8bit 
MOV BX, ACACh ;16bit 
MOV EBX, 12123434h ; 32bit 
1

Sie sehen Artefakte aus Zeichen-Erweiterung des ursprünglichen Wertes werden kann. Wenn die Werkzeuge, die Sie zum Anzeigen der Disassemblierung verwenden, die 0..255 als vorzeichenbehaftetes Byte behandeln, füllt sie beim Laden in einen größeren int-Typ (oder Register) alle oberen Bits mit dem Vorzeichenbit des Originals Wert. Oder anders ausgedrückt, wenn 0xFF ein vorzeichenbehaftetes Byte ist, ist sein Dezimalwert -1. Setzen Sie das in ein 32-Bit-Register und das Hex wird wie 0xFFFFFFFF aussehen, und sein Dezimalwert ist immer noch -1.

Versuchen Sie, einen Wert ohne gesetztes High-Bit zu verwenden, z. B. 0x7F. Da das Vorzeichenbit nicht gesetzt ist, nehme ich an, dass es die oberen Bits mit Null füllt, wenn es in ein größeres Register oder Feld vom Typ int geladen wird.

Es ist auch möglich, dass der Compiler/Assembler den von Ihnen angegebenen Wert abschneidet. Ich würde es als einen Quellcode-Fehler betrachten, aber Assembler sind lustige Bestien. Wenn Sie es 0x7FF geben, kompiliert es zu 0x7FF (nicht abgeschnitten und größer als 0..255) oder zu 0xFFFFFFFF (abgeschnitten auf 0..255, signiertes Byte)? Denken Sie daran,

11

Ein einzelner ARM-Befehl kann nur eine direkte Konstante codieren, die als 8-Bit-Sofortwert dargestellt werden kann und um eine beliebige Zweierpotenz sogar verschoben werden kann. Es gibt aber auch einen MVN Befehl, der wie MOV ist, aber alle Bits invertiert. Während also MOV R2, #0xFFFFFFFF nicht als MOV-Anweisung codiert werden kann, kann sie als MVN R2, #0 codiert werden. Der Assembler kann diese Konvertierung für Sie durchführen.

1

Es ist etwas schwer zu bestimmen, ob die gegebenen Konstanten innerhalb des gültigen Bereichs liegen.

Wie Matthew bereits erwähnt, ist der Assembler verleiht Ihnen Hand von Anweisungen mit ähnlichen ersetzt, diejenigen zu negieren, wie mov/MVN, cmp/cmn, tst/tne usw.

2

MOV-Befehl kann entweder imm16 Wert annehmen oder operator2 Wert (aufgrund Befehlslänge zur Speicherausrichtung entgegengesetzt), die eine der folgenden Vorschriften entsprechen müssen (kopiert aus CortexM Befehlssatz manuell, X und Y eine beliebige hex-Wert):

  • jede konstante, die sein kann, erzeugt durch Verschieben eines 8-Bit-Wertes, der von einer beliebigen Anzahl von Bits innerhalb eines 32-Bit-Worts von übrig ist.
  • Jede Konstante der Form 0x00XY00XY.
  • Jede Konstante der Form 0xXY00XY00.
  • Jede Konstante der Form 0xXYXYXYXY.

Aus diesem Grund wird 0xFFFFFFFF akzeptiert (entspricht der 4. Regel). Wenn Sie Ihre eigene 32-Bit-Konstante zusammenstellen möchten, können Sie die Anweisung MOVT verwenden, die in die obere Hälfte eines Registers schreibt.

+0

Warum sollte es dann nicht 0x45454545 zulassen? Eigentlich sogar 0x00450045. – JSmyth