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:
Stanislav Shwartsman 2004-12-10 14:04:57 +00:00
parent a0efe5e577
commit 8ac3790ab3
5 changed files with 624 additions and 473 deletions

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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);
}
}