Wie wird ein relativer JMP (x86) in einem Assembler implementiert?

8

Beim Erstellen meines Assemblers für die x86-Plattform sind beim Codieren der Anweisung JMP einige Probleme aufgetreten:

%Vor%

( von meiner Lieblings-x86-Instruktionswebsite, Ссылка )

Alle sind relative Sprünge, wobei die Größe jeder Codierung (Operation + Operand) in der dritten Spalte liegt.

Jetzt hat mein ursprüngliches (und deshalb Fehler) Design den maximalen (5 Bytes) Platz für jeden Befehl reserviert. Der Operand ist noch nicht bekannt, weil es ein Sprung zu einem noch unbekannten Ort ist. Also habe ich einen "rewrite" -Mechanismus implementiert, der die Operanden an der richtigen Stelle im Speicher neu schreibt, wenn der Sprung bekannt ist, und den Rest mit NOP s füllt. Dies ist ein ernsthaftes Problem in engen Schleifen.

Jetzt ist mein Problem mit der folgenden Situation:

%Vor%

Das Problem ist, dass ich die kleinstmögliche Kodierung für eine JMP Anweisung (und keine NOP Füllung) möchte.

Ich muss die Größe der Anweisung bei c kennen, bevor ich den relativen Abstand zwischen a und b für den Operanden bei d berechnen kann. Dasselbe gilt für die JMP at c : Sie müssen die Größe von d kennen, bevor sie den relativen Abstand zwischen e und a berechnen kann.

Wie lösen bestehende Assemblierer dieses Problem oder wie würden Sie dies tun?

Das ist, was ich denke, das das Problem löst:

  

Zuerst kodiere alle Befehle, um zwischen dem JMP und seinem Ziel zu operieren, wenn diese Region einen Opcode mit variabler Größe enthält, verwende die maximale Größe, z. 5 für ein JMP . Dann kodiere das relative JMP zu seinem Ziel, indem du die kleinste mögliche Kodierungsgröße wählst (3, 4 oder 5) und den Abstand errechnest. Wenn ein Opcode mit variabler Größe codiert ist, ändern Sie alle absoluten Operanden vor und alle relativen Befehle, die diese codierte Anweisung überspringen: Sie werden neu codiert, wenn sich ihr Operand ändert, um die kleinstmögliche Größe zu wählen. Diese Methode endet garantiert, da Opcodes mit variabler Größe nur schrumpfen können (weil sie die maximale Größe verwenden).

Ich frage mich, vielleicht ist das eine überentwickelte Lösung , deshalb stelle ich diese Frage.

    
Pindatjuh 11.05.2010, 21:23
quelle

2 Antworten

1

Hier ist ein Ansatz, den ich verwendet habe, der vielleicht ineffizient erscheint, aber sich als nicht für den meisten echten Code (Pseudocode) erweist:

%Vor%     
500 - Internal Server Error 11.05.2010, 22:21
quelle
3

Im ersten Durchlauf haben Sie eine sehr gute Annäherung an den zu verwendenden jmp code, indem Sie eine pessimistische Bytezählung für alle Sprungbefehle verwenden.

Im zweiten Durchgang können Sie die Sprünge mit dem gewählten pessimistischen Opcode ausfüllen. Sehr wenige Sprünge könnten dann umgeschrieben werden, um ein Byte oder zwei weniger zu verwenden, nur solche, die ursprünglich sehr nahe an dem Sprungschwellwert von 8/16 Bit oder 16/32 Byte waren. Da die Kandidaten alle Sprünge von vielen Bytes sind, sind sie weniger wahrscheinlich in kritischen Schleifensituationen, so dass Sie wahrscheinlich feststellen werden, dass weitere Durchgänge wenig oder keinen Vorteil gegenüber einer Lösung mit zwei Durchgängen bieten.

    
Charles Bailey 11.05.2010 21:40
quelle

Tags und Links