Added experimental support of AT&T syntax to disasm
Fixed operand for CMPXCHG8B instruction Feature request to somebidy who understand Bochs debugger code - to add Bochs debugger command which will switch between Intel and AT&T style for disassembler.
This commit is contained in:
parent
a0efe5e577
commit
8ac3790ab3
@ -60,7 +60,12 @@ Changes to next release:
|
||||
- fixed sign-extended immediate opcodes (Stanislav)
|
||||
- fixed MOVSS/MOVSD instructions opcode names (Stanislav)
|
||||
- fixed NEG instruction opcode name (Stanislav)
|
||||
- fixed floating point instructions arguments (Stanislav)
|
||||
- fixed CMPXCHG8B instruction, had wrong operand size (Stanislav)
|
||||
- fixed floating point instructions operands (Stanislav)
|
||||
- experimental support of AT&T syntax in disassembler (Stanislav)
|
||||
|
||||
TODO:
|
||||
- disassmbler X86-64 support
|
||||
|
||||
- I/O devices
|
||||
- general
|
||||
|
@ -141,7 +141,7 @@ unsigned disassembler::disasm(bx_bool is_32,
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Internal disassembler error !");
|
||||
printf("Internal disassembler error !\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -162,8 +162,6 @@ unsigned disassembler::disasm(bx_bool is_32,
|
||||
int attr = entry->Attr;
|
||||
while(attr)
|
||||
{
|
||||
if (attr == _COND_JUMP) break;
|
||||
|
||||
switch(attr) {
|
||||
case _GROUPN:
|
||||
entry = &(entry->AnotherArray[nnn]);
|
||||
@ -199,7 +197,7 @@ unsigned disassembler::disasm(bx_bool is_32,
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Internal disassembler error !");
|
||||
printf("Internal disassembler error !\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -210,45 +208,23 @@ unsigned disassembler::disasm(bx_bool is_32,
|
||||
// print prefixes
|
||||
for(unsigned i=0;i<n_prefixes;i++)
|
||||
{
|
||||
if (*(instr+i) == 0xF3 || *(instr+i) == 0xF2 || *(instr+i) == 0xF0)
|
||||
dis_sprintf("%s ", BxDisasmOpcodes[*(instr+i)].Opcode);
|
||||
if (*(instr+i) == 0xF3 || *(instr+i) == 0xF2 || *(instr+i) == 0xF0)
|
||||
dis_sprintf("%s ", BxDisasmOpcodes[*(instr+i)].Opcode);
|
||||
|
||||
if (attr == _COND_JUMP)
|
||||
{
|
||||
if (*(instr+i) == 0x2E)
|
||||
dis_sprintf("not taken ");
|
||||
if (*(instr+i) == 0x3E)
|
||||
dis_sprintf("taken ");
|
||||
}
|
||||
if (entry->Op3Attr == BRANCH_HINT)
|
||||
{
|
||||
if (*(instr+i) == 0x2E)
|
||||
dis_sprintf("not taken ");
|
||||
if (*(instr+i) == 0x3E)
|
||||
dis_sprintf("taken ");
|
||||
}
|
||||
}
|
||||
|
||||
// print opcode
|
||||
dis_sprintf("%s ", entry->Opcode);
|
||||
|
||||
// print instruction disassembly
|
||||
if (intel_mode)
|
||||
{
|
||||
(this->*entry->Operand1)(entry->Op1Attr);
|
||||
if (entry->Operand2 != &disassembler::XX) {
|
||||
dis_sprintf(", ");
|
||||
(this->*entry->Operand2)(entry->Op2Attr);
|
||||
}
|
||||
if (entry->Operand3 != &disassembler::XX) {
|
||||
dis_sprintf(", ");
|
||||
(this->*entry->Operand3)(entry->Op3Attr);
|
||||
}
|
||||
}
|
||||
print_disassembly_intel(entry);
|
||||
else
|
||||
{
|
||||
if (entry->Operand3 != &disassembler::XX) {
|
||||
(this->*entry->Operand3)(entry->Op3Attr);
|
||||
dis_sprintf(", ");
|
||||
}
|
||||
if (entry->Operand2 != &disassembler::XX) {
|
||||
(this->*entry->Operand2)(entry->Op2Attr);
|
||||
dis_sprintf(", ");
|
||||
}
|
||||
(this->*entry->Operand1)(entry->Op1Attr);
|
||||
}
|
||||
print_disassembly_att (entry);
|
||||
|
||||
return(instruction - instruction_begin);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -80,6 +80,17 @@ enum {
|
||||
eDI_REG
|
||||
};
|
||||
|
||||
enum {
|
||||
rAX_REG,
|
||||
rCX_REG,
|
||||
rDX_REG,
|
||||
rBX_REG,
|
||||
rSP_REG,
|
||||
rBP_REG,
|
||||
rSI_REG,
|
||||
rDI_REG
|
||||
};
|
||||
|
||||
enum {
|
||||
ES_REG,
|
||||
CS_REG,
|
||||
@ -89,30 +100,46 @@ enum {
|
||||
GS_REG
|
||||
};
|
||||
|
||||
// datasize attributes
|
||||
#define X_SIZE 0x0000
|
||||
#define B_SIZE 0x0100
|
||||
#define W_SIZE 0x0200
|
||||
#define D_SIZE 0x0300
|
||||
#define V_SIZE 0x0400
|
||||
#define Q_SIZE 0x0500
|
||||
#define O_SIZE 0x0600
|
||||
#define T_SIZE 0x0700
|
||||
#define P_SIZE 0x0800
|
||||
#define S_SIZE 0x0900
|
||||
|
||||
class disassembler;
|
||||
|
||||
typedef void (disassembler::*BxDisasmPtr_t) (unsigned attr);
|
||||
typedef void (disassembler::*BxDisasmResolveModrmPtr_t) (unsigned attr);
|
||||
|
||||
struct BxDisasmOpcodeInfo_t
|
||||
{
|
||||
const char *Opcode;
|
||||
unsigned Attr;
|
||||
BxDisasmPtr_t Operand1;
|
||||
unsigned Op1Attr;
|
||||
BxDisasmPtr_t Operand2;
|
||||
unsigned Op2Attr;
|
||||
BxDisasmPtr_t Operand3;
|
||||
unsigned Op3Attr;
|
||||
struct BxDisasmOpcodeInfo_t *AnotherArray;
|
||||
};
|
||||
|
||||
// datasize attributes
|
||||
#define X_SIZE 0x0000
|
||||
#define B_SIZE 0x0100
|
||||
#define W_SIZE 0x0200
|
||||
#define D_SIZE 0x0300
|
||||
#define V_SIZE 0x0400
|
||||
#define Q_SIZE 0x0500
|
||||
#define O_SIZE 0x0600
|
||||
#define T_SIZE 0x0700
|
||||
#define P_SIZE 0x0800
|
||||
#define S_SIZE 0x0900
|
||||
|
||||
// branch hint attribute
|
||||
#define BRANCH_HINT 0x1000
|
||||
|
||||
class disassembler {
|
||||
public:
|
||||
disassembler() { set_syntax_intel(); }
|
||||
unsigned disasm(bx_bool is_32, Bit32u base, Bit32u ip, Bit8u *instr, char *disbuf);
|
||||
|
||||
void set_syntax_att();
|
||||
void set_syntax_intel();
|
||||
void set_syntax_att ();
|
||||
|
||||
private:
|
||||
bx_bool intel_mode;
|
||||
@ -209,6 +236,9 @@ private:
|
||||
void print_memory_access32(int datasize,
|
||||
const char *seg, const char *base, const char *index, int scale, Bit32u disp);
|
||||
|
||||
void print_disassembly_intel(const BxDisasmOpcodeInfo_t *entry);
|
||||
void print_disassembly_att (const BxDisasmOpcodeInfo_t *entry);
|
||||
|
||||
public:
|
||||
|
||||
/*
|
||||
@ -279,8 +309,6 @@ public:
|
||||
* if the effective operand size is 32 or 64 bits.
|
||||
*/
|
||||
|
||||
void XX (unsigned attribute) {}
|
||||
|
||||
// fpu
|
||||
void ST0 (unsigned attribute);
|
||||
void STj (unsigned attribute);
|
||||
|
@ -142,6 +142,54 @@ void disassembler::set_syntax_intel()
|
||||
initialize_modrm_segregs();
|
||||
}
|
||||
|
||||
void disassembler::print_disassembly_intel(const BxDisasmOpcodeInfo_t *entry)
|
||||
{
|
||||
// print opcode
|
||||
dis_sprintf("%s", entry->Opcode);
|
||||
|
||||
// patch opcode
|
||||
disbufptr --;
|
||||
|
||||
switch(*disbufptr) {
|
||||
case 'B':
|
||||
case 'W':
|
||||
case 'V':
|
||||
case 'L':
|
||||
case 'Q':
|
||||
case 'T':
|
||||
break;
|
||||
|
||||
case 'X': // movsx or movzx
|
||||
dis_sprintf("x");
|
||||
break;
|
||||
|
||||
case 'O': // string
|
||||
if (i32bit_opsize)
|
||||
dis_sprintf("d");
|
||||
else
|
||||
dis_sprintf("w");
|
||||
break;
|
||||
|
||||
default:
|
||||
disbufptr ++;
|
||||
break;
|
||||
}
|
||||
|
||||
dis_sprintf(" ");
|
||||
|
||||
if (entry->Operand1) {
|
||||
(this->*entry->Operand1)(entry->Op1Attr);
|
||||
}
|
||||
if (entry->Operand2) {
|
||||
dis_sprintf(", ");
|
||||
(this->*entry->Operand2)(entry->Op2Attr);
|
||||
}
|
||||
if (entry->Operand3) {
|
||||
dis_sprintf(", ");
|
||||
(this->*entry->Operand3)(entry->Op3Attr);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////
|
||||
// AT&T STYLE
|
||||
//////////////////
|
||||
@ -161,3 +209,93 @@ void disassembler::set_syntax_att()
|
||||
|
||||
initialize_modrm_segregs();
|
||||
}
|
||||
|
||||
void disassembler::print_disassembly_att(const BxDisasmOpcodeInfo_t *entry)
|
||||
{
|
||||
// print opcode
|
||||
dis_sprintf("%s", entry->Opcode);
|
||||
|
||||
// patch opcode
|
||||
disbufptr --;
|
||||
|
||||
switch(*disbufptr) {
|
||||
case 'B':
|
||||
dis_sprintf("b");
|
||||
break;
|
||||
|
||||
case 'W':
|
||||
dis_sprintf("w");
|
||||
break;
|
||||
|
||||
case 'O':
|
||||
if (i32bit_opsize)
|
||||
dis_sprintf("d");
|
||||
else
|
||||
dis_sprintf("w");
|
||||
break;
|
||||
|
||||
case 'V':
|
||||
if (i32bit_opsize)
|
||||
dis_sprintf("l");
|
||||
else
|
||||
dis_sprintf("w");
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
dis_sprintf("l");
|
||||
break;
|
||||
|
||||
case 'Q':
|
||||
dis_sprintf("q");
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
dis_sprintf("t");
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
if (entry->Op2Attr == B_SIZE)
|
||||
dis_sprintf("b");
|
||||
else if (entry->Op2Attr == W_SIZE)
|
||||
dis_sprintf("w");
|
||||
else if (entry->Op2Attr == D_SIZE)
|
||||
dis_sprintf("l");
|
||||
else
|
||||
printf("Internal disassembler error !\n");
|
||||
|
||||
if (entry->Op1Attr == W_SIZE)
|
||||
dis_sprintf("w");
|
||||
else if (entry->Op1Attr == D_SIZE)
|
||||
dis_sprintf("l");
|
||||
else if (entry->Op1Attr == Q_SIZE)
|
||||
dis_sprintf("q");
|
||||
else if (entry->Op1Attr == V_SIZE)
|
||||
{
|
||||
if (i32bit_opsize)
|
||||
dis_sprintf("l");
|
||||
else
|
||||
dis_sprintf("w");
|
||||
}
|
||||
else
|
||||
printf("Internal disassembler error !\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
disbufptr ++;
|
||||
break;
|
||||
}
|
||||
|
||||
dis_sprintf(" ");
|
||||
|
||||
if (entry->Operand3) {
|
||||
(this->*entry->Operand3)(entry->Op3Attr);
|
||||
dis_sprintf(", ");
|
||||
}
|
||||
if (entry->Operand2) {
|
||||
(this->*entry->Operand2)(entry->Op2Attr);
|
||||
dis_sprintf(", ");
|
||||
}
|
||||
if (entry->Operand1) {
|
||||
(this->*entry->Operand1)(entry->Op1Attr);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user