GUIDA Decodificare la lunghezza delle istruzioni di x86 e x64

DispatchCode

Moderatore
Staff Forum
Utente Èlite
1,558
1,202
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
30Mbps/3Mbps con Eolo
OS
Windows 10 64bit
MCA - Machine Code Analyzer

Vi avevo già parlato di un mio progetto qualche mese fa. MCA è parte di quel progetto. Si tratta di una parte così importante che ho preferito "scorporare" e pubblicare separatamente, aggiungendo un pò di cose che mi ero perso. Ma andiamo con ordine.
Il compito di MCA è decodificare il codice macchina che ha come target le architetture x86 e x64.

Le architetture CISC hanno un gran numero di opcodes, e la lunghezza delle istruzioni non è fissa (varia da 1 a 15bytes). Quindi se si ha bisogno di decodifcare il codice macchina di queste architetture l'unica soluzione è decodificare ogni byte, per capire di quale operazione si tratta.
La struttura di un'istruzione è mostrata di seguito:

Codice:
// con [ ] vengono indicati i campi opzionali
[prefix] opcode [modrm] [sib] [disp] [imm]

A questi vanno aggiunti anche alcuni altri prefissi, come REX e VEX, che si trovano sempre prima dell'opcode. Gli opcode possono essere a 1byte, 2byte o 3byte (in due forme differenti).

Per mostrarvi il funzionamento di MCA, riporto un esempio preso dal README del progetto:

Codice:
008910BC  |.  C785 68FFFFFF 00000000  MOV DWORD PTR SS:[LOCAL.38],0
008910C6  |.  8D45 CC                 LEA EAX,[LOCAL.13]
008910C9  |.  8D5D 9C                 LEA EBX,[LOCAL.25]
008910CC  |.  33C9                    XOR ECX,ECX
008910CE  |>  83F9 30                 /CMP ECX,30
008910D1  |.  7D 18                   |JGE SHORT 008910EB
008910D3  |.  0F100408                |MOVUPS XMM0,DQWORD PTR DS:[ECX+EAX]
008910D7  |.  0F100C0B                |MOVUPS XMM1,DQWORD PTR DS:[ECX+EBX]
008910DB  |.  0F58C1                  |ADDPS XMM0,XMM1
008910DE  |.  0F11840D 6CFFFFFF       |MOVUPS DQWORD PTR SS:[ECX+EBP-94],XMM0
008910E6  |.  83C1 04                 |ADD ECX,4
008910E9  |.^ EB E3                   \JMP SHORT 008910CE

Decodificando il file binario che contiene quel codice macchina e stampando ogni istruzioni riga per riga (così da riuscire a leggerla meglio), MCA decodifica:

Codice:
C7 85 68 FF FF FF 00 00 00 00
8D 45 CC
8D 5D 9C
33 C9
83 F9 30
7D 18
0F 10 04 08
0F 10 0C 0B
0F 58 C1
0F 11 84 0D 6C FF FF FF
83 C1 04

Come si può osservare il codice è quello che si vede sopra (avevo disassemblato un'istruzione in meno, mi sono perso quindi il JMP...). MCA mantiene un array di 15bytes (opzionale) con i byte dell'istruzione; la stampa qui sopra avviene proprio utilizzando quell'array.

Ovviamente mantiene tutte le altre informazioni che riguardano l'istruzione. Ne ho scelte 2 tra quelle mostrate sopra:

Codice:
MOV DWORD PTR SS:[LOCAL.38],0
MOVUPS DQWORD PTR SS:[ECX+EBP-94],XMM0

Queste sono le informazioni raccolte da MCA sulle due istruzioni:

Codice:
RAW bytes (hex): C7 85 68 FF FF FF 00 00 00 00
Instr. length: 10
Print instruction fields:
        Located Prefixes 0:

        OP: 0xC7
        mod_reg_rm: 0x85
        disp (4): 0xFFFFFF68
        Iimm: 0x0


RAW bytes (hex): 0F 11 84 0D 6C FF FF FF
Instr. length: 8
Print instruction fields:
        Located Prefixes 1:
                0xF
        OP: 0x11
        mod_reg_rm: 0x84
        SIB byte: 0xD
        disp (4): 0xFFFFFF6C

Attualmente è ancora in versione Beta, e necessita quindi di qualche "prova sul campo".
Manca il supporto per il prefisso EVEX (AVX-512), 3DNow! e XOP (di AMD). Attualmente non è presente una trasformazione in mnemonici, ma diciamo che è tra le cose che vorrei implementare in futuro, dopo al supporto per EVEX.

Per tutte le altre info e il codice vi rimando al README di MCA: https://github.com/DispatchCode/Machine-Code-Analyzer
 

Entra

oppure Accedi utilizzando