TCODE static void uprintf(char* buffer) { /* uputchar('.'); char buffer[100]; va_list arg; va_start(arg, fmt); //vsnprintf(buffer, 511, fmt, arg); vsnprintf(buffer, 99, fmt, arg); va_end(arg); */ int i; int len = strlen(buffer); for (i = 0; i < len; i++) { uputchar( *(((char*)buffer) + i)); } }
static void ua_str(char *s) { char ch; if(s == (char *) NULL) { uprintf("<invalid>"); } else { while((ch = *s++) != 0) { if(ch == '%') { ch = *s++; percent(ch, *s++); } else { if(ch == ' ') ch = '\t'; if(ch == '@') ch = ' '; uputchar(ch); } } } }
static void ua_str(char *str) { char c,c1; if ( !str ) { uprintf("<invalid>"); return; } if ( strpbrk( str,"CDFGRST" ) ) // specifiers for registers=>no size 2b specified must_do_size = 0; while( (c = *str++) != 0 ) if (c == '%') { c = *str++; if ( c ) c1 = *str++; else c1 = 0; percent(c, c1); if ( !c1 ) break; } else uputchar(c); }
/* Main table driver */ static void percent( char type, char subtype ) { DWORD vofs; int extend = (addrsize == 32) ? 4 : 2; BYTE c; switch (type) { case 'A': /* direct address */ SET_FLAG( Info->CurrentFlags,DISASM_FL_CODE ); outhex(subtype, extend, 0, addrsize, 0); CLR_FLAG( Info->CurrentFlags,DISASM_FL_CODE ); break; case 'C': /* reg(r/m) picks control reg */ uprintf("C%d", REG(modrm())); must_do_size = 0; break; case 'D': /* reg(r/m) picks debug reg */ uprintf("D%d", REG(modrm())); must_do_size = 0; break; case 'E': /* r/m picks operand */ do_modrm(subtype); break; case 'G': /* reg(r/m) picks register */ if (subtype == 'F') /* 80*87 operand? */ reg_name(RM(modrm()), subtype); else reg_name(REG(modrm()), subtype); must_do_size = 0; break; case 'I': /* immed data */ SET_FLAG( Info->CurrentFlags,DISASM_FL_DATA ); outhex(subtype, 0, 0, opsize, 0); CLR_FLAG( Info->CurrentFlags,DISASM_FL_DATA ); break; case 'J': /* relative IP offset */ vofs = 0; switch(bytes(subtype)) { /* sizeof offset value */ case 1: vofs = (DWORD)getbyte(); break; case 2: vofs = (DWORD)getbyte(); vofs |= (DWORD)getbyte() << 8; vofs &= 0xFFFFu; break; case 4: vofs = (DWORD)getbyte(); /* yuk! */ vofs |= (DWORD)getbyte() << 8; vofs |= (DWORD)getbyte() << 16; vofs |= (DWORD)getbyte() << 24; break; } SET_FLAG( Info->CurrentFlags,DISASM_FL_CODE|DISASM_FL_OFFSET ); uprintf("%s", addr_to_hex(vofs + Info->instruction_length,1,bytes(subtype)) ); CLR_FLAG( Info->CurrentFlags,DISASM_FL_CODE|DISASM_FL_OFFSET ); break; case 'K': if (do_distance==0) break; switch (subtype) { case 'f': uprintf( Info->GetStringName(DISASM_ID_FAR) ); uputchar(' '); break; case 'n': uprintf( Info->GetStringName(DISASM_ID_NEAR) ); uputchar(' '); break; case 's': uprintf( Info->GetStringName(DISASM_ID_SHORT) ); uputchar(' '); break; } break; case 'M': /* r/m picks memory */ do_modrm(subtype); break; case 'O': /* offset only */ ua_str("%p:["); SET_FLAG( Info->CurrentFlags,DISASM_FL_REF ); outhex(subtype, extend, 0, addrsize, 0); CLR_FLAG( Info->CurrentFlags,DISASM_FL_REF ); uputchar(']'); break; case 'P': /* prefix byte (rh) */ ua_str("%p:"); break; case 'R': /* mod(r/m) picks register */ reg_name(REG(modrm()), subtype); /* rh */ must_do_size = 0; break; case 'S': /* reg(r/m) picks segment reg */ uputchar("ecsdfg"[REG(modrm())]); uputchar('s'); must_do_size = 0; break; case 'T': /* reg(r/m) picks T reg */ uprintf("tr%d", REG(modrm())); must_do_size = 0; break; case 'X': /* ds:si type operator */ uprintf("ds:["); if (addrsize == 32) uputchar('e'); uprintf("si]"); break; case 'Y': /* es:di type operator */ uprintf("es:["); if (addrsize == 32) uputchar('e'); uprintf("di]"); break; case '2': /* old [pop cs]! now indexes */ ua_str(second[getbyte()]); /* instructions in 386/486 */ break; case 'g': /* modrm group `subtype' (0--7) */ ua_str( GetOPGroup(subtype) ); break; case 'd': /* sizeof operand==dword? */ if (opsize == 32) uputchar('d'); uputchar(subtype); break; case 'w': /* insert explicit size specifier */ if (opsize == 32) uputchar('d'); else uputchar('w'); uputchar(subtype); break; case 'e': /* extended reg name */ if (opsize == 32) { if (subtype == 'w') uputchar('d'); else { uputchar('e'); uputchar(subtype); } } else uputchar(subtype); break; case 'f': /* '87 opcode */ floating_point(subtype-'0'); break; case 'j': if (addrsize==32 || opsize==32) /* both of them?! */ uputchar('e'); break; case 'p': /* prefix byte */ switch (subtype) { case 'c': case 'd': case 'e': case 'f': case 'g': case 's': prefix = subtype; c = getbyte(); wordop = c & 1; ua_str( GetOP(c) ); break; case ':': if (prefix) uprintf("%cs:", prefix); break; case ' ': c = getbyte(); wordop = c & 1; ua_str( GetOP(c) ); break; } break; case 's': /* size override */ switch (subtype) { case 'a': addrsize = 48 - addrsize; c = getbyte(); wordop = c & 1; ua_str( GetOP(c) ); break; case 'o': opsize = 48 - opsize; c = getbyte(); wordop = c & 1; ua_str( GetOP(c) ); break; } break; } }
/*------------------------------------------------------------------------*/ static void do_modrm(char subtype) { int mod = MOD(modrm()); int rm = RM(modrm()); int extend = (addrsize == 32) ? 4 : 2; /* specifies two registers */ if (mod == 3) { reg_name(rm, subtype); return; } if (must_do_size) { if (wordop) { if (addrsize==32 || opsize==32) /* then must specify size */ uprintf( Info->GetStringName(DISASM_ID_DWORD_PTR) ); else uprintf( Info->GetStringName(DISASM_ID_WORD_PTR) ); } else uprintf( Info->GetStringName(DISASM_ID_BYTE_PTR) ); uputchar(' '); } /* mem operand with 32 bit ofs */ if ((mod == 0) && (rm == 5) && (addrsize == 32)) { ua_str("%p:["); SET_FLAG( Info->CurrentFlags,DISASM_FL_REF ); outhex('d', extend, 0, addrsize, 0); CLR_FLAG( Info->CurrentFlags,DISASM_FL_REF ); uputchar(']'); } else /* 16 bit dsplcmnt */ if ((mod == 0) && (rm == 6) && (addrsize == 16)) { ua_str("%p:["); SET_FLAG( Info->CurrentFlags,DISASM_FL_REF ); outhex('w', extend, 0, addrsize, 0); CLR_FLAG( Info->CurrentFlags,DISASM_FL_REF ); uputchar(']'); } else { /*All other*/ if ( (addrsize != 32) || (rm != 4) ) ua_str("%p:["); SET_FLAG( Info->CurrentFlags,DISASM_FL_REF | DISASM_FL_REFADD ); if (addrsize == 16) switch (rm) { case 0: uprintf("bx+si"); break; case 1: uprintf("bx+di"); break; case 2: uprintf("bp+si"); break; case 3: uprintf("bp+di"); break; case 4: uprintf("si"); break; case 5: uprintf("di"); break; case 6: uprintf("bp"); break; case 7: uprintf("bx"); break; } else switch (rm) { case 0: uprintf("eax"); break; case 1: uprintf("ecx"); break; case 2: uprintf("edx"); break; case 3: uprintf("ebx"); break; case 4: do_sib(mod); break; case 5: uprintf("ebp"); break; case 6: uprintf("esi"); break; case 7: uprintf("edi"); break; } switch (mod) { case 1: outhex('b', extend, 1, addrsize, 0); break; case 2: outhex('v', extend, 1, addrsize, 1); break; } CLR_FLAG( Info->CurrentFlags,DISASM_FL_REF | DISASM_FL_REFADD ); uputchar(']'); } }
static void percent(char type, char subtype) { unsigned int vofs = 0; char *name; int extend = (addrsize == 32) ? 4 : 2; unsigned char c; switch(type) { case 'A': /* Direct address */ outhex(subtype, extend, 0, addrsize, 0); break; case 'C': /* reg(r/m) picks control reg */ uprintf("CR%d", REG(modrm())); must_do_size = 0; break; case 'D': /* reg(r/m) picks debug reg */ uprintf("DR%d", REG(modrm())); must_do_size = 0; break; case 'E': /* r/m picks operand */ do_modrm(subtype); break; case 'G': /* reg(r/m) picks register */ if(subtype == 'f') reg_name(RM(modrm()), subtype); else reg_name(REG(modrm()), subtype); must_do_size = 0; break; case 'I': /* Immediate data */ outhex(subtype, 0, 0, opsize, 0); break; case 'J': /* Relative IP offset */ switch(bytes(subtype)) {/* Size of offset value */ case 1: vofs = (unsigned int) (signed char) getbyte(); break; case 2: vofs = getbyte(); vofs += getbyte() << 8; vofs = (unsigned int) (signed short) vofs; break; case 4: vofs = (unsigned int) getbyte(); vofs |= (unsigned int) getbyte() << 8; vofs |= (unsigned int) getbyte() << 16; vofs |= (unsigned int) getbyte() << 24; break; } name = addr_to_hex((int) (vofs + inst_offset)); uprintf("%s", name); break; case 'K': switch(subtype) { case 'f': ua_str("FAR@"); break; case 'n': ua_str("NEAR@"); break; case 's': ua_str("SHORT@"); break; } break; case 'M': /* r/m picks memory */ do_modrm(subtype); break; case 'O': /* Offset only */ ua_str("%p:["); outhex(subtype, extend, 0, addrsize, 0); uputchar(']'); break; case 'P': /* Prefix byte */ ua_str("%p:"); break; case 'R': /* mod(r/m) picks register */ reg_name(REG(modrm()), subtype); must_do_size = 0; break; case 'S': /* reg(r/m) picks segment register */ uputchar("ECSDFG"[REG(modrm())]); uputchar('S'); must_do_size = 0; break; case 'T': /* reg(r/m) picks T reg */ uprintf("TR%d", REG(modrm())); must_do_size = 0; break; case 'X': /* DS:SI type operator */ uprintf("DS:["); if(addrsize == 32) uputchar('E'); uprintf("SI]"); break; case 'Y': /* ES:DI type operator */ uprintf("ES:["); if(addrsize == 32) uputchar('E'); uprintf("DI]"); break; case '2': /* Extended decode with second byte */ ua_str(second[getbyte()]); break; case 'g': /* modrm group 'subtype' (0--7) */ ua_str(groups[subtype-'0'][REG(modrm())]); break; case 'd': /* Size of operand == dword? */ if(opsize == 32) uputchar('D'); uputchar(subtype);/* No real subtype; following char */ break; case 'w': /* Insert explicit size specifier */ if(opsize == 32) uputchar('D'); else uputchar('W'); uputchar(subtype);/* No real subtype; following char */ break; case 'e': /* Extended reg name */ if(opsize == 32) { if(subtype == 'w') uputchar('D'); else { uputchar('E'); uputchar(subtype); } } else uputchar(subtype); break; case 'f': /* 80x87 opcode */ floating_point(subtype-'0'); break; case 'j': if(addrsize == 32 || opsize == 32) /* both of them?! */ uputchar('E'); break; case 'p': /* Prefix byte */ switch(subtype) { case 'C': case 'D': case 'E': case 'F': case 'G': case 'S': prefix = subtype; c = getbyte(); wordop = c & 1; ua_str(opmap1[c]); break; case ':': if(prefix) uprintf("%cS:", prefix); break; case ' ': c = getbyte(); wordop = c & 1; ua_str(opmap1[c]); break; } break; case 's': /* Size override */ switch(subtype) { case 'a': addrsize = 48 - addrsize; c = getbyte(); wordop = c & 1; ua_str(opmap1[c]); /* ua_str(opmap1[getbyte()]); */ break; case 'o': opsize = 48 - opsize; c = getbyte(); wordop = c & 1; ua_str(opmap1[c]); /* ua_str(opmap1[getbyte()]); */ break; } break; } }
static void do_modrm(char subtype) { int mod = MOD(modrm()); int rm = RM(modrm()); int extend = (addrsize == 32) ? 4 : 2; if(mod == 3) { /* Specifies two registers */ reg_name(rm, subtype); return; } if(must_do_size) { if(wordop) { if(addrsize == 32 || opsize == 32) ua_str("DWORD@PTR@"); else ua_str("WORD@PTR@"); } else ua_str("BYTE@PTR@"); } if((mod == 0) && (rm == 5) && (addrsize == 32)) { /* Mem operand with 32 bit offset */ ua_str("%p:["); outhex('d', extend, 0, addrsize, 0); uputchar(']'); return; } if((mod == 0) && (rm == 6) && (addrsize == 16)) { /* 16 bit displacement */ ua_str("%p:["); outhex('w', extend, 0, addrsize, 0); uputchar(']'); return; } if((addrsize != 32) || (rm != 4)) ua_str("%p:["); if(addrsize == 16) { switch(rm) { case 0: uprintf("BX+SI"); break; case 1: uprintf("BX+DI"); break; case 2: uprintf("BP+SI"); break; case 3: uprintf("BP+DI"); break; case 4: uprintf("SI"); break; case 5: uprintf("DI"); break; case 6: uprintf("BP"); break; case 7: uprintf("BX"); break; } } else { switch(rm) { case 0: uprintf("EAX"); break; case 1: uprintf("ECX"); break; case 2: uprintf("EDX"); break; case 3: uprintf("EBX"); break; case 4: do_sib(mod); break; case 5: uprintf("EBP"); break; case 6: uprintf("ESI"); break; case 7: uprintf("EDI"); break; } } switch(mod) { case 1: outhex('b', extend, 1, addrsize, 0); break; case 2: outhex('v', extend, 1, addrsize, 1); break; } uputchar(']'); }
void uputs(char *buf) { _uputs(buf); uputchar('\r'); uputchar('\n'); }
/* Main table driver */ static void percent(char type, char subtype) { int32 vofs; char *name; int extend = (addrsize == 32) ? 4 : 2; char c; switch (type) { case 'A': /* direct address */ outhex(subtype, extend, 0, addrsize, 0); break; case 'C': /* reg(r/m) picks control reg */ uprintf("C%d", REG(modrm())); must_do_size = 0; break; case 'D': /* reg(r/m) picks debug reg */ uprintf("D%d", REG(modrm())); must_do_size = 0; break; case 'E': /* r/m picks operand */ do_modrm(subtype); break; case 'G': /* reg(r/m) picks register */ if (subtype == 'F') /* 80*87 operand? */ reg_name(RM(modrm()), subtype); else reg_name(REG(modrm()), subtype); must_do_size = 0; break; case 'I': /* immed data */ outhex(subtype, 0, 0, opsize, 0); break; case 'J': /* relative IP offset */ switch(bytes(subtype)) { /* sizeof offset value */ case 1: vofs = (int8)getbyte(); break; case 2: vofs = getbyte(); vofs += getbyte()<<8; vofs = (int16)vofs; break; case 4: vofs = (word32)getbyte(); /* yuk! */ vofs |= (word32)getbyte() << 8; vofs |= (word32)getbyte() << 16; vofs |= (word32)getbyte() << 24; break; } name = addr_to_hex(vofs+instruction_offset,1); uprintf("%s", name); break; case 'K': if (do_distance==0) break; switch (subtype) { case 'f': ua_str("far "); break; case 'n': ua_str("near "); break; case 's': ua_str("short "); break; } break; case 'M': /* r/m picks memory */ do_modrm(subtype); break; case 'O': /* offset only */ ua_str("%p:["); outhex(subtype, extend, 0, addrsize, 0); uputchar(']'); break; case 'P': /* prefix byte (rh) */ ua_str("%p:"); break; case 'R': /* mod(r/m) picks register */ reg_name(REG(modrm()), subtype); /* rh */ must_do_size = 0; break; case 'S': /* reg(r/m) picks segment reg */ uputchar("ecsdfg"[REG(modrm())]); uputchar('s'); must_do_size = 0; break; case 'T': /* reg(r/m) picks T reg */ uprintf("tr%d", REG(modrm())); must_do_size = 0; break; case 'X': /* ds:si type operator */ uprintf("ds:["); if (addrsize == 32) uputchar('e'); uprintf("si]"); break; case 'Y': /* es:di type operator */ uprintf("es:["); if (addrsize == 32) uputchar('e'); uprintf("di]"); break; case '2': /* old [pop cs]! now indexes */ ua_str(second[getbyte()]); /* instructions in 386/486 */ break; case 'g': /* modrm group `subtype' (0--7) */ ua_str(groups[subtype-'0'][REG(modrm())]); break; case 'd': /* sizeof operand==dword? */ if (opsize == 32) uputchar('d'); uputchar(subtype); break; case 'w': /* insert explicit size specifier */ if (opsize == 32) uputchar('d'); else uputchar('w'); uputchar(subtype); break; case 'e': /* extended reg name */ if (opsize == 32) { if (subtype == 'w') uputchar('d'); else { uputchar('e'); uputchar(subtype); } } else uputchar(subtype); break; case 'f': /* '87 opcode */ floating_point(subtype-'0'); break; case 'j': if (addrsize==32 || opsize==32) /* both of them?! */ uputchar('e'); break; case 'p': /* prefix byte */ switch (subtype) { case 'c': case 'd': case 'e': case 'f': case 'g': case 's': prefix = subtype; c = getbyte(); wordop = c & 1; ua_str(opmap1[(unsigned char)c]); break; case ':': if (prefix) uprintf("%cs:", prefix); break; case ' ': c = getbyte(); wordop = c & 1; ua_str(opmap1[(unsigned char)c]); break; } break; case 's': /* size override */ switch (subtype) { case 'a': addrsize = 48 - addrsize; c = getbyte(); wordop = c & 1; ua_str(opmap1[(unsigned char)c]); /* ua_str(opmap1[getbyte()]); */ break; case 'o': opsize = 48 - opsize; c = getbyte(); wordop = c & 1; ua_str(opmap1[(unsigned char)c]); /* ua_str(opmap1[getbyte()]); */ break; } break; } }
/*------------------------------------------------------------------------*/ static void do_modrm(char subtype) { int mod = MOD(modrm()); int rm = RM(modrm()); int extend = (addrsize == 32) ? 4 : 2; if (mod == 3) { /* specifies two registers */ reg_name(rm, subtype); return; } if (must_do_size) { if (wordop) { if (addrsize==32 || opsize==32) { /* then must specify size */ ua_str("dword ptr "); } else { ua_str("word ptr "); } } else { ua_str("byte ptr "); } } if ((mod == 0) && (rm == 5) && (addrsize == 32)) {/* mem operand with 32 bit ofs */ ua_str("%p:["); outhex('d', extend, 0, addrsize, 0); uputchar(']'); return; } if ((mod == 0) && (rm == 6) && (addrsize == 16)) { /* 16 bit dsplcmnt */ ua_str("%p:["); outhex('w', extend, 0, addrsize, 0); uputchar(']'); return; } if ((addrsize != 32) || (rm != 4)) ua_str("%p:["); if (addrsize == 16) { switch (rm) { case 0: uprintf("bx+si"); break; case 1: uprintf("bx+di"); break; case 2: uprintf("bp+si"); break; case 3: uprintf("bp+di"); break; case 4: uprintf("si"); break; case 5: uprintf("di"); break; case 6: uprintf("bp"); break; case 7: uprintf("bx"); break; } } else { switch (rm) { case 0: uprintf("eax"); break; case 1: uprintf("ecx"); break; case 2: uprintf("edx"); break; case 3: uprintf("ebx"); break; case 4: do_sib(mod); break; case 5: uprintf("ebp"); break; case 6: uprintf("esi"); break; case 7: uprintf("edi"); break; } } switch (mod) { case 1: outhex('b', extend, 1, addrsize, 0); break; case 2: outhex('v', extend, 1, addrsize, 1); break; } uputchar(']'); }