2006-04-27 19:11:45 +04:00
|
|
|
/////////////////////////////////////////////////////////////////////////
|
2009-10-15 00:45:29 +04:00
|
|
|
// $Id: syntax.cc,v 1.15 2009-10-14 20:45:29 sshwarts Exp $
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Copyright (c) 2005-2009 Stanislav Shwartsman
|
|
|
|
// Written by Stanislav Shwartsman [sshwarts at sourceforge net]
|
|
|
|
//
|
|
|
|
// This library is free software; you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU Lesser General Public
|
|
|
|
// License as published by the Free Software Foundation; either
|
|
|
|
// version 2 of the License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This library is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
// Lesser General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Lesser General Public
|
|
|
|
// License along with this library; if not, write to the Free Software
|
|
|
|
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
//
|
2006-04-27 19:11:45 +04:00
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2004-12-08 21:55:13 +03:00
|
|
|
#include <stdio.h>
|
|
|
|
#include "disasm.h"
|
|
|
|
|
|
|
|
//////////////////
|
|
|
|
// Intel STYLE
|
|
|
|
//////////////////
|
|
|
|
|
2005-12-23 17:15:13 +03:00
|
|
|
#define BX_DISASM_SUPPORT_X86_64
|
|
|
|
|
|
|
|
#ifdef BX_DISASM_SUPPORT_X86_64
|
2004-12-13 01:12:43 +03:00
|
|
|
|
|
|
|
static const char *intel_general_16bit_regname[16] = {
|
|
|
|
"ax", "cx", "dx", "bx", "sp", "bp", "si", "di",
|
|
|
|
"r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w"
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *intel_general_32bit_regname[16] = {
|
|
|
|
"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi",
|
|
|
|
"r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d"
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *intel_general_64bit_regname[16] = {
|
|
|
|
"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
|
|
|
|
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *intel_general_8bit_regname_rex[16] = {
|
|
|
|
"al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil",
|
|
|
|
"r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b"
|
2004-12-08 21:55:13 +03:00
|
|
|
};
|
|
|
|
|
2004-12-13 01:12:43 +03:00
|
|
|
#else
|
|
|
|
|
|
|
|
static const char *intel_general_16bit_regname[8] = {
|
2004-12-08 21:55:13 +03:00
|
|
|
"ax", "cx", "dx", "bx", "sp", "bp", "si", "di"
|
|
|
|
};
|
|
|
|
|
2004-12-13 01:12:43 +03:00
|
|
|
static const char *intel_general_32bit_regname[8] = {
|
2004-12-08 21:55:13 +03:00
|
|
|
"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
|
|
|
|
};
|
|
|
|
|
2004-12-13 01:12:43 +03:00
|
|
|
#endif
|
|
|
|
|
|
|
|
static const char *intel_general_8bit_regname[8] = {
|
|
|
|
"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"
|
|
|
|
};
|
|
|
|
|
2004-12-08 21:55:13 +03:00
|
|
|
static const char *intel_segment_name[8] = {
|
|
|
|
"es", "cs", "ss", "ds", "fs", "gs", "??", "??"
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *intel_index16[8] = {
|
2008-02-06 01:33:35 +03:00
|
|
|
"bx+si",
|
|
|
|
"bx+di",
|
|
|
|
"bp+si",
|
|
|
|
"bp+di",
|
|
|
|
"si",
|
|
|
|
"di",
|
|
|
|
"bp",
|
2004-12-08 21:55:13 +03:00
|
|
|
"bx"
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////
|
|
|
|
// AT&T STYLE
|
|
|
|
//////////////////
|
|
|
|
|
2005-12-23 17:15:13 +03:00
|
|
|
#ifdef BX_DISASM_SUPPORT_X86_64
|
2004-12-13 01:12:43 +03:00
|
|
|
|
|
|
|
static const char *att_general_16bit_regname[16] = {
|
|
|
|
"%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di",
|
|
|
|
"%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w"
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *att_general_32bit_regname[16] = {
|
|
|
|
"%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi",
|
|
|
|
"%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d"
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *att_general_64bit_regname[16] = {
|
|
|
|
"%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
|
|
|
|
"%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *att_general_8bit_regname_rex[16] = {
|
|
|
|
"%al", "%cl", "%dl", "%bl", "%spl", "%bpl", "%sil", "%dil",
|
|
|
|
"%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b"
|
2004-12-08 21:55:13 +03:00
|
|
|
};
|
|
|
|
|
2004-12-13 01:12:43 +03:00
|
|
|
#else
|
|
|
|
|
|
|
|
static const char *att_general_16bit_regname[8] = {
|
2004-12-08 21:55:13 +03:00
|
|
|
"%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di"
|
|
|
|
};
|
|
|
|
|
2004-12-13 01:12:43 +03:00
|
|
|
static const char *att_general_32bit_regname[8] = {
|
2004-12-08 21:55:13 +03:00
|
|
|
"%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi"
|
|
|
|
};
|
|
|
|
|
2004-12-13 01:12:43 +03:00
|
|
|
#endif
|
|
|
|
|
|
|
|
static const char *att_general_8bit_regname[8] = {
|
|
|
|
"%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh"
|
|
|
|
};
|
|
|
|
|
2004-12-08 21:55:13 +03:00
|
|
|
static const char *att_segment_name[8] = {
|
2004-12-13 01:12:43 +03:00
|
|
|
"%es", "%cs", "%ss", "%ds", "%fs", "%gs", "%??", "%??"
|
2004-12-08 21:55:13 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
static const char *att_index16[8] = {
|
2008-03-20 21:11:57 +03:00
|
|
|
"%bx,%si",
|
|
|
|
"%bx,%di",
|
|
|
|
"%bp,%si",
|
|
|
|
"%bp,%di",
|
2008-02-06 01:33:35 +03:00
|
|
|
"%si",
|
|
|
|
"%di",
|
|
|
|
"%bp",
|
2004-12-08 21:55:13 +03:00
|
|
|
"%bx"
|
|
|
|
};
|
|
|
|
|
|
|
|
#define NULL_SEGMENT_REGISTER 7
|
|
|
|
|
|
|
|
void disassembler::initialize_modrm_segregs()
|
|
|
|
{
|
|
|
|
sreg_mod00_rm16[0] = segment_name[DS_REG];
|
|
|
|
sreg_mod00_rm16[1] = segment_name[DS_REG];
|
|
|
|
sreg_mod00_rm16[2] = segment_name[SS_REG];
|
|
|
|
sreg_mod00_rm16[3] = segment_name[SS_REG];
|
|
|
|
sreg_mod00_rm16[4] = segment_name[DS_REG];
|
|
|
|
sreg_mod00_rm16[5] = segment_name[DS_REG];
|
|
|
|
sreg_mod00_rm16[6] = segment_name[DS_REG];
|
|
|
|
sreg_mod00_rm16[7] = segment_name[DS_REG];
|
|
|
|
|
|
|
|
sreg_mod01or10_rm16[0] = segment_name[DS_REG];
|
|
|
|
sreg_mod01or10_rm16[1] = segment_name[DS_REG];
|
|
|
|
sreg_mod01or10_rm16[2] = segment_name[SS_REG];
|
|
|
|
sreg_mod01or10_rm16[3] = segment_name[SS_REG];
|
|
|
|
sreg_mod01or10_rm16[4] = segment_name[DS_REG];
|
|
|
|
sreg_mod01or10_rm16[5] = segment_name[DS_REG];
|
|
|
|
sreg_mod01or10_rm16[6] = segment_name[SS_REG];
|
|
|
|
sreg_mod01or10_rm16[7] = segment_name[DS_REG];
|
|
|
|
|
2007-11-19 00:29:17 +03:00
|
|
|
sreg_mod01or10_rm32[0] = segment_name[DS_REG];
|
|
|
|
sreg_mod01or10_rm32[1] = segment_name[DS_REG];
|
|
|
|
sreg_mod01or10_rm32[2] = segment_name[DS_REG];
|
|
|
|
sreg_mod01or10_rm32[3] = segment_name[DS_REG];
|
|
|
|
sreg_mod01or10_rm32[4] = segment_name[NULL_SEGMENT_REGISTER];
|
|
|
|
sreg_mod01or10_rm32[5] = segment_name[SS_REG];
|
|
|
|
sreg_mod01or10_rm32[6] = segment_name[DS_REG];
|
|
|
|
sreg_mod01or10_rm32[7] = segment_name[DS_REG];
|
|
|
|
sreg_mod01or10_rm32[8] = segment_name[DS_REG];
|
|
|
|
sreg_mod01or10_rm32[9] = segment_name[DS_REG];
|
|
|
|
sreg_mod01or10_rm32[10] = segment_name[DS_REG];
|
|
|
|
sreg_mod01or10_rm32[11] = segment_name[DS_REG];
|
|
|
|
sreg_mod01or10_rm32[12] = segment_name[NULL_SEGMENT_REGISTER];
|
|
|
|
sreg_mod01or10_rm32[13] = segment_name[DS_REG];
|
|
|
|
sreg_mod01or10_rm32[14] = segment_name[DS_REG];
|
|
|
|
sreg_mod01or10_rm32[15] = segment_name[DS_REG];
|
|
|
|
|
|
|
|
sreg_mod00_base32[0] = segment_name[DS_REG];
|
|
|
|
sreg_mod00_base32[1] = segment_name[DS_REG];
|
|
|
|
sreg_mod00_base32[2] = segment_name[DS_REG];
|
|
|
|
sreg_mod00_base32[3] = segment_name[DS_REG];
|
|
|
|
sreg_mod00_base32[4] = segment_name[SS_REG];
|
|
|
|
sreg_mod00_base32[5] = segment_name[DS_REG];
|
|
|
|
sreg_mod00_base32[6] = segment_name[DS_REG];
|
|
|
|
sreg_mod00_base32[7] = segment_name[DS_REG];
|
|
|
|
sreg_mod00_base32[8] = segment_name[DS_REG];
|
|
|
|
sreg_mod00_base32[9] = segment_name[DS_REG];
|
|
|
|
sreg_mod00_base32[10] = segment_name[DS_REG];
|
|
|
|
sreg_mod00_base32[11] = segment_name[DS_REG];
|
|
|
|
sreg_mod00_base32[12] = segment_name[DS_REG];
|
|
|
|
sreg_mod00_base32[13] = segment_name[DS_REG];
|
|
|
|
sreg_mod00_base32[14] = segment_name[DS_REG];
|
|
|
|
sreg_mod00_base32[15] = segment_name[DS_REG];
|
|
|
|
|
|
|
|
sreg_mod01or10_base32[0] = segment_name[DS_REG];
|
|
|
|
sreg_mod01or10_base32[1] = segment_name[DS_REG];
|
|
|
|
sreg_mod01or10_base32[2] = segment_name[DS_REG];
|
|
|
|
sreg_mod01or10_base32[3] = segment_name[DS_REG];
|
|
|
|
sreg_mod01or10_base32[4] = segment_name[SS_REG];
|
|
|
|
sreg_mod01or10_base32[5] = segment_name[SS_REG];
|
|
|
|
sreg_mod01or10_base32[6] = segment_name[DS_REG];
|
|
|
|
sreg_mod01or10_base32[7] = segment_name[DS_REG];
|
|
|
|
sreg_mod01or10_base32[8] = segment_name[DS_REG];
|
|
|
|
sreg_mod01or10_base32[9] = segment_name[DS_REG];
|
|
|
|
sreg_mod01or10_base32[10] = segment_name[DS_REG];
|
|
|
|
sreg_mod01or10_base32[11] = segment_name[DS_REG];
|
|
|
|
sreg_mod01or10_base32[12] = segment_name[DS_REG];
|
|
|
|
sreg_mod01or10_base32[13] = segment_name[DS_REG];
|
|
|
|
sreg_mod01or10_base32[14] = segment_name[DS_REG];
|
|
|
|
sreg_mod01or10_base32[15] = segment_name[DS_REG];
|
2004-12-08 21:55:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////
|
|
|
|
// Intel STYLE
|
|
|
|
//////////////////
|
|
|
|
|
|
|
|
void disassembler::set_syntax_intel()
|
|
|
|
{
|
|
|
|
intel_mode = 1;
|
|
|
|
|
2004-12-13 01:12:43 +03:00
|
|
|
general_16bit_regname = intel_general_16bit_regname;
|
|
|
|
general_8bit_regname = intel_general_8bit_regname;
|
|
|
|
general_32bit_regname = intel_general_32bit_regname;
|
|
|
|
general_8bit_regname_rex = intel_general_8bit_regname_rex;
|
|
|
|
general_64bit_regname = intel_general_64bit_regname;
|
2004-12-08 21:55:13 +03:00
|
|
|
|
|
|
|
segment_name = intel_segment_name;
|
|
|
|
index16 = intel_index16;
|
|
|
|
|
|
|
|
initialize_modrm_segregs();
|
|
|
|
}
|
|
|
|
|
2005-12-23 17:15:13 +03:00
|
|
|
void disassembler::print_disassembly_intel(const x86_insn *insn, const BxDisasmOpcodeInfo_t *entry)
|
2004-12-10 17:04:57 +03:00
|
|
|
{
|
|
|
|
// print opcode
|
2005-12-23 17:15:13 +03:00
|
|
|
dis_sprintf("%s ", entry->IntelOpcode);
|
2004-12-10 17:04:57 +03:00
|
|
|
|
|
|
|
if (entry->Operand1) {
|
2005-12-23 17:15:13 +03:00
|
|
|
(this->*entry->Operand1)(insn);
|
2004-12-10 17:04:57 +03:00
|
|
|
}
|
|
|
|
if (entry->Operand2) {
|
|
|
|
dis_sprintf(", ");
|
2005-12-23 17:15:13 +03:00
|
|
|
(this->*entry->Operand2)(insn);
|
2004-12-10 17:04:57 +03:00
|
|
|
}
|
|
|
|
if (entry->Operand3) {
|
|
|
|
dis_sprintf(", ");
|
2005-12-23 17:15:13 +03:00
|
|
|
(this->*entry->Operand3)(insn);
|
2004-12-10 17:04:57 +03:00
|
|
|
}
|
2007-10-10 00:24:42 +04:00
|
|
|
if (entry->Operand4) {
|
|
|
|
dis_sprintf(", ");
|
|
|
|
(this->*entry->Operand4)(insn);
|
|
|
|
}
|
2004-12-10 17:04:57 +03:00
|
|
|
}
|
|
|
|
|
2004-12-08 21:55:13 +03:00
|
|
|
//////////////////
|
|
|
|
// AT&T STYLE
|
|
|
|
//////////////////
|
2008-02-06 01:33:35 +03:00
|
|
|
|
2004-12-08 21:55:13 +03:00
|
|
|
void disassembler::set_syntax_att()
|
|
|
|
{
|
|
|
|
intel_mode = 0;
|
|
|
|
|
2004-12-13 01:12:43 +03:00
|
|
|
general_16bit_regname = att_general_16bit_regname;
|
|
|
|
general_8bit_regname = att_general_8bit_regname;
|
|
|
|
general_32bit_regname = att_general_32bit_regname;
|
|
|
|
general_8bit_regname_rex = att_general_8bit_regname_rex;
|
|
|
|
general_64bit_regname = att_general_64bit_regname;
|
2004-12-08 21:55:13 +03:00
|
|
|
|
|
|
|
segment_name = att_segment_name;
|
|
|
|
index16 = att_index16;
|
|
|
|
|
|
|
|
initialize_modrm_segregs();
|
|
|
|
}
|
2004-12-10 17:04:57 +03:00
|
|
|
|
2006-01-25 00:34:39 +03:00
|
|
|
void disassembler::toggle_syntax_mode()
|
|
|
|
{
|
|
|
|
if (intel_mode) set_syntax_att();
|
|
|
|
else set_syntax_intel();
|
|
|
|
}
|
|
|
|
|
2005-12-23 17:15:13 +03:00
|
|
|
void disassembler::print_disassembly_att(const x86_insn *insn, const BxDisasmOpcodeInfo_t *entry)
|
2004-12-10 17:04:57 +03:00
|
|
|
{
|
|
|
|
// print opcode
|
2005-12-23 17:15:13 +03:00
|
|
|
dis_sprintf("%s ", entry->AttOpcode);
|
2004-12-10 17:04:57 +03:00
|
|
|
|
2008-02-06 01:33:35 +03:00
|
|
|
if (entry->Operand4) {
|
2007-10-10 00:24:42 +04:00
|
|
|
(this->*entry->Operand4)(insn);
|
|
|
|
dis_sprintf(", ");
|
|
|
|
}
|
2008-02-06 01:33:35 +03:00
|
|
|
if (entry->Operand3) {
|
2005-12-23 17:15:13 +03:00
|
|
|
(this->*entry->Operand3)(insn);
|
2004-12-10 17:04:57 +03:00
|
|
|
dis_sprintf(", ");
|
|
|
|
}
|
|
|
|
if (entry->Operand2) {
|
2005-12-23 17:15:13 +03:00
|
|
|
(this->*entry->Operand2)(insn);
|
2004-12-10 17:04:57 +03:00
|
|
|
dis_sprintf(", ");
|
|
|
|
}
|
|
|
|
if (entry->Operand1) {
|
2005-12-23 17:15:13 +03:00
|
|
|
(this->*entry->Operand1)(insn);
|
2004-12-10 17:04:57 +03:00
|
|
|
}
|
|
|
|
}
|