/*------------------------------------------------------------------------*/ static void outhex( char subtype, int extend, int optional, int defsize, int sign) { int n=0, s=0, i; BYTE buff[6]; signed long int delta; switch (subtype) { case 'q': if (wordop) n = ( opsize == 32 ) ? 4 : 2; else n = 1; break; case 'a': break; case 'x': extend = 2; n = 1; break; case 'b': n = 1; break; case 'w': n = 2; break; case 'd': n = 4; break; case 's': n = 6; break; case 'c': case 'v': n = (defsize == 32) ? 4 : 2; break; case 'p': n = (defsize == 32) ? 6 : 4; s = 1; break; } for (i=0; i<n; i++) buff[i] = getbyte(); for (; i<extend; i++) buff[i] = (BYTE) ((buff[i-1] & 0x80) ? '\xff' : '\x0'); if (s) { uprintf("%02X%02X:", buff[n-1], buff[n-2]); n -= 2; } delta = 0; switch (n) { case 1: delta = *(signed char *)buff; break; case 2: delta = *(signed int *)buff; break; case 4: delta = *(signed long *)buff; break; } if (extend > n) uprintf( "%s",addr_to_hex(delta,subtype!='x',extend) ); else uprintf( "%s", addr_to_hex(delta,sign,n) ); }
/* 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 outhex(char subtype, int extend, int optional, int defsize, int sign) { int i; int n = 0; int s = 0; int delta = 0; unsigned char buff[6]; char *name; char signchar; switch(subtype) { case 'q': if(wordop) { if(opsize == 16) n = 2; else n = 4; } else n = 1; break; case 'a': break; case 'x': extend = 2; n = 1; break; case 'b': n = 1; break; case 'w': n = 2; break; case 'd': n = 4; break; case 's': n = 6; break; case 'c': case 'v': if(defsize == 32) n = 4; else n = 2; break; case 'p': if(defsize == 32) n = 6; else n = 4; s = 1; break; } for (i = 0; i < n; i++) buff[i] = getbyte(); for (; i < extend; i++) buff[i] = (unsigned char) ((buff[i-1] & (unsigned char) 0x80) ? 0xff : 0); if(s) { uprintf("%02X%02X:", buff[n-1], buff[n-2]); n -= 2; } switch(n) { case 1: delta = *(signed char *) buff; break; case 2: delta = *(signed short *) buff; break; case 4: delta = *(signed int *) buff; break; } if(extend > n) { if(subtype != 'x') { if(delta < 0) { delta = -delta; signchar = '-'; } else signchar = '+'; if(delta || !optional) uprintf("%c%0*X", signchar, extend, delta); } else { if(extend == 2) delta = (unsigned short) delta; uprintf("%0.*X", 2*extend+1, delta); } return; } if((n == 4) && !sign) { name = addr_to_hex(delta); uprintf("%s", name); return; } switch(n) { case 1: delta = (int) (signed char) delta; if(sign && delta < 0) { delta = -delta; signchar = '-'; } else signchar = '+'; if(sign) uprintf("%c%02X",signchar, (unsigned char) delta); else uprintf("%02X", (unsigned char) delta); break; case 2: if(sign && (short) delta < 0) { signchar = '-'; delta = -delta; } else signchar = '+'; if(sign) uprintf("%c%04X", signchar, (short) delta); else uprintf("%04X", (unsigned short) delta); break; case 4: if(sign && delta < 0) { delta = -delta; signchar = '-'; } else signchar = '+'; if(sign) uprintf("%c%08X", signchar, delta); else uprintf("%08X", delta); break; } }
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; } }
/* 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 outhex(char subtype, int extend, int optional, int defsize, int sign) { int n=0, s=0, i; int32 delta; unsigned char buff[6]; char *name; char signchar; switch (subtype) { case 'q': if (wordop) { if (opsize==16) { n = 2; } else { n = 4; } } else { n = 1; } break; case 'a': break; case 'x': extend = 2; n = 1; break; case 'b': n = 1; break; case 'w': n = 2; break; case 'd': n = 4; break; case 's': n = 6; break; case 'c': case 'v': if (defsize == 32) n = 4; else n = 2; break; case 'p': if (defsize == 32) n = 6; else n = 4; s = 1; break; } for (i=0; i<n; i++) buff[i] = getbyte(); for (; i<extend; i++) buff[i] = (buff[i-1] & 0x80) ? 0xff : 0; if (s) { uprintf("%02X%02X:", buff[n-1], buff[n-2]); n -= 2; } switch (n) { case 1: delta = *(signed char *)buff; break; case 2: delta = *(signed int *)buff; break; case 4: delta = *(signed long *)buff; break; } if (extend > n) { if (subtype!='x') { if ((long)delta<0) { delta = -delta; signchar = '-'; } else signchar = '+'; if (delta || !optional) uprintf(do_hex?"%c%0*lX":"%c%0*lXh", signchar, do_hex?extend:extend+1, delta); } else { if (extend==2) delta = (word16) delta; uprintf(do_hex?"%0.*lX":"%0.*lXh", 2*extend+1, delta); /* uprintf(do_hex?"%0.*lX":"%0.*lXh", 2*(do_hex?extend:extend+1), delta); */ } return; } if ((n == 4) && !sign) { name = addr_to_hex(delta, 0); uprintf("%s", name); return; } switch (n) { case 1: if (sign && (char)delta<0) { delta = -delta; signchar = '-'; } else signchar = '+'; if (sign) uprintf(do_hex?"%c%02X":"%c%03Xh",signchar,(unsigned char)delta); else uprintf(do_hex?"%02X":"%03Xh", (unsigned char)delta); break; case 2: if (sign && (int)delta<0) { signchar = '-'; delta = -delta; } else signchar = '+'; if (sign) uprintf(do_hex?"%c%04X":"%c%05Xh", signchar,(int)delta); else uprintf(do_hex?"%04X":"%05Xh", (unsigned int)delta); break; case 4: if (sign && (long)delta<0) { delta = -delta; signchar = '-'; } else signchar = '+'; if (sign) uprintf(do_hex?"%c%08X":"%c%09lXh", signchar, (unsigned long)delta); else uprintf(do_hex?"%08X":"%09lXh", (unsigned long)delta); break; } }