/*******************************************************************************/ /* COS2000 - Compatible Operating System - LGPL v3 - Hordé Nicolas */ /* */ #include "types.h" #include "video.h" #include "debug.h" u8 *r8[] = { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh" }; u8 *r16[] = { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di" }; u8 *r32[] = { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" }; u8 *rseg[] = { "ds", "es", "fs", "gs", "ss", "cs", "ip" }; /*******************************************************************************/ /* Efface un breakpoint sur une adresse */ void cleardebugreg(u8 * address) { for (u8 i = 0; i < 4; i++) if (getdebugreg(i) == address) setdebugreg(i, 0x0, DBG_CLEAR); } /*******************************************************************************/ /* Permet de manipuler dr0-dr7 pour mettre en place des breakpoints */ u8 *getdebugreg(u8 number) { u8 *address; if (number == 0) asm("mov %%dr0,%%eax; mov %%eax,%[address]":[address] "=m" (address)::); else if (number == 1) asm("mov %%dr1,%%eax; movl %%eax,%[address]":[address] "=m" (address)::); else if (number == 2) asm("mov %%dr2,%%eax; movl %%eax,%[address]":[address] "=m" (address)::); else if (number == 3) asm("mov %%dr0,%%eax; movl %%eax,%[address]":[address] "=m" (address)::); return address; } /*******************************************************************************/ /* Permet de manipuler dr0-dr7 pour mettre en place des breakpoints */ void setdebugreg(u8 number, u8 * address, u8 type) { u32 dr7 = 0; asm("movl %%dr7,%%eax; mov %%eax,%[dr7]":[dr7] "=m"(dr7)::); if (type == DBG_WRITE || type == DBG_READWRITE) dr7 |= 0x3 << 8; if (type != DBG_CLEAR) dr7 |= 0x3 << (number << 1); else dr7 &= ~(0x3 << (number << 1)); dr7 &= ~(0x3 << (16 + (number << 2))); dr7 |= type << (16 + (number << 2)); dr7 &= ~(0x3 << (16 + ((number << 2) + 2))); asm("movl %[dr7],%%eax; mov %%eax,%%dr7"::[dr7] "m"(dr7):); if (number == 0) asm("movl %[address],%%eax; mov %%eax,%%dr0"::[address] "m"(address):); else if (number == 1) asm("movl %[address],%%eax; mov %%eax,%%dr1"::[address] "m"(address):); else if (number == 2) asm("movl %[address],%%eax; mov %%eax,%%dr2"::[address] "m"(address):); else if (number == 3) asm("movl %[address],%%eax; mov %%eax,%%dr3"::[address] "m"(address):); else return; } /*******************************************************************************/ /* Fonctions de déboguage */ u16 decodeModSM(bool show, u8 * a, u8 * op, u16 order, u32 Gsz, u32 Esz) { u32 len = 0; u32 reg = 0; u32 scale = 0; u8 *b = a; u8 *E, *G, *indx, *base, *disp = "\0"; u8 ebuf[32] = { 0 }; setG(); if (Esz) { switch (*b & 0xc7) { case 0x00: E = "[bx+si]"; break; case 0x01: E = "[bx+di]"; break; case 0x02: E = "[bp+si]"; break; case 0x03: E = "[bp+di]"; break; case 0x04: E = "[si]"; break; case 0x05: E = "[di]"; break; case 0x06: snprintf(ebuf, sizeof(ebuf), "ds:%x", *(u16 *)++ b); E = ebuf; ++b; break; case 0x07: E = "[bx]"; break; case 0x40: snprintf(ebuf, sizeof(ebuf), "[bx+si+%x]", *(u8 *)++ b); E = ebuf; break; case 0x41: snprintf(ebuf, sizeof(ebuf), "[bx+di+%x]", *(u8 *)++ b); E = ebuf; break; case 0x42: snprintf(ebuf, sizeof(ebuf), "[bp+si+%x]", *(u8 *)++ b); E = ebuf; break; case 0x43: snprintf(ebuf, sizeof(ebuf), "[bp+di+%x]", *(u8 *)++ b); E = ebuf; break; case 0x44: snprintf(ebuf, sizeof(ebuf), "[si+%x]", *(u8 *)++ b); E = ebuf; break; case 0x45: snprintf(ebuf, sizeof(ebuf), "[di+%x]", *(u8 *)++ b); E = ebuf; break; case 0x46: snprintf(ebuf, sizeof(ebuf), "[bp+%x]", *(u8 *)++ b); E = ebuf; break; case 0x47: snprintf(ebuf, sizeof(ebuf), "[bx+%x]", *(u8 *)++ b); E = ebuf; case 0x80: snprintf(ebuf, sizeof(ebuf), "[bx+si+%x]", *(u8 *)++ b); E = ebuf; ++b; break; case 0x81: snprintf(ebuf, sizeof(ebuf), "[bx+di+%x]", *(u8 *)++ b); E = ebuf; ++b; break; case 0x82: snprintf(ebuf, sizeof(ebuf), "[bp+si+%x]", *(u8 *)++ b); E = ebuf; ++b; break; case 0x83: snprintf(ebuf, sizeof(ebuf), "[bp+di+%x]", *(u8 *)++ b); E = ebuf; ++b; break; case 0x84: snprintf(ebuf, sizeof(ebuf), "[si+%x]", *(u8 *)++ b); E = ebuf; ++b; break; case 0x85: snprintf(ebuf, sizeof(ebuf), "[di+%x]", *(u8 *)++ b); E = ebuf; ++b; break; case 0x86: snprintf(ebuf, sizeof(ebuf), "[bp+%x]", *(u8 *)++ b); E = ebuf; ++b; break; case 0x87: snprintf(ebuf, sizeof(ebuf), "[bx+%x]", *(u8 *)++ b); E = ebuf; ++b; break; case 0xc0: E = "al"; break; case 0xc1: E = "cl"; break; case 0xc2: E = "dl"; break; case 0xc3: E = "bl"; break; case 0xc4: E = "ah"; break; case 0xc5: E = "ch"; break; case 0xc6: E = "dh"; break; case 0xc7: E = "bh"; break; default: if (show) print("Invalid Mod R/M byte."); return 1000; } } else { switch (*b & 0xc7) { case 0x00: E = "[eax]"; break; case 0x01: E = "[ecx]"; break; case 0x02: E = "[edx]"; break; case 0x03: E = "[ebx]"; break; case 0x04: ++b; decodeSIB(); if (!indx) { snprintf(ebuf, sizeof(ebuf), "[%s]", base); } else if (!base) { if (!scale) { snprintf(ebuf, sizeof(ebuf), "[%s]", indx); } else { snprintf(ebuf, sizeof(ebuf), "[%s*%i]", indx, scale); } } else if (!scale) { snprintf(ebuf, sizeof(ebuf), "[%s+%s]", base, indx); } else { snprintf(ebuf, sizeof(ebuf), "[%s+%s*%i]", base, indx, scale); } E = ebuf; break; case 0x05: snprintf(ebuf, sizeof(ebuf), "ds:%x", *(u32 *)++ b); E = ebuf; b += 3; break; case 0x06: E = "[esi]"; break; case 0x07: E = "[edi]"; break; case 0x40: snprintf(ebuf, sizeof(ebuf), "[eax+%x]", *(u8 *)++ b); E = ebuf; break; case 0x41: snprintf(ebuf, sizeof(ebuf), "[ecx+%x]", *(u8 *)++ b); E = ebuf; break; case 0x42: snprintf(ebuf, sizeof(ebuf), "[edx+%x]", *(u8 *)++ b); E = ebuf; break; case 0x43: snprintf(ebuf, sizeof(ebuf), "[ebx+%x]", *(u8 *)++ b); E = ebuf; case 0x44: ++b; decodeSIB(); if (!indx) { snprintf(ebuf, sizeof(ebuf), "[%s", base); } else if (!base) { if (!scale) { snprintf(ebuf, sizeof(ebuf), "[%s", indx); } else { snprintf(ebuf, sizeof(ebuf), "[%s*%i", indx, scale); } } else if (!scale) { snprintf(ebuf, sizeof(ebuf), "[%s+%s", base, indx); } else { snprintf(ebuf, sizeof(ebuf), "[%s+%s*%i", base, indx, scale); } len = strlen(ebuf); snprintf(ebuf + len, sizeof(ebuf) - len, "+%x]", *(u8 *)++ b); E = ebuf; break; case 0x45: snprintf(ebuf, sizeof(ebuf), "[ebp+%x]", *(u8 *)++ b); E = ebuf; break; case 0x46: snprintf(ebuf, sizeof(ebuf), "[esi+%x]", *(u8 *)++ b); E = ebuf; break; case 0x47: snprintf(ebuf, sizeof(ebuf), "[edi+%x]", *(u8 *)++ b); E = ebuf; break; case 0x80: snprintf(ebuf, sizeof(ebuf), "[eax+%x]", *(u32 *)++ b); E = ebuf; b += 3; break; case 0x81: snprintf(ebuf, sizeof(ebuf), "[ecx+%x]", *(u32 *)++ b); E = ebuf; break; case 0x82: snprintf(ebuf, sizeof(ebuf), "[edx+%x]", *(u32 *)++ b); E = ebuf; b += 3; break; case 0x83: snprintf(ebuf, sizeof(ebuf), "[ebx+%x]", *(u32 *)++ b); E = ebuf; b += 3; break; case 0x84: ++b; decodeSIB(); if (!indx) { snprintf(ebuf, sizeof(ebuf), "[%s", base); } else if (!base) { if (!scale) { snprintf(ebuf, sizeof(ebuf), "[%s", indx); } else { snprintf(ebuf, sizeof(ebuf), "[%s*%i", indx, scale); } } else if (!scale) { snprintf(ebuf, sizeof(ebuf), "[%s+%s", base, indx); } else { snprintf(ebuf, sizeof(ebuf), "[%s+%s*%i", base, indx, scale); } len = strlen(ebuf); snprintf(ebuf + len, sizeof(ebuf) - len, "+%x]", *(u32 *)++ b); b += 3; E = ebuf; break; case 0x85: snprintf(ebuf, sizeof(ebuf), "[ebp+%x]", *(u32 *)++ b); E = ebuf; b += 3; break; case 0x86: snprintf(ebuf, sizeof(ebuf), "[esi+%x]", *(u32 *)++ b); E = ebuf; b += 3; break; case 0x87: snprintf(ebuf, sizeof(ebuf), "[edi+%x]", *(u32 *)++ b); E = ebuf; b += 3; break; case 0xc0: E = Esz == 1 ? "ax" : "eax"; break; case 0xc1: E = Esz == 1 ? "cx" : "ecx"; break; case 0xc2: E = Esz == 1 ? "dx" : "edx"; break; case 0xc3: E = Esz == 1 ? "bx" : "ebx"; break; case 0xc4: E = Esz == 1 ? "sp" : "esp"; break; case 0xc5: E = Esz == 1 ? "bp" : "ebp"; break; case 0xc6: E = Esz == 1 ? "si" : "esi"; break; case 0xc7: E = Esz == 1 ? "di" : "edi"; break; default: if (show) print("Invalid Mod R/M byte."); return 1000; } } if (order) { snprintf(op, opBufSz, "%s", E); len = strlen(op); if (Gsz) { snprintf(op + len, opBufSz - len, ", %s", G); } } else { snprintf(op, opBufSz, "%s, ", G); len = strlen(op); snprintf(op + len, opBufSz - len, "%s", E); } return b - a; } u32 decodeModSM_float(bool show, u8 * a, u8 * op, u32 order, u32 Gsz, u32 Esz) { u32 len = 0; u32 reg = 0; u32 scale = 0; u8 *b = a; u8 *E, *G, *indx, *base, *disp = "\0"; u8 ebuf[32] = { 0 }; setG(); if (Esz) { switch (*b & 0xc7) { case 0x00: E = "[bx+si]"; break; case 0x01: E = "[bx+di]"; break; case 0x02: E = "[bp+si]"; break; case 0x03: E = "[bp+di]"; break; case 0x04: E = "[si]"; break; case 0x05: E = "[di]"; break; case 0x06: snprintf(ebuf, sizeof(ebuf), "ds:%x", *(u16 *)++ b); E = ebuf; ++b; break; case 0x07: E = "[bx]"; break; case 0x40: snprintf(ebuf, sizeof(ebuf), "[bx+si+%x]", *(u8 *)++ b); E = ebuf; break; case 0x41: snprintf(ebuf, sizeof(ebuf), "[bx+di+%x]", *(u8 *)++ b); E = ebuf; break; case 0x42: snprintf(ebuf, sizeof(ebuf), "[bp+si+%x]", *(u8 *)++ b); E = ebuf; break; case 0x43: snprintf(ebuf, sizeof(ebuf), "[bp+di+%x]", *(u8 *)++ b); E = ebuf; break; case 0x44: snprintf(ebuf, sizeof(ebuf), "[si+%x]", *(u8 *)++ b); E = ebuf; break; case 0x45: snprintf(ebuf, sizeof(ebuf), "[di+%x]", *(u8 *)++ b); E = ebuf; break; case 0x46: snprintf(ebuf, sizeof(ebuf), "[bp+%x]", *(u8 *)++ b); E = ebuf; break; case 0x47: snprintf(ebuf, sizeof(ebuf), "[bx+%x]", *(u8 *)++ b); E = ebuf; case 0x80: snprintf(ebuf, sizeof(ebuf), "[bx+si+%x]", *(u16 *)++ b); E = ebuf; ++b; break; case 0x81: snprintf(ebuf, sizeof(ebuf), "[bx+di+%x]", *(u16 *)++ b); E = ebuf; ++b; break; case 0x82: snprintf(ebuf, sizeof(ebuf), "[bp+si+%x]", *(u16 *)++ b); E = ebuf; ++b; break; case 0x83: snprintf(ebuf, sizeof(ebuf), "[bp+di+%x]", *(u16 *)++ b); E = ebuf; ++b; break; case 0x84: snprintf(ebuf, sizeof(ebuf), "[si+%x]", *(u16 *)++ b); E = ebuf; ++b; break; case 0x85: snprintf(ebuf, sizeof(ebuf), "[di+%x]", *(u16 *)++ b); E = ebuf; ++b; break; case 0x86: snprintf(ebuf, sizeof(ebuf), "[bp+%x]", *(u16 *)++ b); E = ebuf; ++b; break; case 0x87: snprintf(ebuf, sizeof(ebuf), "[bx+%x]", *(u16 *)++ b); E = ebuf; ++b; break; case 0xc0: E = "st(0)"; break; case 0xc1: E = "st(1)"; break; case 0xc2: E = "st(2)"; break; case 0xc3: E = "st(3)"; break; case 0xc4: E = "st(4)"; break; case 0xc5: E = "st(5)"; break; case 0xc6: E = "st(6)"; break; case 0xc7: E = "st(7)"; break; default: if (show) print("Invalid Mod R/M byte."); return 1000; } } else { switch (*b & 0xc7) { case 0x00: E = "[eax]"; break; case 0x01: E = "[ecx]"; break; case 0x02: E = "[edx]"; break; case 0x03: E = "[ebx]"; break; case 0x04: ++b; decodeSIB(); if (!indx) { snprintf(ebuf, sizeof(ebuf), "[%s]", base); } else if (!base) { if (!scale) { snprintf(ebuf, sizeof(ebuf), "[%s]", indx); } else { snprintf(ebuf, sizeof(ebuf), "[%s*%i]", indx, scale); } } else if (!scale) { snprintf(ebuf, sizeof(ebuf), "[%s+%s]", base, indx); } else { snprintf(ebuf, sizeof(ebuf), "[%s+%s*%i]", base, indx, scale); } E = ebuf; break; case 0x05: snprintf(ebuf, sizeof(ebuf), "ds:%x", *(u32 *)++ b); E = ebuf; b += 3; break; case 0x06: E = "[esi]"; break; case 0x07: E = "[edi]"; break; case 0x40: snprintf(ebuf, sizeof(ebuf), "[eax+%x]", *(u8 *)++ b); E = ebuf; break; case 0x41: snprintf(ebuf, sizeof(ebuf), "[ecx+%x]", *(u8 *)++ b); E = ebuf; break; case 0x42: snprintf(ebuf, sizeof(ebuf), "[edx+%x]", *(u8 *)++ b); E = ebuf; break; case 0x43: snprintf(ebuf, sizeof(ebuf), "[ebx+%x]", *(u8 *)++ b); E = ebuf; case 0x44: ++b; decodeSIB(); if (!indx) { snprintf(ebuf, sizeof(ebuf), "[%s", base); } else if (!base) { if (!scale) { snprintf(ebuf, sizeof(ebuf), "[%s", indx); } else { snprintf(ebuf, sizeof(ebuf), "[%s*%i", indx, scale); } } else if (!scale) { snprintf(ebuf, sizeof(ebuf), "[%s+%s", base, indx); } else { snprintf(ebuf, sizeof(ebuf), "[%s+%s*%i", base, indx, scale); } len = strlen(ebuf); snprintf(ebuf + len, sizeof(ebuf) - len, "+%x]", *(u8 *)++ b); E = ebuf; break; case 0x45: snprintf(ebuf, sizeof(ebuf), "[ebp+%x]", *(u8 *)++ b); E = ebuf; break; case 0x46: snprintf(ebuf, sizeof(ebuf), "[esi+%x]", *(u8 *)++ b); E = ebuf; break; case 0x47: snprintf(ebuf, sizeof(ebuf), "[edi+%x]", *(u8 *)++ b); E = ebuf; break; case 0x80: snprintf(ebuf, sizeof(ebuf), "[eax+%x]", *(u32 *)++ b); E = ebuf; b += 3; break; case 0x81: snprintf(ebuf, sizeof(ebuf), "[ecx+%x]", *(u32 *)++ b); E = ebuf; break; case 0x82: snprintf(ebuf, sizeof(ebuf), "[edx+%x]", *(u32 *)++ b); E = ebuf; b += 3; break; case 0x83: snprintf(ebuf, sizeof(ebuf), "[ebx+%x]", *(u32 *)++ b); E = ebuf; b += 3; break; case 0x84: ++b; decodeSIB(); if (!indx) { snprintf(ebuf, sizeof(ebuf), "[%s", base); } else if (!base) { if (!scale) { snprintf(ebuf, sizeof(ebuf), "[%s", indx); } else { snprintf(ebuf, sizeof(ebuf), "[%s*%i", indx, scale); } } else if (!scale) { snprintf(ebuf, sizeof(ebuf), "[%s+%s", base, indx); } else { snprintf(ebuf, sizeof(ebuf), "[%s+%s*%i", base, indx, scale); } len = strlen(ebuf); snprintf(ebuf + len, sizeof(ebuf) - len, "+%x]", *(u32 *)++ b); b += 3; E = ebuf; break; case 0x85: snprintf(ebuf, sizeof(ebuf), "[ebp+%x]", *(u32 *)++ b); E = ebuf; b += 3; break; case 0x86: snprintf(ebuf, sizeof(ebuf), "[esi+%x]", *(u32 *)++ b); E = ebuf; b += 3; break; case 0x87: snprintf(ebuf, sizeof(ebuf), "[edi+%x]", *(u32 *)++ b); E = ebuf; b += 3; break; case 0xc0: E = "st(0)"; break; case 0xc1: E = "st(1)"; break; case 0xc2: E = "st(2)"; break; case 0xc3: E = "st(3)"; break; case 0xc4: E = "st(4)"; break; case 0xc5: E = "st(5)"; break; case 0xc6: E = "st(6)"; break; case 0xc7: E = "st(7)"; break; default: if (show) print("Invalid Mod R/M byte."); return 1000; } } if (order) { snprintf(op, opBufSz, "%s", E); len = strlen(op); if (Gsz) { snprintf(op + len, opBufSz - len, ", %s", G); } } else { snprintf(op, opBufSz, "%s, ", G); len = strlen(op); snprintf(op + len, opBufSz - len, "%s", E); } return b - a; } u32 decodeModSM_memonly(bool show, u8 * a, u8 * op, u32 order, u32 Gsz, u32 Esz) { u32 len = 0; u32 reg = 0; u32 scale = 0; u8 *b = a; u8 *E, *G, *indx, *base, *disp = "\0"; u8 ebuf[32] = { 0 }; setG(); if (Esz) { switch (*b & 0xc7) { case 0x00: E = "[bx+si]"; break; case 0x01: E = "[bx+di]"; break; case 0x02: E = "[bp+si]"; break; case 0x03: E = "[bp+di]"; break; case 0x04: E = "[si]"; break; case 0x05: E = "[di]"; break; case 0x06: snprintf(ebuf, sizeof(ebuf), "ds:%x", *(u16 *)++ b); E = ebuf; ++b; break; case 0x07: E = "[bx]"; break; case 0x40: snprintf(ebuf, sizeof(ebuf), "[bx+si+%x]", *(u8 *)++ b); E = ebuf; break; case 0x41: snprintf(ebuf, sizeof(ebuf), "[bx+di+%x]", *(u8 *)++ b); E = ebuf; break; case 0x42: snprintf(ebuf, sizeof(ebuf), "[bp+si+%x]", *(u8 *)++ b); E = ebuf; break; case 0x43: snprintf(ebuf, sizeof(ebuf), "[bp+di+%x]", *(u8 *)++ b); E = ebuf; break; case 0x44: snprintf(ebuf, sizeof(ebuf), "[si+%x]", *(u8 *)++ b); E = ebuf; break; case 0x45: snprintf(ebuf, sizeof(ebuf), "[di+%x]", *(u8 *)++ b); E = ebuf; break; case 0x46: snprintf(ebuf, sizeof(ebuf), "[bp+%x]", *(u8 *)++ b); E = ebuf; break; case 0x47: snprintf(ebuf, sizeof(ebuf), "[bx+%x]", *(u8 *)++ b); E = ebuf; case 0x80: snprintf(ebuf, sizeof(ebuf), "[bx+si+%x]", *(u16 *)++ b); E = ebuf; ++b; break; case 0x81: snprintf(ebuf, sizeof(ebuf), "[bx+di+%x]", *(u16 *)++ b); E = ebuf; ++b; break; case 0x82: snprintf(ebuf, sizeof(ebuf), "[bp+si+%x]", *(u16 *)++ b); E = ebuf; ++b; break; case 0x83: snprintf(ebuf, sizeof(ebuf), "[bp+di+%x]", *(u16 *)++ b); E = ebuf; ++b; break; case 0x84: snprintf(ebuf, sizeof(ebuf), "[si+%x]", *(u16 *)++ b); E = ebuf; ++b; break; case 0x85: snprintf(ebuf, sizeof(ebuf), "[di+%x]", *(u16 *)++ b); E = ebuf; ++b; break; case 0x86: snprintf(ebuf, sizeof(ebuf), "[bp+%x]", *(u16 *)++ b); E = ebuf; ++b; break; case 0x87: snprintf(ebuf, sizeof(ebuf), "[bx+%x]", *(u16 *)++ b); E = ebuf; ++b; break; default: if (show) print("Invalid Mod R/M byte."); return 1000; } } else { switch (*b & 0xc7) { case 0x00: E = "[eax]"; break; case 0x01: E = "[ecx]"; break; case 0x02: E = "[edx]"; break; case 0x03: E = "[ebx]"; break; case 0x04: ++b; decodeSIB(); if (!indx) { snprintf(ebuf, sizeof(ebuf), "[%s]", base); } else if (!base) { if (!scale) { snprintf(ebuf, sizeof(ebuf), "[%s]", indx); } else { snprintf(ebuf, sizeof(ebuf), "[%s*%i]", indx, scale); } } else if (!scale) { snprintf(ebuf, sizeof(ebuf), "[%s+%s]", base, indx); } else { snprintf(ebuf, sizeof(ebuf), "[%s+%s*%i]", base, indx, scale); } E = ebuf; break; case 0x05: snprintf(ebuf, sizeof(ebuf), "ds:%x", *(u32 *)++ b); E = ebuf; b += 3; break; case 0x06: E = "[esi]"; break; case 0x07: E = "[edi]"; break; case 0x40: snprintf(ebuf, sizeof(ebuf), "[eax+%x]", *(u8 *)++ b); E = ebuf; break; case 0x41: snprintf(ebuf, sizeof(ebuf), "[ecx+%x]", *(u8 *)++ b); E = ebuf; break; case 0x42: snprintf(ebuf, sizeof(ebuf), "[edx+%x]", *(u8 *)++ b); E = ebuf; break; case 0x43: snprintf(ebuf, sizeof(ebuf), "[ebx+%x]", *(u8 *)++ b); E = ebuf; case 0x44: ++b; decodeSIB(); if (!indx) { snprintf(ebuf, sizeof(ebuf), "[%s", base); } else if (!base) { if (!scale) { snprintf(ebuf, sizeof(ebuf), "[%s", indx); } else { snprintf(ebuf, sizeof(ebuf), "[%s*%i", indx, scale); } } else if (!scale) { snprintf(ebuf, sizeof(ebuf), "[%s+%s", base, indx); } else { snprintf(ebuf, sizeof(ebuf), "[%s+%s*%i", base, indx, scale); } len = strlen(ebuf); snprintf(ebuf + len, sizeof(ebuf) - len, "+%x]", *(u8 *)++ b); E = ebuf; break; case 0x45: snprintf(ebuf, sizeof(ebuf), "[ebp+%x]", *(u8 *)++ b); E = ebuf; break; case 0x46: snprintf(ebuf, sizeof(ebuf), "[esi+%x]", *(u8 *)++ b); E = ebuf; break; case 0x47: snprintf(ebuf, sizeof(ebuf), "[edi+%x]", *(u8 *)++ b); E = ebuf; break; case 0x80: snprintf(ebuf, sizeof(ebuf), "[eax+%x]", *(u32 *)++ b); E = ebuf; b += 3; break; case 0x81: snprintf(ebuf, sizeof(ebuf), "[ecx+%x]", *(u32 *)++ b); E = ebuf; break; case 0x82: snprintf(ebuf, sizeof(ebuf), "[edx+%x]", *(u32 *)++ b); E = ebuf; b += 3; break; case 0x83: snprintf(ebuf, sizeof(ebuf), "[ebx+%x]", *(u32 *)++ b); E = ebuf; b += 3; break; case 0x84: ++b; decodeSIB(); if (!indx) { snprintf(ebuf, sizeof(ebuf), "[%s", base); } else if (!base) { if (!scale) { snprintf(ebuf, sizeof(ebuf), "[%s", indx); } else { snprintf(ebuf, sizeof(ebuf), "[%s*%i", indx, scale); } } else if (!scale) { snprintf(ebuf, sizeof(ebuf), "[%s+%s", base, indx); } else { snprintf(ebuf, sizeof(ebuf), "[%s+%s*%i", base, indx, scale); } len = strlen(ebuf); snprintf(ebuf + len, sizeof(ebuf) - len, "+%x]", *(u32 *)++ b); b += 3; E = ebuf; break; case 0x85: snprintf(ebuf, sizeof(ebuf), "[ebp+%x]", *(u32 *)++ b); E = ebuf; b += 3; break; case 0x86: snprintf(ebuf, sizeof(ebuf), "[esi+%x]", *(u32 *)++ b); E = ebuf; b += 3; break; case 0x87: snprintf(ebuf, sizeof(ebuf), "[edi+%x]", *(u32 *)++ b); E = ebuf; b += 3; break; default: if (show) print("Invalid Mod R/M byte."); return 1000; } } if (order) { snprintf(op, opBufSz, "%s", E); len = strlen(op); if (Gsz) { snprintf(op + len, opBufSz - len, ", %s", G); } } else { snprintf(op, opBufSz, "%s, ", G); len = strlen(op); snprintf(op + len, opBufSz - len, "%s", E); } return b - a; } /*******************************************************************************/ /* Décode une adresse mémoire au format intel */ u32 disasm(u8 * a, u8 * string, bool show) { u8 *f_entry; u16 entry; u8 *b = a; u32 len = 0; u32 flip_addr_sz = 0; u32 flip_imm_sz = 0; u32 EG = 1; u32 B = 1; u8 *s, *prefix, *seg_oride = "\0"; u8 op1[opBufSz] = { 0 }; if (*b == 0xf3) { prefix = "rep"; ++b; } else if (*b == 0xf2) { prefix = "repnz"; ++b; } else if (*b == 0xf0) { prefix = "lock"; ++b; } if (*b == 0x67) { flip_addr_sz = 1; ++b; } if (*b == 0x66) { flip_imm_sz = 1; ++b; } switch (*b) { case 0x2e: seg_oride = "cs"; ++b; break; case 0x36: seg_oride = "ss"; ++b; break; case 0x3e: seg_oride = "ds"; ++b; break; case 0x26: seg_oride = "es"; ++b; break; case 0x64: seg_oride = "fs"; ++b; break; case 0x65: seg_oride = "gs"; ++b; } if (*b == 0x0f) { if (show) print("Extended opcodes not implimented.\r\n"); return 1000; } else { switch (*b) { case 0x00: s = "add"; b += decodeModSM(show, ++b, op1, 1, 1, flip_addr_sz); break; case 0x01: s = "add"; b += decodeModSM(show, ++b, op1, 1, flip_imm_sz ? 2 : 3, flip_addr_sz); break; case 0x02: s = "add"; b += decodeModSM(show, ++b, op1, 0, 1, flip_addr_sz); break; case 0x03: s = "add"; b += decodeModSM(show, ++b, op1, 0, flip_imm_sz ? 2 : 3, flip_addr_sz); break; case 0x04: s = "add"; ++b; snprintf(op1, sizeof(op1), "al, %x", (void *) *b); break; case 0x05: s = "add"; if (flip_imm_sz) { snprintf(op1, sizeof(op1), "ax, %x", *(u16 *)++ b); ++b; } else { snprintf(op1, sizeof(op1), "eax, %x", *(u32 *)++ b); b += 3; } break; case 0x06: s = "push es"; break; case 0x07: s = "pop es"; break; case 0x08: s = "or"; b += decodeModSM(show, ++b, op1, 1, 1, flip_addr_sz); break; case 0x09: s = "or"; b += decodeModSM(show, ++b, op1, 1, flip_imm_sz ? 2 : 3, flip_addr_sz); break; case 0x0a: s = "or"; b += decodeModSM(show, ++b, op1, 0, 1, flip_addr_sz); break; case 0x0b: s = "or"; b += decodeModSM(show, ++b, op1, 0, flip_imm_sz ? 2 : 3, flip_addr_sz); break; case 0x0c: s = "or"; ++b; snprintf(op1, sizeof(op1), "al, %x", (void *) *b); break; case 0x0d: s = "or"; if (flip_imm_sz) { snprintf(op1, sizeof(op1), "ax, %x", *(u16 *)++ b); ++b; } else { snprintf(op1, sizeof(op1), "eax, %x", *(u32 *)++ b); b += 3; } break; case 0x0e: s = "push cs"; break; case 0x10: s = "adc"; b += decodeModSM(show, ++b, op1, 1, 1, flip_addr_sz); break; case 0x11: s = "adc"; b += decodeModSM(show, ++b, op1, 1, flip_imm_sz ? 2 : 3, flip_addr_sz); break; case 0x12: s = "adc"; b += decodeModSM(show, ++b, op1, 0, 1, flip_addr_sz); break; case 0x13: s = "adc"; b += decodeModSM(show, ++b, op1, 0, flip_imm_sz ? 2 : 3, flip_addr_sz); break; case 0x14: s = "adc"; ++b; snprintf(op1, sizeof(op1), "al, %x", (void *) *b); break; case 0x15: s = "adc"; if (flip_imm_sz) { snprintf(op1, sizeof(op1), "ax, %x", *(u16 *)++ b); ++b; } else { snprintf(op1, sizeof(op1), "eax, %x", *(u32 *)++ b); b += 3; } break; case 0x16: s = "push ss"; break; case 0x17: s = "pop ss"; break; case 0x18: s = "sbb"; b += decodeModSM(show, ++b, op1, 1, 1, flip_addr_sz); break; case 0x19: s = "sbb"; b += decodeModSM(show, ++b, op1, 1, flip_imm_sz ? 2 : 3, flip_addr_sz); break; case 0x1a: s = "sbb"; b += decodeModSM(show, ++b, op1, 0, 1, flip_addr_sz); break; case 0x1b: s = "sbb"; b += decodeModSM(show, ++b, op1, 0, flip_imm_sz ? 2 : 3, flip_addr_sz); break; case 0x1c: s = "sbb"; ++b; snprintf(op1, sizeof(op1), "al, %x", (void *) *b); break; case 0x1d: s = "sbb"; if (flip_imm_sz) { snprintf(op1, sizeof(op1), "ax, %x", *(u16 *)++ b); ++b; } else { snprintf(op1, sizeof(op1), "eax, %x", *(u32 *)++ b); b += 3; } break; case 0x1e: s = "push ds"; break; case 0x1f: s = "pop ds"; break; case 0x20: s = "and"; b += decodeModSM(show, ++b, op1, 1, 1, flip_addr_sz); break; case 0x21: s = "and"; b += decodeModSM(show, ++b, op1, 1, flip_imm_sz ? 2 : 3, flip_addr_sz); break; case 0x22: s = "and"; b += decodeModSM(show, ++b, op1, 0, 1, flip_addr_sz); break; case 0x23: s = "and"; b += decodeModSM(show, ++b, op1, 0, flip_imm_sz ? 2 : 3, flip_addr_sz); break; case 0x24: s = "and"; ++b; snprintf(op1, sizeof(op1), "al, %x", (void *) *b); break; case 0x25: s = "and"; if (flip_imm_sz) { snprintf(op1, sizeof(op1), "ax, %x", *(u16 *)++ b); ++b; } else { snprintf(op1, sizeof(op1), "eax, %x", *(u32 *)++ b); b += 3; } break; case 0x27: s = "daa"; break; case 0x28: s = "sub"; b += decodeModSM(show, ++b, op1, 1, 1, flip_addr_sz); break; case 0x29: s = "sub"; b += decodeModSM(show, ++b, op1, 1, flip_imm_sz ? 2 : 3, flip_addr_sz); break; case 0x2a: s = "sub"; b += decodeModSM(show, ++b, op1, 0, 1, flip_addr_sz); break; case 0x2b: s = "sub"; b += decodeModSM(show, ++b, op1, 0, flip_imm_sz ? 2 : 3, flip_addr_sz); break; case 0x2c: s = "sub"; ++b; snprintf(op1, sizeof(op1), "al, %x", (void *) *b); break; case 0x2d: s = "sub"; if (flip_imm_sz) { snprintf(op1, sizeof(op1), "ax, %x", *(u16 *)++ b); ++b; } else { snprintf(op1, sizeof(op1), "eax, %x", *(u32 *)++ b); b += 3; } break; case 0x2f: s = "das"; break; case 0x30: s = "xor"; b += decodeModSM(show, ++b, op1, 1, 1, flip_addr_sz); break; case 0x31: s = "xor"; b += decodeModSM(show, ++b, op1, 1, flip_imm_sz ? 2 : 3, flip_addr_sz); break; case 0x32: s = "xor"; b += decodeModSM(show, ++b, op1, 0, 1, flip_addr_sz); break; case 0x33: s = "xor"; b += decodeModSM(show, ++b, op1, 0, flip_imm_sz ? 2 : 3, flip_addr_sz); break; case 0x34: s = "xor"; ++b; snprintf(op1, sizeof(op1), "al, %x", (void *) *b); break; case 0x35: s = "xor"; if (flip_imm_sz) { snprintf(op1, sizeof(op1), "ax, %x", *(u16 *)++ b); ++b; } else { snprintf(op1, sizeof(op1), "eax, %x", *(u32 *)++ b); b += 3; } break; case 0x37: s = "aaa"; break; case 0x38: s = "cmp"; b += decodeModSM(show, ++b, op1, 1, 1, flip_addr_sz); break; case 0x39: s = "cmp"; b += decodeModSM(show, ++b, op1, 1, flip_imm_sz ? 2 : 3, flip_addr_sz); break; case 0x3a: s = "cmp"; b += decodeModSM(show, ++b, op1, 0, 1, flip_addr_sz); break; case 0x3b: s = "cmp"; b += decodeModSM(show, ++b, op1, 0, flip_imm_sz ? 2 : 3, flip_addr_sz); break; case 0x3c: s = "cmp"; ++b; snprintf(op1, sizeof(op1), "al, %x", (void *) *b); break; case 0x3d: s = "cmp"; if (flip_imm_sz) { snprintf(op1, sizeof(op1), "ax, %x", *(u16 *)++ b); ++b; } else { snprintf(op1, sizeof(op1), "eax, %x", *(u32 *)++ b); b += 3; } break; case 0x3f: s = "aas"; break; case 0x40: s = flip_imm_sz ? "inc ax" : "inc eax"; break; case 0x41: s = flip_imm_sz ? "inc cx" : "inc ecx"; break; case 0x42: s = flip_imm_sz ? "inc dx" : "inc edx"; break; case 0x43: s = flip_imm_sz ? "inc bx" : "inc ebx"; break; case 0x44: s = flip_imm_sz ? "inc sp" : "inc esp"; break; case 0x45: s = flip_imm_sz ? "inc bp" : "inc ebp"; break; case 0x46: s = flip_imm_sz ? "inc si" : "inc esi"; break; case 0x47: s = flip_imm_sz ? "inc di" : "inc edi"; break; case 0x48: s = flip_imm_sz ? "dec ax" : "dec eax"; break; case 0x49: s = flip_imm_sz ? "dec cx" : "dec ecx"; break; case 0x4a: s = flip_imm_sz ? "dec dx" : "dec edx"; break; case 0x4b: s = flip_imm_sz ? "dec bx" : "dec ebx"; break; case 0x4c: s = flip_imm_sz ? "dec sp" : "dec esp"; break; case 0x4d: s = flip_imm_sz ? "dec bp" : "dec ebp"; break; case 0x4e: s = flip_imm_sz ? "dec si" : "dec esi"; break; case 0x4f: s = flip_imm_sz ? "dec di" : "dec edi"; break; case 0x50: s = flip_imm_sz ? "push ax" : "push eax"; break; case 0x51: s = flip_imm_sz ? "push cx" : "push ecx"; break; case 0x52: s = flip_imm_sz ? "push dx" : "push edx"; break; case 0x53: s = flip_imm_sz ? "push bx" : "push ebx"; break; case 0x54: s = flip_imm_sz ? "push sp" : "push esp"; break; case 0x55: s = flip_imm_sz ? "push bp" : "push ebp"; break; case 0x56: s = flip_imm_sz ? "push si" : "push esi"; break; case 0x57: s = flip_imm_sz ? "push di" : "push edi"; break; case 0x58: s = flip_imm_sz ? "pop ax" : "pop eax"; break; case 0x59: s = flip_imm_sz ? "pop cx" : "pop ecx"; break; case 0x5a: s = flip_imm_sz ? "pop dx" : "pop edx"; break; case 0x5b: s = flip_imm_sz ? "pop bx" : "pop ebx"; break; case 0x5c: s = flip_imm_sz ? "pop sp" : "pop esp"; break; case 0x5d: s = flip_imm_sz ? "pop bp" : "pop ebp"; break; case 0x5e: s = flip_imm_sz ? "pop si" : "pop esi"; break; case 0x5f: s = flip_imm_sz ? "pop di" : "pop edi"; break; case 0x60: s = flip_imm_sz ? "pushaw" : "pusha"; break; case 0x61: s = flip_imm_sz ? "popaw" : "popa"; break; case 0x63: s = "arpl"; b += decodeModSM(show, ++b, op1, 1, 1, flip_addr_sz); break; case 0x68: s = "push"; if (flip_imm_sz) { snprintf(op1, sizeof(op1), "%x", *(u16 *)++ b); ++b; } else { snprintf(op1, sizeof(op1), "%x", *(u32 *)++ b); b += 3; } break; case 0x69: s = "imul"; b += decodeModSM(show, ++b, op1, 0, flip_imm_sz ? 2 : 3, flip_addr_sz); len = strlen(op1); if (flip_imm_sz) { snprintf(op1 + len, sizeof(op1) - len, ", %x", *(u16 *)++ b); ++b; } else { snprintf(op1 + len, sizeof(op1) - len, ", %x", *(u32 *)++ b); b += 3; } break; case 0x6a: s = "push"; ++b; snprintf(op1, sizeof(op1), "%x", (void *) *b); case 0x6b: s = "imul"; b += decodeModSM(show, ++b, op1, 0, flip_imm_sz ? 2 : 3, flip_addr_sz); len = strlen(op1); snprintf(op1 + len, sizeof(op1) - len, ", %x", *(u8 *)++ b); break; case 0x6c: s = flip_addr_sz ? "ins bytes ptr es:[di], dx" : "insb"; break; case 0x6d: if (flip_addr_sz) { s = flip_imm_sz ? "ins word ptr es:[di], dx" : "ins dword ptr es:[di], dx"; } else { s = flip_imm_sz ? "insw" : "insd"; } break; case 0x6e: s = flip_addr_sz ? "outs dx, byte ptr [si]" : "outsb"; break; case 0x6f: if (flip_addr_sz) { s = flip_imm_sz ? "outs dx, word ptr [si]" : "outs dx, dword ptr [si]"; } else { s = flip_imm_sz ? "outsw" : "outsd"; } break; case 0x70: s = "jo"; ++b; snprintf(op1, sizeof(op1), "%x", (void *) entry + (u32) b - (u32) f_entry + *b + 1); break; case 0x71: s = "jno"; ++b; snprintf(op1, sizeof(op1), "%x", (void *) entry + (u32) b - (u32) f_entry + *b + 1); break; case 0x72: s = "jb"; ++b; snprintf(op1, sizeof(op1), "%x", (void *) entry + (u32) b - (u32) f_entry + *b + 1); break; case 0x73: s = "jnb"; ++b; snprintf(op1, sizeof(op1), "%x", (void *) entry + (u32) b - (u32) f_entry + *b + 1); break; case 0x74: s = "jz"; ++b; snprintf(op1, sizeof(op1), "%x", (void *) entry + (u32) b - (u32) f_entry + *b + 1); break; case 0x75: s = "jnz"; ++b; snprintf(op1, sizeof(op1), "%x", (void *) entry + (u32) b - (u32) f_entry + *b + 1); break; case 0x76: s = "jbe"; ++b; snprintf(op1, sizeof(op1), "%x", (void *) entry + (u32) b - (u32) f_entry + *b + 1); break; case 0x77: s = "ja"; ++b; snprintf(op1, sizeof(op1), "%x", (void *) entry + (u32) b - (u32) f_entry + *b + 1); break; case 0x78: s = "js"; ++b; snprintf(op1, sizeof(op1), "%x", (void *) entry + (u32) b - (u32) f_entry + *b + 1); break; case 0x79: s = "jns"; ++b; snprintf(op1, sizeof(op1), "%x", (void *) entry + (u32) b - (u32) f_entry + *b + 1); break; case 0x7a: s = "jp"; ++b; break; case 0x7b: s = "jnp"; ++b; snprintf(op1, sizeof(op1), "%x", (void *) entry + (u32) b - (u32) f_entry + *b + 1); break; case 0x7c: s = "jl"; ++b; snprintf(op1, sizeof(op1), "%x", (void *) entry + (u32) b - (u32) f_entry + *b + 1); break; case 0x7d: s = "jnl"; ++b; snprintf(op1, sizeof(op1), "%x", (void *) entry + (u32) b - (u32) f_entry + *b + 1); break; case 0x7e: s = "jle"; ++b; snprintf(op1, sizeof(op1), "%x", (void *) entry + (u32) b - (u32) f_entry + *b + 1); break; case 0x7f: s = "jnle"; ++b; snprintf(op1, sizeof(op1), "%x", (void *) entry + (u32) b - (u32) f_entry + *b + 1); break; case 0x80: b += decodeModSM(show, ++b, op1, 1, 0, flip_addr_sz); switch ((*b & 0x38) / 8) { case 0: s = "add"; break; case 1: s = "or"; break; case 2: s = "adc"; break; case 3: s = "sbb"; break; case 4: s = "and"; break; case 5: s = "sub"; break; case 6: s = "xor"; break; case 7: s = "cmp"; break; default: if (show) print("Invalid Mod R/M byte."); return 1000; } len = strlen(op1); snprintf(op1 + len, sizeof(op1) - len, ", %x", *(u8 *)++ b); break; case 0x81: b += decodeModSM(show, ++b, op1, 1, 0, flip_addr_sz); switch ((*b & 0x38) / 8) { case 0: s = "add"; break; case 1: s = "or"; break; case 2: s = "adc"; break; case 3: s = "sbb"; break; case 4: s = "and"; break; case 5: s = "sub"; break; case 6: s = "xor"; break; case 7: s = "cmp"; break; default: if (show) print("Invalid Mod R/M byte."); return 1000; } len = strlen(op1); if (flip_imm_sz) { snprintf(op1 + len, sizeof(op1) - len, ", %x", *(u16 *)++ b); ++b; } else { snprintf(op1 + len, sizeof(op1) - len, ", %x", *(u32 *)++ b); b += 3; } break; case 0x82: b += decodeModSM(show, ++b, op1, 1, 0, flip_addr_sz); switch ((*b & 0x38) / 8) { case 0: s = "add"; break; case 1: s = "or"; break; case 2: s = "adc"; break; case 3: s = "sbb"; break; case 4: s = "and"; break; case 5: s = "sub"; break; case 6: s = "xor"; break; case 7: s = "cmp"; break; default: if (show) print("Invalid Mod R/M byte."); return 1000; } len = strlen(op1); snprintf(op1 + len, sizeof(op1) - len, ", %x", *(u8 *)++ b); break; case 0x83: b += decodeModSM(show, ++b, op1, 1, 0, flip_addr_sz); switch ((*b & 0x38) / 8) { case 0: s = "add"; break; case 1: s = "or"; break; case 2: s = "adc"; break; case 3: s = "sbb"; break; case 4: s = "and"; break; case 5: s = "sub"; break; case 6: s = "xor"; break; case 7: s = "cmp"; break; default: if (show) print("Invalid Mod R/M byte."); return 1000; } len = strlen(op1); snprintf(op1 + len, sizeof(op1) - len, ", %x", *(u8 *)++ b); break; case 0x84: s = "test"; b += decodeModSM(show, ++b, op1, 1, 1, flip_addr_sz); break; case 0x85: s = "test"; b += decodeModSM(show, ++b, op1, 1, flip_imm_sz ? 2 : 3, flip_addr_sz); break; case 0x86: s = "xchg"; b += decodeModSM(show, ++b, op1, 1, 1, flip_addr_sz); break; case 0x87: s = "xchg"; b += decodeModSM(show, ++b, op1, 1, flip_imm_sz ? 2 : 3, flip_addr_sz); break; case 0x88: s = "mov"; b += decodeModSM(show, ++b, op1, 1, 1, flip_addr_sz); break; case 0x89: s = "mov"; b += decodeModSM(show, ++b, op1, 1, flip_imm_sz ? 2 : 3, flip_addr_sz); break; case 0x8a: s = "mov"; b += decodeModSM(show, ++b, op1, 0, 1, flip_addr_sz); break; case 0x8b: s = "mov"; b += decodeModSM(show, ++b, op1, 0, flip_imm_sz ? 2 : 3, flip_addr_sz); break; case 0x8c: s = "mov"; b += decodeModSM(show, ++b, op1, 1, 4, flip_addr_sz); break; case 0x8d: s = "lea"; b += decodeModSM_memonly(show, ++b, op1, 0, flip_imm_sz ? 2 : 3, flip_addr_sz); break; case 0x8e: s = "mov"; b += decodeModSM(show, ++b, op1, 0, 4, flip_addr_sz); break; case 0x8f: s = "pop"; b += decodeModSM(show, ++b, op1, 1, 0, flip_addr_sz); break; case 0x90: s = flip_imm_sz ? "xchg ax, ax" : "nop"; break; case 0x91: s = flip_imm_sz ? "xchg ax, cx" : "xchg eax, ecx"; break; case 0x92: s = flip_imm_sz ? "xchg ax, dx" : "xchg eax, edx"; break; case 0x93: s = flip_imm_sz ? "xchg ax, bx" : "xchg eax, ebx"; break; case 0x94: s = flip_imm_sz ? "xchg ax, sp" : "xchg eax, esp"; break; case 0x95: s = flip_imm_sz ? "xchg ax, bp" : "xchg eax, ebp"; break; case 0x96: s = flip_imm_sz ? "xchg ax, si" : "xchg eax, esi"; break; case 0x97: s = flip_imm_sz ? "xchg ax, di" : "xchg eax, edi"; break; case 0x98: s = flip_imm_sz ? "cbw" : "cwde"; break; case 0x99: s = flip_imm_sz ? "cwd" : "cdq"; break; case 0x9a: s = "call"; if (flip_imm_sz) { snprintf(op1, sizeof(op1), "%x:%x", *(u16 *) (b + 2), *(u16 *)++ b); b += 3; } else { snprintf(op1, sizeof(op1), "far ptr %x:%x", *(u16 *) (b + 4), *(u32 *)++ b); b += 5; } break; case 0x9b: s = "wait"; break; case 0x9c: s = flip_imm_sz ? "pushfw" : "pushf"; break; case 0x9d: s = flip_imm_sz ? "popfw" : "popf"; break; case 0x9e: s = "sahf"; break; case 0x9f: s = "lahf"; break; case 0xa0: s = "mov"; snprintf(op1, sizeof(op1), "al, ds:%x", *(u32 *)++ b); b += 3; break; case 0xa1: s = "mov"; snprintf(op1, sizeof(op1), flip_imm_sz ? "ax, ds:%x" : "eax, ds:%x", *(u32 *)++ b); b += 3; break; case 0xa2: s = "mov"; snprintf(op1, sizeof(op1), "ds:%x, al", *(u32 *)++ b); b += 3; break; case 0xa3: s = "mov"; snprintf(op1, sizeof(op1), flip_imm_sz ? "ds:%x, ax" : "ds:%x, eax", *(u32 *)++ b); b += 3; break; case 0xa4: s = flip_addr_sz ? "movs byte ptr es:[di], byte ptr [si]" : "movsb"; break; case 0xa5: if (flip_addr_sz) { s = flip_imm_sz ? "movs word ptr es:[di], word ptr [si]" : "movs dword ptr es:[di], dword ptr [si]"; } else { s = flip_imm_sz ? "movsw" : "movsd"; } break; case 0xa6: s = flip_addr_sz ? "cmps byte ptr [si], byte ptr es:[di]" : "cmpsb"; break; case 0xa7: if (flip_addr_sz) { s = flip_imm_sz ? "movs word ptr [si], word ptr es:[di]" : "movs dword ptr [si], dword ptr es:[di]"; } else { s = flip_imm_sz ? "cmpsw" : "cmpsd"; } break; case 0xa8: s = "test"; ++b; snprintf(op1, sizeof(op1), "al, %x", (void *) *b); break; case 0xa9: s = "test"; if (flip_imm_sz) { snprintf(op1, sizeof(op1), "eax, %x", *(u32 *)++ b); ++b; } else { snprintf(op1, sizeof(op1), "ax, %x", *(u16 *)++ b); b += 3; } break; case 0xaa: s = flip_addr_sz ? "stos byte ptr es:[di]" : "stosb"; break; case 0xab: if (flip_addr_sz) { s = flip_imm_sz ? "stos word ptr es:[di]" : "stos dword ptr es:[di]"; } else { s = flip_imm_sz ? "stosw" : "stosd"; } break; case 0xac: s = flip_addr_sz ? "lods byte ptr [si]" : "lodsb"; break; case 0xad: if (flip_addr_sz) { s = flip_imm_sz ? "lods word ptr [si]" : "lods dword ptr [si]"; } else { s = flip_imm_sz ? "lodsw" : "lodsd"; } break; case 0xae: s = flip_addr_sz ? "scas byte ptr es:[di]" : "scasb"; break; case 0xaf: if (flip_addr_sz) { s = flip_imm_sz ? "scas word ptr es:[di]" : "scas dword ptr es:[di]"; } else { s = flip_imm_sz ? "scasw" : "scasd"; } break; case 0xb0: s = "mov"; ++b; snprintf(op1, sizeof(op1), "al, %x", (void *) *b); break; case 0xb1: s = "mov"; ++b; snprintf(op1, sizeof(op1), "cl, %x", (void *) *b); break; case 0xb2: s = "mov"; ++b; snprintf(op1, sizeof(op1), "dl, %x", (void *) *b); break; case 0xb3: s = "mov"; ++b; snprintf(op1, sizeof(op1), "al, %x", (void *) *b); break; case 0xb4: s = "mov"; ++b; snprintf(op1, sizeof(op1), "ah, %x", (void *) *b); break; case 0xb5: s = "mov"; ++b; snprintf(op1, sizeof(op1), "ch, %x", (void *) *b); break; case 0xb6: s = "mov"; ++b; snprintf(op1, sizeof(op1), "dh, %x", (void *) *b); break; case 0xb7: s = "mov"; ++b; snprintf(op1, sizeof(op1), "bh, %x", (void *) *b); break; case 0xb8: s = "mov"; if (flip_imm_sz) { snprintf(op1, sizeof(op1), "ax, %x", *(u16 *)++ b); ++b; } else { snprintf(op1, sizeof(op1), "eax, %x", *(u32 *)++ b); b += 3; } break; case 0xb9: s = "mov"; if (flip_imm_sz) { snprintf(op1, sizeof(op1), "cx, %x", *(u16 *)++ b); ++b; } else { snprintf(op1, sizeof(op1), "ecx, %x", *(u32 *)++ b); b += 3; } break; case 0xba: s = "mov"; if (flip_imm_sz) { snprintf(op1, sizeof(op1), "dx, %x", *(u16 *)++ b); ++b; } else { snprintf(op1, sizeof(op1), "edx, %x", *(u32 *)++ b); b += 3; } break; case 0xbb: s = "mov"; if (flip_imm_sz) { snprintf(op1, sizeof(op1), "bx, %x", *(u16 *)++ b); ++b; } else { snprintf(op1, sizeof(op1), "ebx, %x", *(u32 *)++ b); b += 3; } break; case 0xbc: s = "mov"; if (flip_imm_sz) { snprintf(op1, sizeof(op1), "sp, %x", *(u16 *)++ b); ++b; } else { snprintf(op1, sizeof(op1), "esp, %x", *(u32 *)++ b); b += 3; } break; case 0xbd: s = "mov"; if (flip_imm_sz) { snprintf(op1, sizeof(op1), "bp, %x", *(u16 *)++ b); ++b; } else { snprintf(op1, sizeof(op1), "ebp, %x", *(u32 *)++ b); b += 3; } break; case 0xbe: s = "mov"; if (flip_imm_sz) { snprintf(op1, sizeof(op1), "si, %x", *(u16 *)++ b); ++b; } else { snprintf(op1, sizeof(op1), "esi, %x", *(u32 *)++ b); b += 3; } break; case 0xbf: s = "mov"; if (flip_imm_sz) { snprintf(op1, sizeof(op1), "di, %x", *(u16 *)++ b); ++b; } else { snprintf(op1, sizeof(op1), "edi, %x", *(u32 *)++ b); b += 3; } break; case 0xc0: b += decodeModSM(show, ++b, op1, 1, 0, flip_addr_sz); switch ((*b & 0x38) / 8) { case 0: s = "rol"; break; case 1: s = "ror"; break; case 2: s = "rcl"; break; case 3: s = "rcr"; break; case 4: s = "shl"; break; case 5: s = "shr"; break; case 6: s = "shl"; break; case 7: s = "sar"; break; default: if (show) print("Invalid Mod R/M byte."); return 1000; } len = strlen(op1); snprintf(op1 + len, sizeof(op1) - len, ", %x", *(u8 *)++ b); break; case 0xc1: b += decodeModSM(show, ++b, op1, 1, 0, flip_addr_sz); switch ((*b & 0x38) / 8) { case 0: s = "rol"; break; case 1: s = "ror"; break; case 2: s = "rcl"; break; case 3: s = "rcr"; break; case 4: s = "shl"; break; case 5: s = "shr"; break; case 6: s = "shl"; break; case 7: s = "sar"; break; default: if (show) print("Invalid Mod R/M byte."); return 1000; } len = strlen(op1); snprintf(op1 + len, sizeof(op1) - len, ", %x", *(u8 *)++ b); break; case 0xc2: s = "retn"; snprintf(op1, sizeof(op1), "%x", *(u16 *)++ b); ++b; break; case 0xc3: s = "retn"; break; case 0xc4: s = "les"; b += decodeModSM_memonly(show, ++b, op1, 0, flip_imm_sz ? 2 : 3, flip_addr_sz); break; case 0xc5: s = "lds"; b += decodeModSM_memonly(show, ++b, op1, 0, flip_imm_sz ? 2 : 3, flip_addr_sz); break; case 0xc6: s = "mov"; b += decodeModSM(show, ++b, op1, 1, 0, flip_addr_sz); len = strlen(op1); snprintf(op1 + len, sizeof(op1) - len, ", %x", *(u8 *)++ b); break; case 0xc7: s = "mov"; b += decodeModSM(show, ++b, op1, 1, 0, flip_addr_sz); len = strlen(op1); if (flip_imm_sz) { snprintf(op1 + len, sizeof(op1) - len, ", %x", *(u16 *)++ b); ++b; } else { snprintf(op1 + len, sizeof(op1) - len, ", %x", *(u32 *)++ b); b += 3; } break; case 0xc8: s = "enter"; snprintf(op1, sizeof(op1), "%x, %x", *(u16 *) (b + 1), *(u8 *) (b + 3)); b += 3; break; case 0xc9: s = "leave"; break; case 0xca: s = "retf"; snprintf(op1, sizeof(op1), "%x", *(u16 *)++ b); ++b; break; case 0xcb: s = "retf"; break; case 0xcc: s = "int 3"; break; case 0xcd: s = "int"; ++b; snprintf(op1, sizeof(op1), "%x", (void *) *b); break; case 0xce: s = "into"; break; case 0xcf: s = "iret"; break; case 0xd0: b += decodeModSM(show, ++b, op1, 1, 0, flip_addr_sz); switch ((*b & 0x38) / 8) { case 0: s = "rol"; break; case 1: s = "ror"; break; case 2: s = "rcl"; break; case 3: s = "rcr"; break; case 4: s = "shl"; break; case 5: s = "shr"; break; case 6: s = "shl"; break; case 7: s = "sar"; break; default: if (show) print("Invalid Mod R/M byte."); return 1000; } len = strlen(op1); snprintf(op1 + len, sizeof(op1) - len, ", 1"); break; case 0xd1: b += decodeModSM(show, ++b, op1, 1, 0, flip_addr_sz); switch ((*b & 0x38) / 8) { case 0: s = "rol"; break; case 1: s = "ror"; break; case 2: s = "rcl"; break; case 3: s = "rcr"; break; case 4: s = "shl"; break; case 5: s = "shr"; break; case 6: s = "shl"; break; case 7: s = "sar"; break; default: if (show) print("Invalid Mod R/M byte."); return 1000; } len = strlen(op1); snprintf(op1 + len, sizeof(op1) - len, ", 1"); break; case 0xd2: b += decodeModSM(show, ++b, op1, 1, 0, flip_addr_sz); switch ((*b & 0x38) / 8) { case 0: s = "rol"; break; case 1: s = "ror"; break; case 2: s = "rcl"; break; case 3: s = "rcr"; break; case 4: s = "shl"; break; case 5: s = "shr"; break; case 6: s = "shl"; break; case 7: s = "sar"; break; default: if (show) print("Invalid Mod R/M byte."); return 1000; } len = strlen(op1); snprintf(op1 + len, sizeof(op1) - len, ", cl"); break; case 0xd3: b += decodeModSM(show, ++b, op1, 1, 0, flip_addr_sz); switch ((*b & 0x38) / 8) { case 0: s = "rol"; break; case 1: s = "ror"; break; case 2: s = "rcl"; break; case 3: s = "rcr"; break; case 4: s = "shl"; break; case 5: s = "shr"; break; case 6: s = "shl"; break; case 7: s = "sar"; break; default: if (show) print("Invalid Mod R/M byte."); return 1000; } len = strlen(op1); snprintf(op1 + len, sizeof(op1) - len, ", cl"); break; case 0xd4: s = "aam"; ++b; snprintf(op1, sizeof(op1), "%x", (void *) *b); break; case 0xd5: s = "aad"; ++b; snprintf(op1, sizeof(op1), "%x", (void *) *b); break; case 0xd6: s = "salc"; break; case 0xd7: s = "xlat"; break; case 0xd8: if (*++b == 0xd1) { s = "fcom st(1)"; } else if (*b == 0xd9) { s = "fcomp st(1)"; } else { switch ((*b & 0x38) >> 3) { case 0: s = "fadd"; b += decodeModSM_float(show, b, op1, 1, 0, flip_addr_sz); break; case 1: s = "fmul"; b += decodeModSM_float(show, b, op1, 1, 0, flip_addr_sz); break; case 2: s = "fcom"; b += decodeModSM_float(show, b, op1, 1, 0, flip_addr_sz); break; case 3: s = "fcomp"; b += decodeModSM_float(show, b, op1, 1, 0, flip_addr_sz); break; case 4: s = "fsub"; b += decodeModSM_float(show, b, op1, 1, 0, flip_addr_sz); break; case 5: s = "fsubr"; b += decodeModSM_float(show, b, op1, 1, 0, flip_addr_sz); break; case 6: s = "fdiv"; b += decodeModSM_float(show, b, op1, 1, 0, flip_addr_sz); break; case 7: s = "fdivr"; b += decodeModSM_float(show, b, op1, 1, 0, flip_addr_sz); break; default: if (show) print("Invalid Mod R/M byte."); return 1000; } } break; case 0xe0: s = "loopnz"; ++b; snprintf(op1, sizeof(op1), "%x", (void *) entry + (u32) b - (u32) f_entry + *b + 1); break; case 0xe1: s = "loopz"; ++b; snprintf(op1, sizeof(op1), "%x", (void *) entry + (u32) b - (u32) f_entry + *b + 1); break; case 0xe2: s = "loop"; ++b; snprintf(op1, sizeof(op1), "%x", (void *) entry + (u32) b - (u32) f_entry + *b + 1); break; case 0xe3: s = "jcxz"; ++b; snprintf(op1, sizeof(op1), "%x", (void *) entry + (u32) b - (u32) f_entry + *b + 1); break; case 0xe4: s = "in"; ++b; snprintf(op1, sizeof(op1), "al, %x", (void *) *b); break; case 0xe5: s = "in"; ++b; snprintf(op1, sizeof(op1), flip_imm_sz ? "ax, %x" : "eax, %x", (void *) *b); break; case 0xe6: s = "out"; ++b; snprintf(op1, sizeof(op1), "%x, al", (void *) *b); break; case 0xe7: s = "in"; ++b; snprintf(op1, sizeof(op1), flip_imm_sz ? "%x, ax" : "%x, eax", (void *) *b); break; case 0xe8: s = "call"; if (flip_imm_sz) { snprintf(op1, sizeof(op1), "%x", entry + (u32) b - (u32) f_entry + *(u16 *)++ b + 3); b += 2; } else { snprintf(op1, sizeof(op1), "%x", (void *) entry + (u32) b - (u32) f_entry + *(u32 *)++ b + 4); b += 3; } break; case 0xe9: s = "jmp"; if (flip_imm_sz) { snprintf(op1, sizeof(op1), "near ptr %x", entry + (u32) b - (u32) f_entry + *(u16 *)++ b + 3); ++b; } else { snprintf(op1, sizeof(op1), "near ptr %x", (void *) entry + (u32) b - (u32) f_entry + *(u32 *)++ b + 4); b += 3; } break; case 0xea: s = "jmp"; if (flip_imm_sz) { snprintf(op1, sizeof(op1), "%x:%x", *(u16 *) (b + 2), *(u16 *)++ b); b += 3; } else { snprintf(op1, sizeof(op1), "%x:%x", *(u16 *) (b + 4), *(u32 *)++ b); b += 5; } break; case 0xeb: s = "jmp"; ++b; snprintf(op1, sizeof(op1), "%x", (void *) entry + (u32) b - (u32) f_entry + *b + 1); break; case 0xec: s = "in al, dx"; break; case 0xed: s = flip_imm_sz ? "in ax, dx" : "in eax, dx"; break; case 0xee: s = "out dx, al"; break; case 0xef: s = flip_imm_sz ? "out dx, ax" : "out dx, eax"; break; case 0xf1: s = "int 1"; break; case 0xf4: s = "hlt"; break; case 0xf5: s = "cmc"; break; case 0xf6: b += decodeModSM(show, ++b, op1, 1, 0, flip_addr_sz); switch ((*b & 0x38) / 8) { case 0: s = "test"; len = strlen(op1); snprintf(op1 + len, sizeof(op1) - len, "%x", *(u8 *)++ b); break; case 1: s = "test"; len = strlen(op1); snprintf(op1 + len, sizeof(op1) - len, "%x", *(u8 *)++ b); break; case 2: s = "not"; break; case 3: s = "neg"; break; case 4: s = "mul ax, al, "; break; case 5: s = "imul ax, al, "; break; case 6: s = "div al, ah, ax, "; break; case 7: s = "idiv al, ah, ax, "; break; default: if (show) print("Invalid Mod R/M byte."); return 1000; } break; case 0xf7: b += decodeModSM(show, ++b, op1, 1, 0, flip_addr_sz); switch ((*b & 0x38) / 8) { case 0: s = "test"; len = strlen(op1); if (flip_imm_sz) { snprintf(op1 + len, sizeof (op1) - len, "%x", *(u16 *)++ b); ++b; } else { snprintf(op1 + len, sizeof (op1) - len, "%x", *(u32 *)++ b); b += 3; } break; case 1: s = "test"; len = strlen(op1); if (flip_imm_sz) { snprintf(op1 + len, sizeof (op1) - len, "%x", *(u16 *)++ b); ++b; } else { snprintf(op1 + len, sizeof (op1) - len, "%x", *(u32 *)++ b); b += 3; } break; case 2: s = "not"; break; case 3: s = "neg"; break; case 4: s = "mul rdx, rax, "; break; case 5: s = "imul rdx, rax, "; break; case 6: s = "div rdx, rax, "; break; case 7: s = "idiv rdx, rax, "; break; default: if (show) print("Invalid Mod R/M byte."); return 1000; } break; case 0xf8: s = "clc"; break; case 0xf9: s = "stc"; break; case 0xfa: s = "cli"; break; case 0xfb: s = "sti"; break; case 0xfc: s = "cld"; break; case 0xfd: s = "std"; break; case 0xfe: b += decodeModSM(show, ++b, op1, 1, 0, flip_addr_sz); if (!((*b & 0x38) / 8)) { s = "inc"; } else if ((*b & 0x38) / 8 == 1) { s = "dec"; } else { if (show) print("Invalid Mod R/M byte."); return 1000; } break; case 0xff: switch ((*++b & 0x38) >> 3) { case 0: s = "inc"; b += decodeModSM(show, b, op1, 1, 0, flip_addr_sz); break; case 1: s = "dec"; b += decodeModSM(show, b, op1, 1, 0, flip_addr_sz); break; case 2: s = "call"; b += decodeModSM(show, b, op1, 1, 0, flip_addr_sz); break; case 3: s = "callf"; b += decodeModSM_memonly (show, b, op1, 1, 0, flip_addr_sz); break; case 4: s = "jmp"; b += decodeModSM(show, b, op1, 1, 0, flip_addr_sz); break; case 5: s = "jmpf"; b += decodeModSM_memonly (show, b, op1, 1, 0, flip_addr_sz); break; case 6: s = "push"; b += decodeModSM(show, b, op1, 1, 0, flip_addr_sz); break; default: if (show) print("Invalid Mod R/M byte."); return 1000; } break; default: if (show) print("invalid opcode\r\n"); return 1000; } strcompressdelimiter(s, ' '); if (show) printf(" %X: %s %s\r\n", (u32) a, s, op1); else if (string != NULL) sprintf(string, " %X: %s %s\r\n", (u32) a, s, op1); ++b; } return b - a; }