Opcodes aus der Intel-Referenz



  • Hallo,
    ich möchte mir zu Lernzwecken einen kleinen Assembler für Intel-Prozessoren schreiben, also habe ich mir die Referenz heruntergeladen. Vor allem interessieren mich die Opcodes für einzelne Befehle, nur leider verstehe ich nicht ganz, wie man die aus der Tabelle ermitteln kann. Zum Beispiel habe ich nach dem Opcode für "push eax" gesucht, aber ich verstehe nicht, wie man den Wert aus der Tabelle ermitteln kann:

    [b]Opcode[/b]   [b]Instruction[/b]   [b]Description[/b]
    FF /6    PUSH r/m16    Push r/m16
    FF /6    PUSH r/m32    Push r/m32
    50+rw    PUSH r16      Push r16
    50+rd    PUSH r32      Push r32
    6A       PUSH imm8     Push imm8
    68       PUSH imm16    Push imm16
    68       PUSH imm32    Push imm32
    0E       PUSH CS       Push CS
    16       PUSH SS       Push SS
    1E       PUSH DS       Push DS
    06       PUSH ES       Push ES
    0F A0    PUSH FS       Push FS
    0F A8    PUSH GS       Push GS
    

    Ich bedanke mich schonmal recht herzlichen für Antworten!



  • eax ist ein 32-bit register also must du den opcode 50+rd benutzen.
    rd ist dabei eine zahl, die das dword register angibt. Dafür müsste in der refenrenz noch eine tabelle stehen. Da eax das erste register ist vermute ich, dass rd=0 --> 50 ist push eax



  • Nur aus dieser Tabelle kannst du das nicht ermitteln.
    Schau dich mal weiter in der Referenz um, irgendwo am Anfang muss definiert sein wofuer sowas wie "+rd" oder "r/m16" steht, wie das "instruction format" allgemein aussieht und was zB. ModR/M und SIB bytes sind.

    Ansonsten weiss ich zwar nicht, wie sicher du auf dem Gebiet Assembler schon bist, aber der x86-Befehlssatz ist vom Aufbau her sicher nicht gerade leichte Kost...



  • Vielen Dank, jetzt hab ich die Tabelle für das Instruction Format gefunden. 🙂



  • Ich hab jetzt mal über die Referenz drüber geschaut und da sind ja recht viele Instruktionen aufgeführt. Die meisten werde ich zwar sowieso nicht brauchen (SSE, MMX und so weiter), aber dennoch stellt sich mir die Frage, wie man einen Assembler effizient aufbaut. Ich dachte daran, ihn wie einen Hochsprachen-Compiler zu schreiben, aber während eine Hochsprache ja relativ wenige Keywords und Code-Konstrukte braucht, hat man beim Assembler ein paar hundert Instruktionen. Gibt es da einen speziellen Ansatz, um den Code schnell in Opcodes zu übersetzen?



  • Ich kenne mich zwar beim Compiler-Bau nicht so aus, aber wo liegt denn da das Problem? An einem effizienten Algo zum Identifizieren der Mnemonic-Strings wird es da doch wohl kaum scheitern?
    Sonst schau dir halt mal an, wie andere Assembler das machen. Gibt ja genug Open Source (nasm, gas, yasm, ...)



  • Beim Compiler kann man Rekursion nutzen, weil man ja durch Funktionen usw. Struktur in seinen Quelltext bekommt. Bei einem Assemblercode würde das womöglich in so etwas ausarten:

    while(!eof)
    {
        x = nextline();
        switch(x)
        {
            case "PUSH EAX": ...
            case "PUSH EBX": ...
            case "PUSH ECX": ...
            ...
            case "MOV Register, Register": ...
            case "MOV Register, Speicher": ...
            case "MOV Register, Register": ...
            ...
        }
    }
    

    Bei PUSH könnte man das noch vereinfachen, aber meistens ist das ja nur durchswitchen durch die verschiedenen Befehle und Kombinationen. 😕
    Aber danke für den Tipp mit den Open Source Assemblern. Werde ich mir mal anschauen. 🙂



  • Naja...
    Das mit dem "Durchswitchen" ist natuerlich reichlich primitiv, da kann man auch durchaus mit mehr Feingefuehl rangehen. Vollkommen unsystematisch ist der x86-Code ja nun auch nicht.
    Ansonsten gibt es ja auch durchaus Assembler, die sehr viele Hochsprachenelemente implementieren, wie zB. der MASM.
    Mit Rekursion ist da zwar meistens nicht unbedingt geschickt zu arbeiten, aber das duerfte beim Compiler letztendlich ja wohl auch nicht das Ausschlaggebende Mittel beim Programmieren sein...


Anmelden zum Antworten