summaryrefslogtreecommitdiff
path: root/src/arch/x86
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2008-08-03 15:35:43 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2008-08-03 15:35:43 (GMT)
commit1249cf6e2c0ed87e1c593e488beedbbfe153ff00 (patch)
tree0a92b85df9dabe76b34810071e0c1def906311da /src/arch/x86
parentf0b80c6ab55ede4f8ab8ede757f1f8951512affa (diff)
Read registers from the ModR/M encoding.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@13 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/arch/x86')
-rw-r--r--src/arch/x86/Makefile.am7
-rw-r--r--src/arch/x86/instruction.h149
-rw-r--r--src/arch/x86/op_adc.c98
-rw-r--r--src/arch/x86/op_add.c98
-rw-r--r--src/arch/x86/op_and.c98
-rw-r--r--src/arch/x86/op_mov.c67
-rw-r--r--src/arch/x86/op_or.c98
-rw-r--r--src/arch/x86/op_sbb.c98
-rw-r--r--src/arch/x86/op_sub.c98
-rw-r--r--src/arch/x86/op_xor.c165
-rw-r--r--src/arch/x86/opcodes.h27
-rw-r--r--src/arch/x86/operand.c59
-rw-r--r--src/arch/x86/operand.h3
-rw-r--r--src/arch/x86/processor.c223
14 files changed, 1085 insertions, 203 deletions
diff --git a/src/arch/x86/Makefile.am b/src/arch/x86/Makefile.am
index 0a32def..aba9e5b 100644
--- a/src/arch/x86/Makefile.am
+++ b/src/arch/x86/Makefile.am
@@ -3,6 +3,9 @@ lib_LIBRARIES = libarchx86.a
libarchx86_a_SOURCES = \
instruction.h \
+ op_adc.c \
+ op_add.c \
+ op_and.c \
op_call.c \
op_dec.c \
op_hlt.c \
@@ -11,9 +14,13 @@ libarchx86_a_SOURCES = \
op_leave.c \
op_nop.c \
op_mov.c \
+ op_or.c \
op_pop.c \
op_push.c \
op_ret.c \
+ op_sbb.c \
+ op_sub.c \
+ op_xor.c \
opcodes.h \
operand.h operand.c \
processor.h processor.c
diff --git a/src/arch/x86/instruction.h b/src/arch/x86/instruction.h
index af1c5bc..9f89a9e 100644
--- a/src/arch/x86/instruction.h
+++ b/src/arch/x86/instruction.h
@@ -38,54 +38,66 @@ typedef struct _asm_x86_instr asm_x86_instr;
/* Enumération de tous les opcodes */
typedef enum _X86Opcodes
{
- X86_OP_INC_EAX, /* inc (0x40) */
- X86_OP_INC_ECX, /* inc (0x41) */
- X86_OP_INC_EDX, /* inc (0x42) */
- X86_OP_INC_EBX, /* inc (0x43) */
- X86_OP_INC_ESP, /* inc (0x44) */
- X86_OP_INC_EBP, /* inc (0x45) */
- X86_OP_INC_ESI, /* inc (0x46) */
- X86_OP_INC_EDI, /* inc (0x47) */
-
- X86_OP_DEC_EAX, /* dec (0x48) */
- X86_OP_DEC_ECX, /* dec (0x49) */
- X86_OP_DEC_EDX, /* dec (0x4a) */
- X86_OP_DEC_EBX, /* dec (0x4b) */
- X86_OP_DEC_ESP, /* dec (0x4c) */
- X86_OP_DEC_EBP, /* dec (0x4d) */
- X86_OP_DEC_ESI, /* dec (0x4e) */
- X86_OP_DEC_EDI, /* dec (0x4f) */
-
- X86_OP_PUSH_EAX, /* push (0x50) */
- X86_OP_PUSH_ECX, /* push (0x51) */
- X86_OP_PUSH_EDX, /* push (0x52) */
- X86_OP_PUSH_EBX, /* push (0x53) */
- X86_OP_PUSH_ESP, /* push (0x54) */
- X86_OP_PUSH_EBP, /* push (0x55) */
- X86_OP_PUSH_ESI, /* push (0x56) */
- X86_OP_PUSH_EDI, /* push (0x57) */
-
- X86_OP_POP_EAX, /* pop (0x58) */
- X86_OP_POP_ECX, /* pop (0x59) */
- X86_OP_POP_EDX, /* pop (0x5a) */
- X86_OP_POP_EBX, /* pop (0x5b) */
- X86_OP_POP_ESP, /* pop (0x5c) */
- X86_OP_POP_EBP, /* pop (0x5d) */
- X86_OP_POP_ESI, /* pop (0x5e) */
- X86_OP_POP_EDI, /* pop (0x5f) */
-
- X86_OP_PUSH_IMM32, /* push (0x68) */
+ X86_OP_XOR_REG1632, /* xor ([0x66] 0x31) */
+
+ X86_OP_INC_E_AX, /* inc ([0x66] 0x40) */
+ X86_OP_INC_E_CX, /* inc ([0x66] 0x41) */
+ X86_OP_INC_E_DX, /* inc ([0x66] 0x42) */
+ X86_OP_INC_E_BX, /* inc ([0x66] 0x43) */
+ X86_OP_INC_E_SP, /* inc ([0x66] 0x44) */
+ X86_OP_INC_E_BP, /* inc ([0x66] 0x45) */
+ X86_OP_INC_E_SI, /* inc ([0x66] 0x46) */
+ X86_OP_INC_E_DI, /* inc ([0x66] 0x47) */
+
+ X86_OP_DEC_E_AX, /* dec ([0x66] 0x48) */
+ X86_OP_DEC_E_CX, /* dec ([0x66] 0x49) */
+ X86_OP_DEC_E_DX, /* dec ([0x66] 0x4a) */
+ X86_OP_DEC_E_BX, /* dec ([0x66] 0x4b) */
+ X86_OP_DEC_E_SP, /* dec ([0x66] 0x4c) */
+ X86_OP_DEC_E_BP, /* dec ([0x66] 0x4d) */
+ X86_OP_DEC_E_SI, /* dec ([0x66] 0x4e) */
+ X86_OP_DEC_E_DI, /* dec ([0x66] 0x4f) */
+
+ X86_OP_PUSH_E_AX, /* push ([0x66] 0x50) */
+ X86_OP_PUSH_E_CX, /* push ([0x66] 0x51) */
+ X86_OP_PUSH_E_DX, /* push ([0x66] 0x52) */
+ X86_OP_PUSH_E_BX, /* push ([0x66] 0x53) */
+ X86_OP_PUSH_E_SP, /* push ([0x66] 0x54) */
+ X86_OP_PUSH_E_BP, /* push ([0x66] 0x55) */
+ X86_OP_PUSH_E_SI, /* push ([0x66] 0x56) */
+ X86_OP_PUSH_E_DI, /* push ([0x66] 0x57) */
+
+ X86_OP_POP_E_AX, /* pop ([0x66] 0x58) */
+ X86_OP_POP_E_CX, /* pop ([0x66] 0x59) */
+ X86_OP_POP_E_DX, /* pop ([0x66] 0x5a) */
+ X86_OP_POP_E_BX, /* pop ([0x66] 0x5b) */
+ X86_OP_POP_E_SP, /* pop ([0x66] 0x5c) */
+ X86_OP_POP_E_BP, /* pop ([0x66] 0x5d) */
+ X86_OP_POP_E_SI, /* pop ([0x66] 0x5e) */
+ X86_OP_POP_E_DI, /* pop ([0x66] 0x5f) */
+
+ X86_OP_PUSH_IMM1632, /* push ([0x66] 0x68) */
+
+ X86_OP_MOV_REG1632, /* mov ([0x66] 0x89) */
+
+ X86_OP_ADD8_REG1632, /* add ([0x66] 0x83) */
+ X86_OP_OR8_REG1632, /* or ([0x66] 0x83) */
+ X86_OP_ADC8_REG1632, /* adc ([0x66] 0x83) */
+ X86_OP_SBB8_REG1632, /* sbb ([0x66] 0x83) */
+ X86_OP_AND8_REG1632, /* and ([0x66] 0x83) */
+ X86_OP_SUB8_REG1632, /* sub ([0x66] 0x83) */
+ X86_OP_XOR8_REG1632, /* xor ([0x66] 0x83) */
X86_OP_NOP, /* nop (0x90) */
- X86_OP_MOV_AX, /* mov (0xb8) */
- X86_OP_MOV_CX, /* mov (0xb9) */
- X86_OP_MOV_DX, /* mov (0xba) */
- X86_OP_MOV_BX, /* mov (0xbb) */
- X86_OP_MOV_SP, /* mov (0xbc) */
- X86_OP_MOV_BP, /* mov (0xbd) */
- X86_OP_MOV_SI, /* mov (0xbe) */
- X86_OP_MOV_DI, /* mov (0xbf) */
+ X86_OP_MOV_E_AX, /* mov ([0x66] 0xb8) */
+ X86_OP_MOV_E_CX, /* mov ([0x66] 0xb9) */
+ X86_OP_MOV_E_DX, /* mov ([0x66] 0xba) */
+ X86_OP_MOV_E_BX, /* mov ([0x66] 0xbb) */
+ X86_OP_MOV_E_SP, /* mov ([0x66] 0xbc) */
+ X86_OP_MOV_E_BP, /* mov ([0x66] 0xbd) */
+ X86_OP_MOV_E_SI, /* mov ([0x66] 0xbe) */
+ X86_OP_MOV_E_DI, /* mov ([0x66] 0xbf) */
X86_OP_RET, /* ret (0xc3) */
X86_OP_LEAVE, /* leave (0xc9) */
@@ -96,53 +108,6 @@ typedef enum _X86Opcodes
X86_OP_HLT, /* hlt (0xf4) */
- X86_OP_INC_AX, /* inc (0x66 0x40) */
- X86_OP_INC_CX, /* inc (0x66 0x41) */
- X86_OP_INC_DX, /* inc (0x66 0x42) */
- X86_OP_INC_BX, /* inc (0x66 0x43) */
- X86_OP_INC_SP, /* inc (0x66 0x44) */
- X86_OP_INC_BP, /* inc (0x66 0x45) */
- X86_OP_INC_SI, /* inc (0x66 0x46) */
- X86_OP_INC_DI, /* inc (0x66 0x47) */
-
- X86_OP_DEC_AX, /* dec (0x66 0x48) */
- X86_OP_DEC_CX, /* dec (0x66 0x49) */
- X86_OP_DEC_DX, /* dec (0x66 0x4a) */
- X86_OP_DEC_BX, /* dec (0x66 0x4b) */
- X86_OP_DEC_SP, /* dec (0x66 0x4c) */
- X86_OP_DEC_BP, /* dec (0x66 0x4d) */
- X86_OP_DEC_SI, /* dec (0x66 0x4e) */
- X86_OP_DEC_DI, /* dec (0x66 0x4f) */
-
- X86_OP_PUSH_AX, /* push (0x66 0x50) */
- X86_OP_PUSH_CX, /* push (0x66 0x51) */
- X86_OP_PUSH_DX, /* push (0x66 0x52) */
- X86_OP_PUSH_BX, /* push (0x66 0x53) */
- X86_OP_PUSH_SP, /* push (0x66 0x54) */
- X86_OP_PUSH_BP, /* push (0x66 0x55) */
- X86_OP_PUSH_SI, /* push (0x66 0x56) */
- X86_OP_PUSH_DI, /* push (0x66 0x57) */
-
- X86_OP_POP_AX, /* pop (0x66 0x58) */
- X86_OP_POP_CX, /* pop (0x66 0x59) */
- X86_OP_POP_DX, /* pop (0x66 0x5a) */
- X86_OP_POP_BX, /* pop (0x66 0x5b) */
- X86_OP_POP_SP, /* pop (0x66 0x5c) */
- X86_OP_POP_BP, /* pop (0x66 0x5d) */
- X86_OP_POP_SI, /* pop (0x66 0x5e) */
- X86_OP_POP_DI, /* pop (0x66 0x5f) */
-
- X86_OP_PUSH_IMM16, /* push (0x66 0x68) */
-
- X86_OP_MOV_EAX, /* mov (0x66 0xb8) */
- X86_OP_MOV_ECX, /* mov (0x66 0xb9) */
- X86_OP_MOV_EDX, /* mov (0x66 0xba) */
- X86_OP_MOV_EBX, /* mov (0x66 0xbb) */
- X86_OP_MOV_ESP, /* mov (0x66 0xbc) */
- X86_OP_MOV_EBP, /* mov (0x66 0xbd) */
- X86_OP_MOV_ESI, /* mov (0x66 0xbe) */
- X86_OP_MOV_EDI, /* mov (0x66 0xbf) */
-
X86_OP_COUNT
} X86Opcodes;
diff --git a/src/arch/x86/op_adc.c b/src/arch/x86/op_adc.c
new file mode 100644
index 0000000..8eab0f5
--- /dev/null
+++ b/src/arch/x86/op_adc.c
@@ -0,0 +1,98 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * op_adc.c - décodage des additions avec retenue
+ *
+ * Copyright (C) 2008 Cyrille Bagard
+ *
+ * This file is part of OpenIDA.
+ *
+ * OpenIDA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * OpenIDA 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include <malloc.h>
+
+
+#include "../instruction-int.h"
+#include "opcodes.h"
+#include "operand.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : data = flux de données à analyser. *
+* pos = position courante dans ce flux. [OUT] *
+* len = taille totale des données à analyser. *
+* offset = adresse virtuelle de l'instruction. *
+* proc = architecture ciblée par le désassemblage. *
+* *
+* Description : Décode une instruction de type 'adc' (16 ou 32 bits). *
+* *
+* Retour : Instruction mise en place ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+asm_x86_instr *read_instr_adc8_with_reg1632(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc)
+{
+ asm_x86_instr *result; /* Instruction à retourner */
+ AsmOperandSize oprsize; /* Taille des opérandes */
+ asm_x86_operand *reg; /* Registre de destination */
+ asm_x86_operand *value; /* Valeur empilée */
+
+ result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr));
+
+ /* Utilisation des registres 32 bits ? */
+ if (data[*pos] == 0x66)
+ {
+ oprsize = switch_x86_operand_size(proc);
+ (*pos)++;
+ }
+ else oprsize = get_x86_current_operand_size(proc);
+
+ ASM_INSTRUCTION(result)->opcode = data[(*pos)++];
+
+ /* TODO ! */
+ if ((data[*pos] & 0xc0) != 0xc0)
+ return NULL;
+
+ reg = x86_create_reg1632_operand_from_modrm(data[*pos], oprsize == AOS_32_BITS, false);
+ if (reg == NULL)
+ {
+ free(result);
+ return NULL;
+ }
+
+ (*pos)++;
+
+ value = create_new_x86_operand();
+ if (!fill_imm_operand(ASM_OPERAND(value), AOS_8_BITS, data, pos, len))
+ {
+ free(reg);
+ free(value);
+ free(result);
+ return NULL;
+ }
+
+ ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(2, sizeof(asm_operand *));
+ ASM_INSTRUCTION(result)->operands_count = 2;
+
+ ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(reg);
+ ASM_INSTRUCTION(result)->operands[1] = ASM_OPERAND(value);
+
+ return result;
+
+}
diff --git a/src/arch/x86/op_add.c b/src/arch/x86/op_add.c
new file mode 100644
index 0000000..99a30fc
--- /dev/null
+++ b/src/arch/x86/op_add.c
@@ -0,0 +1,98 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * op_add.c - décodage des additions
+ *
+ * Copyright (C) 2008 Cyrille Bagard
+ *
+ * This file is part of OpenIDA.
+ *
+ * OpenIDA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * OpenIDA 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include <malloc.h>
+
+
+#include "../instruction-int.h"
+#include "opcodes.h"
+#include "operand.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : data = flux de données à analyser. *
+* pos = position courante dans ce flux. [OUT] *
+* len = taille totale des données à analyser. *
+* offset = adresse virtuelle de l'instruction. *
+* proc = architecture ciblée par le désassemblage. *
+* *
+* Description : Décode une instruction de type 'add' (16 ou 32 bits). *
+* *
+* Retour : Instruction mise en place ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+asm_x86_instr *read_instr_add8_with_reg1632(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc)
+{
+ asm_x86_instr *result; /* Instruction à retourner */
+ AsmOperandSize oprsize; /* Taille des opérandes */
+ asm_x86_operand *reg; /* Registre de destination */
+ asm_x86_operand *value; /* Valeur empilée */
+
+ result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr));
+
+ /* Utilisation des registres 32 bits ? */
+ if (data[*pos] == 0x66)
+ {
+ oprsize = switch_x86_operand_size(proc);
+ (*pos)++;
+ }
+ else oprsize = get_x86_current_operand_size(proc);
+
+ ASM_INSTRUCTION(result)->opcode = data[(*pos)++];
+
+ /* TODO ! */
+ if ((data[*pos] & 0xc0) != 0xc0)
+ return NULL;
+
+ reg = x86_create_reg1632_operand_from_modrm(data[*pos], oprsize == AOS_32_BITS, false);
+ if (reg == NULL)
+ {
+ free(result);
+ return NULL;
+ }
+
+ (*pos)++;
+
+ value = create_new_x86_operand();
+ if (!fill_imm_operand(ASM_OPERAND(value), AOS_8_BITS, data, pos, len))
+ {
+ free(reg);
+ free(value);
+ free(result);
+ return NULL;
+ }
+
+ ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(2, sizeof(asm_operand *));
+ ASM_INSTRUCTION(result)->operands_count = 2;
+
+ ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(reg);
+ ASM_INSTRUCTION(result)->operands[1] = ASM_OPERAND(value);
+
+ return result;
+
+}
diff --git a/src/arch/x86/op_and.c b/src/arch/x86/op_and.c
new file mode 100644
index 0000000..e220b4c
--- /dev/null
+++ b/src/arch/x86/op_and.c
@@ -0,0 +1,98 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * op_and.c - décodage des ET logiques
+ *
+ * Copyright (C) 2008 Cyrille Bagard
+ *
+ * This file is part of OpenIDA.
+ *
+ * OpenIDA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * OpenIDA 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include <malloc.h>
+
+
+#include "../instruction-int.h"
+#include "opcodes.h"
+#include "operand.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : data = flux de données à analyser. *
+* pos = position courante dans ce flux. [OUT] *
+* len = taille totale des données à analyser. *
+* offset = adresse virtuelle de l'instruction. *
+* proc = architecture ciblée par le désassemblage. *
+* *
+* Description : Décode une instruction de type 'and' (16 ou 32 bits). *
+* *
+* Retour : Instruction mise en place ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+asm_x86_instr *read_instr_and8_with_reg1632(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc)
+{
+ asm_x86_instr *result; /* Instruction à retourner */
+ AsmOperandSize oprsize; /* Taille des opérandes */
+ asm_x86_operand *reg; /* Registre de destination */
+ asm_x86_operand *value; /* Valeur empilée */
+
+ result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr));
+
+ /* Utilisation des registres 32 bits ? */
+ if (data[*pos] == 0x66)
+ {
+ oprsize = switch_x86_operand_size(proc);
+ (*pos)++;
+ }
+ else oprsize = get_x86_current_operand_size(proc);
+
+ ASM_INSTRUCTION(result)->opcode = data[(*pos)++];
+
+ /* TODO ! */
+ if ((data[*pos] & 0xc0) != 0xc0)
+ return NULL;
+
+ reg = x86_create_reg1632_operand_from_modrm(data[*pos], oprsize == AOS_32_BITS, false);
+ if (reg == NULL)
+ {
+ free(result);
+ return NULL;
+ }
+
+ (*pos)++;
+
+ value = create_new_x86_operand();
+ if (!fill_imm_operand(ASM_OPERAND(value), AOS_8_BITS, data, pos, len))
+ {
+ free(reg);
+ free(value);
+ free(result);
+ return NULL;
+ }
+
+ ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(2, sizeof(asm_operand *));
+ ASM_INSTRUCTION(result)->operands_count = 2;
+
+ ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(reg);
+ ASM_INSTRUCTION(result)->operands[1] = ASM_OPERAND(value);
+
+ return result;
+
+}
diff --git a/src/arch/x86/op_mov.c b/src/arch/x86/op_mov.c
index e14a2f7..f0a5fce 100644
--- a/src/arch/x86/op_mov.c
+++ b/src/arch/x86/op_mov.c
@@ -46,6 +46,73 @@
* *
******************************************************************************/
+asm_x86_instr *read_instr_mov_with_reg1632(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc)
+{
+ asm_x86_instr *result; /* Instruction à retourner */
+ AsmOperandSize oprsize; /* Taille des opérandes */
+ asm_x86_operand *reg2; /* Registre de source */
+ asm_x86_operand *reg1; /* Registre de destination */
+
+ result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr));
+
+ /* Utilisation des registres 32 bits ? */
+ if (data[*pos] == 0x66)
+ {
+ oprsize = switch_x86_operand_size(proc);
+ (*pos)++;
+ }
+ else oprsize = get_x86_current_operand_size(proc);
+
+ ASM_INSTRUCTION(result)->opcode = data[(*pos)++];
+
+ /* TODO ! */
+ if ((data[*pos] & 0xc0) != 0xc0)
+ return NULL;
+
+ reg1 = x86_create_reg1632_operand_from_modrm(data[*pos], oprsize == AOS_32_BITS, true);
+ if (reg1 == NULL)
+ {
+ free(result);
+ return NULL;
+ }
+
+ reg2 = x86_create_reg1632_operand_from_modrm(data[*pos], oprsize == AOS_32_BITS, false);
+ if (reg2 == NULL)
+ {
+ free(result);
+ free(reg1);
+ return NULL;
+ }
+
+ (*pos)++;
+
+ ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(2, sizeof(asm_operand *));
+ ASM_INSTRUCTION(result)->operands_count = 2;
+
+ ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(reg1);
+ ASM_INSTRUCTION(result)->operands[1] = ASM_OPERAND(reg2);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : data = flux de données à analyser. *
+* pos = position courante dans ce flux. [OUT] *
+* len = taille totale des données à analyser. *
+* offset = adresse virtuelle de l'instruction. *
+* proc = architecture ciblée par le désassemblage. *
+* *
+* Description : Décode une instruction de type 'mov' (16 ou 32 bits). *
+* *
+* Retour : Instruction mise en place ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
asm_x86_instr *read_instr_mov_to_1632(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc)
{
asm_x86_instr *result; /* Instruction à retourner */
diff --git a/src/arch/x86/op_or.c b/src/arch/x86/op_or.c
new file mode 100644
index 0000000..a092448
--- /dev/null
+++ b/src/arch/x86/op_or.c
@@ -0,0 +1,98 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * op_or.c - décodage des OU logiques
+ *
+ * Copyright (C) 2008 Cyrille Bagard
+ *
+ * This file is part of OpenIDA.
+ *
+ * OpenIDA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * OpenIDA 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include <malloc.h>
+
+
+#include "../instruction-int.h"
+#include "opcodes.h"
+#include "operand.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : data = flux de données à analyser. *
+* pos = position courante dans ce flux. [OUT] *
+* len = taille totale des données à analyser. *
+* offset = adresse virtuelle de l'instruction. *
+* proc = architecture ciblée par le désassemblage. *
+* *
+* Description : Décode une instruction de type 'or' (16 ou 32 bits). *
+* *
+* Retour : Instruction mise en place ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+asm_x86_instr *read_instr_or8_with_reg1632(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc)
+{
+ asm_x86_instr *result; /* Instruction à retourner */
+ AsmOperandSize oprsize; /* Taille des opérandes */
+ asm_x86_operand *reg; /* Registre de destination */
+ asm_x86_operand *value; /* Valeur empilée */
+
+ result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr));
+
+ /* Utilisation des registres 32 bits ? */
+ if (data[*pos] == 0x66)
+ {
+ oprsize = switch_x86_operand_size(proc);
+ (*pos)++;
+ }
+ else oprsize = get_x86_current_operand_size(proc);
+
+ ASM_INSTRUCTION(result)->opcode = data[(*pos)++];
+
+ /* TODO ! */
+ if ((data[*pos] & 0xc0) != 0xc0)
+ return NULL;
+
+ reg = x86_create_reg1632_operand_from_modrm(data[*pos], oprsize == AOS_32_BITS, false);
+ if (reg == NULL)
+ {
+ free(result);
+ return NULL;
+ }
+
+ (*pos)++;
+
+ value = create_new_x86_operand();
+ if (!fill_imm_operand(ASM_OPERAND(value), AOS_8_BITS, data, pos, len))
+ {
+ free(reg);
+ free(value);
+ free(result);
+ return NULL;
+ }
+
+ ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(2, sizeof(asm_operand *));
+ ASM_INSTRUCTION(result)->operands_count = 2;
+
+ ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(reg);
+ ASM_INSTRUCTION(result)->operands[1] = ASM_OPERAND(value);
+
+ return result;
+
+}
diff --git a/src/arch/x86/op_sbb.c b/src/arch/x86/op_sbb.c
new file mode 100644
index 0000000..9286448
--- /dev/null
+++ b/src/arch/x86/op_sbb.c
@@ -0,0 +1,98 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * op_sbb.c - décodage des soustractions avec retenue
+ *
+ * Copyright (C) 2008 Cyrille Bagard
+ *
+ * This file is part of OpenIDA.
+ *
+ * OpenIDA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * OpenIDA 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include <malloc.h>
+
+
+#include "../instruction-int.h"
+#include "opcodes.h"
+#include "operand.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : data = flux de données à analyser. *
+* pos = position courante dans ce flux. [OUT] *
+* len = taille totale des données à analyser. *
+* offset = adresse virtuelle de l'instruction. *
+* proc = architecture ciblée par le désassemblage. *
+* *
+* Description : Décode une instruction de type 'sbb' (16 ou 32 bits). *
+* *
+* Retour : Instruction mise en place ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+asm_x86_instr *read_instr_sbb8_with_reg1632(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc)
+{
+ asm_x86_instr *result; /* Instruction à retourner */
+ AsmOperandSize oprsize; /* Taille des opérandes */
+ asm_x86_operand *reg; /* Registre de destination */
+ asm_x86_operand *value; /* Valeur empilée */
+
+ result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr));
+
+ /* Utilisation des registres 32 bits ? */
+ if (data[*pos] == 0x66)
+ {
+ oprsize = switch_x86_operand_size(proc);
+ (*pos)++;
+ }
+ else oprsize = get_x86_current_operand_size(proc);
+
+ ASM_INSTRUCTION(result)->opcode = data[(*pos)++];
+
+ /* TODO ! */
+ if ((data[*pos] & 0xc0) != 0xc0)
+ return NULL;
+
+ reg = x86_create_reg1632_operand_from_modrm(data[*pos], oprsize == AOS_32_BITS, false);
+ if (reg == NULL)
+ {
+ free(result);
+ return NULL;
+ }
+
+ (*pos)++;
+
+ value = create_new_x86_operand();
+ if (!fill_imm_operand(ASM_OPERAND(value), AOS_8_BITS, data, pos, len))
+ {
+ free(reg);
+ free(value);
+ free(result);
+ return NULL;
+ }
+
+ ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(2, sizeof(asm_operand *));
+ ASM_INSTRUCTION(result)->operands_count = 2;
+
+ ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(reg);
+ ASM_INSTRUCTION(result)->operands[1] = ASM_OPERAND(value);
+
+ return result;
+
+}
diff --git a/src/arch/x86/op_sub.c b/src/arch/x86/op_sub.c
new file mode 100644
index 0000000..a323aa8
--- /dev/null
+++ b/src/arch/x86/op_sub.c
@@ -0,0 +1,98 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * op_sub.c - décodage des soustractions
+ *
+ * Copyright (C) 2008 Cyrille Bagard
+ *
+ * This file is part of OpenIDA.
+ *
+ * OpenIDA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * OpenIDA 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include <malloc.h>
+
+
+#include "../instruction-int.h"
+#include "opcodes.h"
+#include "operand.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : data = flux de données à analyser. *
+* pos = position courante dans ce flux. [OUT] *
+* len = taille totale des données à analyser. *
+* offset = adresse virtuelle de l'instruction. *
+* proc = architecture ciblée par le désassemblage. *
+* *
+* Description : Décode une instruction de type 'sub' (16 ou 32 bits). *
+* *
+* Retour : Instruction mise en place ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+asm_x86_instr *read_instr_sub8_with_reg1632(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc)
+{
+ asm_x86_instr *result; /* Instruction à retourner */
+ AsmOperandSize oprsize; /* Taille des opérandes */
+ asm_x86_operand *reg; /* Registre de destination */
+ asm_x86_operand *value; /* Valeur empilée */
+
+ result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr));
+
+ /* Utilisation des registres 32 bits ? */
+ if (data[*pos] == 0x66)
+ {
+ oprsize = switch_x86_operand_size(proc);
+ (*pos)++;
+ }
+ else oprsize = get_x86_current_operand_size(proc);
+
+ ASM_INSTRUCTION(result)->opcode = data[(*pos)++];
+
+ /* TODO ! */
+ if ((data[*pos] & 0xc0) != 0xc0)
+ return NULL;
+
+ reg = x86_create_reg1632_operand_from_modrm(data[*pos], oprsize == AOS_32_BITS, false);
+ if (reg == NULL)
+ {
+ free(result);
+ return NULL;
+ }
+
+ (*pos)++;
+
+ value = create_new_x86_operand();
+ if (!fill_imm_operand(ASM_OPERAND(value), AOS_8_BITS, data, pos, len))
+ {
+ free(reg);
+ free(value);
+ free(result);
+ return NULL;
+ }
+
+ ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(2, sizeof(asm_operand *));
+ ASM_INSTRUCTION(result)->operands_count = 2;
+
+ ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(reg);
+ ASM_INSTRUCTION(result)->operands[1] = ASM_OPERAND(value);
+
+ return result;
+
+}
diff --git a/src/arch/x86/op_xor.c b/src/arch/x86/op_xor.c
new file mode 100644
index 0000000..ae97022
--- /dev/null
+++ b/src/arch/x86/op_xor.c
@@ -0,0 +1,165 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * op_xor.c - décodage des OU exclusifs
+ *
+ * Copyright (C) 2008 Cyrille Bagard
+ *
+ * This file is part of OpenIDA.
+ *
+ * OpenIDA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * OpenIDA 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include <malloc.h>
+
+
+#include "../instruction-int.h"
+#include "opcodes.h"
+#include "operand.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : data = flux de données à analyser. *
+* pos = position courante dans ce flux. [OUT] *
+* len = taille totale des données à analyser. *
+* offset = adresse virtuelle de l'instruction. *
+* proc = architecture ciblée par le désassemblage. *
+* *
+* Description : Décode une instruction de type 'xor' (16 ou 32 bits). *
+* *
+* Retour : Instruction mise en place ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+asm_x86_instr *read_instr_xor_with_reg1632(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc)
+{
+ asm_x86_instr *result; /* Instruction à retourner */
+ AsmOperandSize oprsize; /* Taille des opérandes */
+ asm_x86_operand *reg2; /* Registre de source */
+ asm_x86_operand *reg1; /* Registre de destination */
+
+ result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr));
+
+ /* Utilisation des registres 32 bits ? */
+ if (data[*pos] == 0x66)
+ {
+ oprsize = switch_x86_operand_size(proc);
+ (*pos)++;
+ }
+ else oprsize = get_x86_current_operand_size(proc);
+
+ ASM_INSTRUCTION(result)->opcode = data[(*pos)++];
+
+ /* TODO ! */
+ if ((data[*pos] & 0xc0) != 0xc0)
+ return NULL;
+
+ reg1 = x86_create_reg1632_operand_from_modrm(data[*pos], oprsize == AOS_32_BITS, true);
+ if (reg1 == NULL)
+ {
+ free(result);
+ return NULL;
+ }
+
+ reg2 = x86_create_reg1632_operand_from_modrm(data[*pos], oprsize == AOS_32_BITS, false);
+ if (reg2 == NULL)
+ {
+ free(result);
+ free(reg1);
+ return NULL;
+ }
+
+ (*pos)++;
+
+ ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(2, sizeof(asm_operand *));
+ ASM_INSTRUCTION(result)->operands_count = 2;
+
+ ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(reg1);
+ ASM_INSTRUCTION(result)->operands[1] = ASM_OPERAND(reg2);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : data = flux de données à analyser. *
+* pos = position courante dans ce flux. [OUT] *
+* len = taille totale des données à analyser. *
+* offset = adresse virtuelle de l'instruction. *
+* proc = architecture ciblée par le désassemblage. *
+* *
+* Description : Décode une instruction de type 'xor' (16 ou 32 bits). *
+* *
+* Retour : Instruction mise en place ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+asm_x86_instr *read_instr_xor8_with_reg1632(const uint8_t *data, off_t *pos, off_t len, uint64_t offset, const asm_x86_processor *proc)
+{
+ asm_x86_instr *result; /* Instruction à retourner */
+ AsmOperandSize oprsize; /* Taille des opérandes */
+ asm_x86_operand *reg; /* Registre de destination */
+ asm_x86_operand *value; /* Valeur empilée */
+
+ result = (asm_x86_instr *)calloc(1, sizeof(asm_x86_instr));
+
+ /* Utilisation des registres 32 bits ? */
+ if (data[*pos] == 0x66)
+ {
+ oprsize = switch_x86_operand_size(proc);
+ (*pos)++;
+ }
+ else oprsize = get_x86_current_operand_size(proc);
+
+ ASM_INSTRUCTION(result)->opcode = data[(*pos)++];
+
+ /* TODO ! */
+ if ((data[*pos] & 0xc0) != 0xc0)
+ return NULL;
+
+ reg = x86_create_reg1632_operand_from_modrm(data[*pos], oprsize == AOS_32_BITS, false);
+ if (reg == NULL)
+ {
+ free(result);
+ return NULL;
+ }
+
+ (*pos)++;
+
+ value = create_new_x86_operand();
+ if (!fill_imm_operand(ASM_OPERAND(value), AOS_8_BITS, data, pos, len))
+ {
+ free(reg);
+ free(value);
+ free(result);
+ return NULL;
+ }
+
+ ASM_INSTRUCTION(result)->operands = (asm_operand **)calloc(2, sizeof(asm_operand *));
+ ASM_INSTRUCTION(result)->operands_count = 2;
+
+ ASM_INSTRUCTION(result)->operands[0] = ASM_OPERAND(reg);
+ ASM_INSTRUCTION(result)->operands[1] = ASM_OPERAND(value);
+
+ return result;
+
+}
diff --git a/src/arch/x86/opcodes.h b/src/arch/x86/opcodes.h
index a75de7e..6cf6d3c 100644
--- a/src/arch/x86/opcodes.h
+++ b/src/arch/x86/opcodes.h
@@ -34,6 +34,15 @@
+/* Décode une instruction de type 'adc' (16 ou 32 bits). */
+asm_x86_instr *read_instr_adc8_with_reg1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
+
+/* Décode une instruction de type 'add' (16 ou 32 bits). */
+asm_x86_instr *read_instr_add8_with_reg1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
+
+/* Décode une instruction de type 'and' (16 ou 32 bits). */
+asm_x86_instr *read_instr_and8_with_reg1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
+
/* Décode une instruction de type 'call'. */
asm_x86_instr *read_instr_call(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
@@ -55,9 +64,15 @@ asm_x86_instr *read_instr_leave(const uint8_t *, off_t *, off_t, uint64_t, const
/* Décode une instruction de type 'mov' (16 ou 32 bits). */
asm_x86_instr *read_instr_mov_to_1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
+/* Décode une instruction de type 'mov' (16 ou 32 bits). */
+asm_x86_instr *read_instr_mov_with_reg1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
+
/* Décode une instruction de type 'nop'. */
asm_x86_instr *read_instr_nop(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
+/* Décode une instruction de type 'or' (16 ou 32 bits). */
+asm_x86_instr *read_instr_or8_with_reg1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
+
/* Décode une instruction de type 'pop' (16 ou 32 bits). */
asm_x86_instr *read_instr_pop_reg1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
@@ -70,6 +85,18 @@ asm_x86_instr *read_instr_push_reg1632(const uint8_t *, off_t *, off_t, uint64_t
/* Décode une instruction de type 'ret'. */
asm_x86_instr *read_instr_ret(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
+/* Décode une instruction de type 'sbb'. */
+asm_x86_instr *read_instr_sbb8_with_reg1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
+
+/* Décode une instruction de type 'sub'. */
+asm_x86_instr *read_instr_sub8_with_reg1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
+
+/* Décode une instruction de type 'xor' (16 ou 32 bits). */
+asm_x86_instr *read_instr_xor_with_reg1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
+
+/* Décode une instruction de type 'xor' (16 ou 32 bits). */
+asm_x86_instr *read_instr_xor8_with_reg1632(const uint8_t *, off_t *, off_t, uint64_t, const asm_x86_processor *);
+
#endif /* _ARCH_X86_OPCODES_H */
diff --git a/src/arch/x86/operand.c b/src/arch/x86/operand.c
index 4b8eef8..3eaefd2 100644
--- a/src/arch/x86/operand.c
+++ b/src/arch/x86/operand.c
@@ -183,6 +183,65 @@ asm_x86_operand *x86_create_reg1632_operand(uint8_t data, bool is_reg32, uint8_t
/******************************************************************************
* *
+* Paramètres : data = donnée à analyser. *
+* is_reg32 = indique si le registre est un registre 32 bits. *
+* first = indique la partie du ModR/M à traiter. *
+* *
+* Description : Crée une opérande renvoyant vers un registre 16 ou 32 bits. *
+* *
+* Retour : Opérande mise en place ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+asm_x86_operand *x86_create_reg1632_operand_from_modrm(uint8_t data, bool is_reg32, bool first)
+{
+ asm_x86_operand *result; /* Registre à retourner */
+ uint8_t reg; /* Transcription du registre */
+ X8616bRegister reg16; /* Registre 16 bits */
+ X8632bRegister reg32; /* Registre 32 bits */
+
+ if (first) reg = data & 0x07;
+ else reg = (data & 0x38) >> 3;
+
+ if (is_reg32)
+ switch (reg)
+ {
+ case 0 ... 7:
+ reg32 = (X8632bRegister)reg;
+ break;
+ default:
+ return NULL;
+ break;
+ }
+
+ else
+ switch (reg)
+ {
+ case 0 ... 7:
+ reg16 = (X8616bRegister)reg;
+ break;
+ default:
+ return NULL;
+ break;
+ }
+
+ result = create_new_x86_operand();
+
+ ASM_OPERAND(result)->type = AOT_REG;
+ ASM_OPERAND(result)->size = (is_reg32 ? AOS_32_BITS : AOS_16_BITS);
+
+ if (is_reg32) result->x86_value.reg32 = reg32;
+ else result->x86_value.reg16 = reg16;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : operand = instruction à traiter. *
* buffer = tampon de sortie mis à disposition. [OUT] *
* len = taille de ce tampon. *
diff --git a/src/arch/x86/operand.h b/src/arch/x86/operand.h
index ebbdd50..e6eb3cc 100644
--- a/src/arch/x86/operand.h
+++ b/src/arch/x86/operand.h
@@ -45,6 +45,9 @@ asm_x86_operand *create_new_x86_operand(void);
/* Crée une opérande renvoyant vers un registre 16 ou 32 bits. */
asm_x86_operand *x86_create_reg1632_operand(uint8_t, bool, uint8_t);
+/* Crée une opérande renvoyant vers un registre 16 ou 32 bits. */
+asm_x86_operand *x86_create_reg1632_operand_from_modrm(uint8_t, bool, bool);
+
/*Traduit une opérande de registre en texte. */
void x86_print_reg_operand(const asm_x86_operand *, char *, size_t, AsmSyntax);
diff --git a/src/arch/x86/processor.c b/src/arch/x86/processor.c
index 487e4a0..0014652 100644
--- a/src/arch/x86/processor.c
+++ b/src/arch/x86/processor.c
@@ -43,19 +43,44 @@ typedef struct _x86_opcode
{
uint8_t prefix; /* préfixe eventuel */
uint8_t opcode; /* Opcode seul */
+ uint8_t op_ext; /* Extension de l'opcode */
+
+ bool opt_prefix; /* Préfixe optionnel ? */
+ bool has_op_ext; /* Ext. à prendre en compte ? */
+
const char *name; /* Désignation humaine */
read_instr read; /* Décodage de l'instruction */
} x86_opcode;
-#define register_opcode(target, pre, bin, n, func) \
-do {\
-target.prefix = pre; \
-target.opcode = bin; \
-target.name = n; \
-target.read = func; \
-} while (0)
+#define EXT_OPCODE_MASK 0x38
+
+
+#define register_opcode(target, _prefix, _opcode, _name, _read) \
+ do { \
+ target.prefix = _prefix; \
+ target.opcode = _opcode; \
+ target.opt_prefix = true; \
+ target.has_op_ext = false; \
+ target.name = _name; \
+ target.read = _read; \
+ } while (0)
+
+#define register_opcode_with_ext(target, _prefix, _opcode, _ext, _name, _read) \
+ do { \
+ target.prefix = _prefix; \
+ target.opcode = _opcode; \
+ target.op_ext = _ext << 3; \
+ target.opt_prefix = true; \
+ target.has_op_ext = true; \
+ target.name = _name; \
+ target.read = _read; \
+ } while (0)
+
+
+
+
/* Définition générique d'une architecture */
@@ -169,59 +194,67 @@ AsmOperandSize switch_x86_operand_size(const asm_x86_processor *proc)
void x86_register_instructions(asm_x86_processor *proc)
{
- /* TODO : voir pour une inversion avec le mode 16 bits ! */
-
- register_opcode(proc->opcodes[X86_OP_INC_EAX], 0x00, 0x40, "inc", read_instr_inc_1632);
- register_opcode(proc->opcodes[X86_OP_INC_ECX], 0x00, 0x41, "inc", read_instr_inc_1632);
- register_opcode(proc->opcodes[X86_OP_INC_EDX], 0x00, 0x42, "inc", read_instr_inc_1632);
- register_opcode(proc->opcodes[X86_OP_INC_EBX], 0x00, 0x43, "inc", read_instr_inc_1632);
- register_opcode(proc->opcodes[X86_OP_INC_ESP], 0x00, 0x44, "inc", read_instr_inc_1632);
- register_opcode(proc->opcodes[X86_OP_INC_EBP], 0x00, 0x45, "inc", read_instr_inc_1632);
- register_opcode(proc->opcodes[X86_OP_INC_ESI], 0x00, 0x46, "inc", read_instr_inc_1632);
- register_opcode(proc->opcodes[X86_OP_INC_EDI], 0x00, 0x47, "inc", read_instr_inc_1632);
-
- register_opcode(proc->opcodes[X86_OP_DEC_EAX], 0x00, 0x48, "dec", read_instr_dec_1632);
- register_opcode(proc->opcodes[X86_OP_DEC_ECX], 0x00, 0x49, "dec", read_instr_dec_1632);
- register_opcode(proc->opcodes[X86_OP_DEC_EDX], 0x00, 0x4a, "dec", read_instr_dec_1632);
- register_opcode(proc->opcodes[X86_OP_DEC_EBX], 0x00, 0x4b, "dec", read_instr_dec_1632);
- register_opcode(proc->opcodes[X86_OP_DEC_ESP], 0x00, 0x4c, "dec", read_instr_dec_1632);
- register_opcode(proc->opcodes[X86_OP_DEC_EBP], 0x00, 0x4d, "dec", read_instr_dec_1632);
- register_opcode(proc->opcodes[X86_OP_DEC_ESI], 0x00, 0x4e, "dec", read_instr_dec_1632);
- register_opcode(proc->opcodes[X86_OP_DEC_EDI], 0x00, 0x4f, "dec", read_instr_dec_1632);
-
- register_opcode(proc->opcodes[X86_OP_PUSH_EAX], 0x00, 0x50, "push", read_instr_push_reg1632);
- register_opcode(proc->opcodes[X86_OP_PUSH_ECX], 0x00, 0x51, "push", read_instr_push_reg1632);
- register_opcode(proc->opcodes[X86_OP_PUSH_EDX], 0x00, 0x52, "push", read_instr_push_reg1632);
- register_opcode(proc->opcodes[X86_OP_PUSH_EBX], 0x00, 0x53, "push", read_instr_push_reg1632);
- register_opcode(proc->opcodes[X86_OP_PUSH_ESP], 0x00, 0x54, "push", read_instr_push_reg1632);
- register_opcode(proc->opcodes[X86_OP_PUSH_EBP], 0x00, 0x55, "push", read_instr_push_reg1632);
- register_opcode(proc->opcodes[X86_OP_PUSH_ESI], 0x00, 0x56, "push", read_instr_push_reg1632);
- register_opcode(proc->opcodes[X86_OP_PUSH_EDI], 0x00, 0x57, "push", read_instr_push_reg1632);
-
- register_opcode(proc->opcodes[X86_OP_POP_EAX], 0x00, 0x58, "pop", read_instr_pop_reg1632);
- register_opcode(proc->opcodes[X86_OP_POP_ECX], 0x00, 0x59, "pop", read_instr_pop_reg1632);
- register_opcode(proc->opcodes[X86_OP_POP_EDX], 0x00, 0x5a, "pop", read_instr_pop_reg1632);
- register_opcode(proc->opcodes[X86_OP_POP_EBX], 0x00, 0x5b, "pop", read_instr_pop_reg1632);
- register_opcode(proc->opcodes[X86_OP_POP_ESP], 0x00, 0x5c, "pop", read_instr_pop_reg1632);
- register_opcode(proc->opcodes[X86_OP_POP_EBP], 0x00, 0x5d, "pop", read_instr_pop_reg1632);
- register_opcode(proc->opcodes[X86_OP_POP_ESI], 0x00, 0x5e, "pop", read_instr_pop_reg1632);
- register_opcode(proc->opcodes[X86_OP_POP_EDI], 0x00, 0x5f, "pop", read_instr_pop_reg1632);
-
- register_opcode(proc->opcodes[X86_OP_PUSH_IMM32], 0x00, 0x68, "push", read_instr_push_imm1632);
-
+ register_opcode(proc->opcodes[X86_OP_XOR_REG1632], 0x00/*0x66*/, 0x31, "xor", read_instr_xor_with_reg1632);
+
+ register_opcode(proc->opcodes[X86_OP_INC_E_AX], 0x66, 0x40, "inc", read_instr_inc_1632);
+ register_opcode(proc->opcodes[X86_OP_INC_E_CX], 0x66, 0x41, "inc", read_instr_inc_1632);
+ register_opcode(proc->opcodes[X86_OP_INC_E_DX], 0x66, 0x42, "inc", read_instr_inc_1632);
+ register_opcode(proc->opcodes[X86_OP_INC_E_BX], 0x66, 0x43, "inc", read_instr_inc_1632);
+ register_opcode(proc->opcodes[X86_OP_INC_E_SP], 0x66, 0x44, "inc", read_instr_inc_1632);
+ register_opcode(proc->opcodes[X86_OP_INC_E_BP], 0x66, 0x45, "inc", read_instr_inc_1632);
+ register_opcode(proc->opcodes[X86_OP_INC_E_SI], 0x66, 0x46, "inc", read_instr_inc_1632);
+ register_opcode(proc->opcodes[X86_OP_INC_E_DI], 0x66, 0x47, "inc", read_instr_inc_1632);
+
+ register_opcode(proc->opcodes[X86_OP_DEC_E_AX], 0x66, 0x48, "dec", read_instr_dec_1632);
+ register_opcode(proc->opcodes[X86_OP_DEC_E_CX], 0x66, 0x49, "dec", read_instr_dec_1632);
+ register_opcode(proc->opcodes[X86_OP_DEC_E_DX], 0x66, 0x4a, "dec", read_instr_dec_1632);
+ register_opcode(proc->opcodes[X86_OP_DEC_E_BX], 0x66, 0x4b, "dec", read_instr_dec_1632);
+ register_opcode(proc->opcodes[X86_OP_DEC_E_SP], 0x66, 0x4c, "dec", read_instr_dec_1632);
+ register_opcode(proc->opcodes[X86_OP_DEC_E_BP], 0x66, 0x4d, "dec", read_instr_dec_1632);
+ register_opcode(proc->opcodes[X86_OP_DEC_E_SI], 0x66, 0x4e, "dec", read_instr_dec_1632);
+ register_opcode(proc->opcodes[X86_OP_DEC_E_DI], 0x66, 0x4f, "dec", read_instr_dec_1632);
+
+ register_opcode(proc->opcodes[X86_OP_PUSH_E_AX], 0x66, 0x50, "push", read_instr_push_reg1632);
+ register_opcode(proc->opcodes[X86_OP_PUSH_E_CX], 0x66, 0x51, "push", read_instr_push_reg1632);
+ register_opcode(proc->opcodes[X86_OP_PUSH_E_DX], 0x66, 0x52, "push", read_instr_push_reg1632);
+ register_opcode(proc->opcodes[X86_OP_PUSH_E_BX], 0x66, 0x53, "push", read_instr_push_reg1632);
+ register_opcode(proc->opcodes[X86_OP_PUSH_E_SP], 0x66, 0x54, "push", read_instr_push_reg1632);
+ register_opcode(proc->opcodes[X86_OP_PUSH_E_BP], 0x66, 0x55, "push", read_instr_push_reg1632);
+ register_opcode(proc->opcodes[X86_OP_PUSH_E_SI], 0x66, 0x56, "push", read_instr_push_reg1632);
+ register_opcode(proc->opcodes[X86_OP_PUSH_E_DI], 0x66, 0x57, "push", read_instr_push_reg1632);
+
+ register_opcode(proc->opcodes[X86_OP_POP_E_AX], 0x66, 0x58, "pop", read_instr_pop_reg1632);
+ register_opcode(proc->opcodes[X86_OP_POP_E_CX], 0x66, 0x59, "pop", read_instr_pop_reg1632);
+ register_opcode(proc->opcodes[X86_OP_POP_E_DX], 0x66, 0x5a, "pop", read_instr_pop_reg1632);
+ register_opcode(proc->opcodes[X86_OP_POP_E_BX], 0x66, 0x5b, "pop", read_instr_pop_reg1632);
+ register_opcode(proc->opcodes[X86_OP_POP_E_SP], 0x66, 0x5c, "pop", read_instr_pop_reg1632);
+ register_opcode(proc->opcodes[X86_OP_POP_E_BP], 0x66, 0x5d, "pop", read_instr_pop_reg1632);
+ register_opcode(proc->opcodes[X86_OP_POP_E_SI], 0x66, 0x5e, "pop", read_instr_pop_reg1632);
+ register_opcode(proc->opcodes[X86_OP_POP_E_DI], 0x66, 0x5f, "pop", read_instr_pop_reg1632);
+
+ register_opcode(proc->opcodes[X86_OP_PUSH_IMM1632], 0x66, 0x68, "push", read_instr_push_imm1632);
+
+
+ register_opcode(proc->opcodes[X86_OP_MOV_REG1632], 0x66, 0x89, "mov", read_instr_mov_with_reg1632);
+
+ register_opcode_with_ext(proc->opcodes[X86_OP_ADD8_REG1632], 0x66, 0x83, 0, "add", read_instr_add8_with_reg1632);
+ register_opcode_with_ext(proc->opcodes[X86_OP_OR8_REG1632], 0x66, 0x83, 1, "or", read_instr_or8_with_reg1632);
+ register_opcode_with_ext(proc->opcodes[X86_OP_ADC8_REG1632], 0x66, 0x83, 2, "adc", read_instr_adc8_with_reg1632);
+ register_opcode_with_ext(proc->opcodes[X86_OP_SBB8_REG1632], 0x66, 0x83, 3, "sbb", read_instr_sbb8_with_reg1632);
+ register_opcode_with_ext(proc->opcodes[X86_OP_AND8_REG1632], 0x66, 0x83, 4, "and", read_instr_and8_with_reg1632);
+ register_opcode_with_ext(proc->opcodes[X86_OP_SUB8_REG1632], 0x66, 0x83, 5, "sub", read_instr_sub8_with_reg1632);
+ register_opcode_with_ext(proc->opcodes[X86_OP_XOR8_REG1632], 0x66, 0x83, 6, "xor", read_instr_xor8_with_reg1632);
register_opcode(proc->opcodes[X86_OP_NOP], 0x00, 0x90, "nop", read_instr_nop);
-
- register_opcode(proc->opcodes[X86_OP_MOV_AX], 0x00, 0xb8, "mov", read_instr_mov_to_1632);
- register_opcode(proc->opcodes[X86_OP_MOV_CX], 0x00, 0xb9, "mov", read_instr_mov_to_1632);
- register_opcode(proc->opcodes[X86_OP_MOV_DX], 0x00, 0xba, "mov", read_instr_mov_to_1632);
- register_opcode(proc->opcodes[X86_OP_MOV_BX], 0x00, 0xbb, "mov", read_instr_mov_to_1632);
- register_opcode(proc->opcodes[X86_OP_MOV_SP], 0x00, 0xbc, "mov", read_instr_mov_to_1632);
- register_opcode(proc->opcodes[X86_OP_MOV_BP], 0x00, 0xbd, "mov", read_instr_mov_to_1632);
- register_opcode(proc->opcodes[X86_OP_MOV_SI], 0x00, 0xbe, "mov", read_instr_mov_to_1632);
- register_opcode(proc->opcodes[X86_OP_MOV_DI], 0x00, 0xbf, "mov", read_instr_mov_to_1632);
-
+ register_opcode(proc->opcodes[X86_OP_MOV_E_AX], 0x66, 0xb8, "mov", read_instr_mov_to_1632);
+ register_opcode(proc->opcodes[X86_OP_MOV_E_CX], 0x66, 0xb9, "mov", read_instr_mov_to_1632);
+ register_opcode(proc->opcodes[X86_OP_MOV_E_DX], 0x66, 0xba, "mov", read_instr_mov_to_1632);
+ register_opcode(proc->opcodes[X86_OP_MOV_E_BX], 0x66, 0xbb, "mov", read_instr_mov_to_1632);
+ register_opcode(proc->opcodes[X86_OP_MOV_E_SP], 0x66, 0xbc, "mov", read_instr_mov_to_1632);
+ register_opcode(proc->opcodes[X86_OP_MOV_E_BP], 0x66, 0xbd, "mov", read_instr_mov_to_1632);
+ register_opcode(proc->opcodes[X86_OP_MOV_E_SI], 0x66, 0xbe, "mov", read_instr_mov_to_1632);
+ register_opcode(proc->opcodes[X86_OP_MOV_E_DI], 0x66, 0xbf, "mov", read_instr_mov_to_1632);
register_opcode(proc->opcodes[X86_OP_RET], 0x00, 0xc3, "ret", read_instr_ret);
register_opcode(proc->opcodes[X86_OP_LEAVE], 0x00, 0xc9, "leave", read_instr_leave);
@@ -234,54 +267,6 @@ void x86_register_instructions(asm_x86_processor *proc)
register_opcode(proc->opcodes[X86_OP_HLT], 0x00, 0xf4, "hlt", read_instr_hlt);
- register_opcode(proc->opcodes[X86_OP_INC_AX], 0x66, 0x40, "inc", read_instr_inc_1632);
- register_opcode(proc->opcodes[X86_OP_INC_CX], 0x66, 0x41, "inc", read_instr_inc_1632);
- register_opcode(proc->opcodes[X86_OP_INC_DX], 0x66, 0x42, "inc", read_instr_inc_1632);
- register_opcode(proc->opcodes[X86_OP_INC_BX], 0x66, 0x43, "inc", read_instr_inc_1632);
- register_opcode(proc->opcodes[X86_OP_INC_SP], 0x66, 0x44, "inc", read_instr_inc_1632);
- register_opcode(proc->opcodes[X86_OP_INC_BP], 0x66, 0x45, "inc", read_instr_inc_1632);
- register_opcode(proc->opcodes[X86_OP_INC_SI], 0x66, 0x46, "inc", read_instr_inc_1632);
- register_opcode(proc->opcodes[X86_OP_INC_DI], 0x66, 0x47, "inc", read_instr_inc_1632);
-
- register_opcode(proc->opcodes[X86_OP_DEC_AX], 0x66, 0x48, "dec", read_instr_dec_1632);
- register_opcode(proc->opcodes[X86_OP_DEC_CX], 0x66, 0x49, "dec", read_instr_dec_1632);
- register_opcode(proc->opcodes[X86_OP_DEC_DX], 0x66, 0x4a, "dec", read_instr_dec_1632);
- register_opcode(proc->opcodes[X86_OP_DEC_BX], 0x66, 0x4b, "dec", read_instr_dec_1632);
- register_opcode(proc->opcodes[X86_OP_DEC_SP], 0x66, 0x4c, "dec", read_instr_dec_1632);
- register_opcode(proc->opcodes[X86_OP_DEC_BP], 0x66, 0x4d, "dec", read_instr_dec_1632);
- register_opcode(proc->opcodes[X86_OP_DEC_SI], 0x66, 0x4e, "dec", read_instr_dec_1632);
- register_opcode(proc->opcodes[X86_OP_DEC_DI], 0x66, 0x4f, "dec", read_instr_dec_1632);
-
- register_opcode(proc->opcodes[X86_OP_PUSH_AX], 0x66, 0x50, "push", read_instr_push_reg1632);
- register_opcode(proc->opcodes[X86_OP_PUSH_CX], 0x66, 0x51, "push", read_instr_push_reg1632);
- register_opcode(proc->opcodes[X86_OP_PUSH_DX], 0x66, 0x52, "push", read_instr_push_reg1632);
- register_opcode(proc->opcodes[X86_OP_PUSH_BX], 0x66, 0x53, "push", read_instr_push_reg1632);
- register_opcode(proc->opcodes[X86_OP_PUSH_SP], 0x66, 0x54, "push", read_instr_push_reg1632);
- register_opcode(proc->opcodes[X86_OP_PUSH_BP], 0x66, 0x55, "push", read_instr_push_reg1632);
- register_opcode(proc->opcodes[X86_OP_PUSH_SI], 0x66, 0x56, "push", read_instr_push_reg1632);
- register_opcode(proc->opcodes[X86_OP_PUSH_DI], 0x66, 0x57, "push", read_instr_push_reg1632);
-
- register_opcode(proc->opcodes[X86_OP_POP_AX], 0x66, 0x58, "pop", read_instr_pop_reg1632);
- register_opcode(proc->opcodes[X86_OP_POP_CX], 0x66, 0x59, "pop", read_instr_pop_reg1632);
- register_opcode(proc->opcodes[X86_OP_POP_DX], 0x66, 0x5a, "pop", read_instr_pop_reg1632);
- register_opcode(proc->opcodes[X86_OP_POP_BX], 0x66, 0x5b, "pop", read_instr_pop_reg1632);
- register_opcode(proc->opcodes[X86_OP_POP_SP], 0x66, 0x5c, "pop", read_instr_pop_reg1632);
- register_opcode(proc->opcodes[X86_OP_POP_BP], 0x66, 0x5d, "pop", read_instr_pop_reg1632);
- register_opcode(proc->opcodes[X86_OP_POP_SI], 0x66, 0x5e, "pop", read_instr_pop_reg1632);
- register_opcode(proc->opcodes[X86_OP_POP_DI], 0x66, 0x5f, "pop", read_instr_pop_reg1632);
-
- register_opcode(proc->opcodes[X86_OP_PUSH_IMM16], 0x66, 0x68, "push", read_instr_push_imm1632);
-
- register_opcode(proc->opcodes[X86_OP_MOV_EAX], 0x66, 0xb8, "mov", read_instr_mov_to_1632);
- register_opcode(proc->opcodes[X86_OP_MOV_ECX], 0x66, 0xb9, "mov", read_instr_mov_to_1632);
- register_opcode(proc->opcodes[X86_OP_MOV_EDX], 0x66, 0xba, "mov", read_instr_mov_to_1632);
- register_opcode(proc->opcodes[X86_OP_MOV_EBX], 0x66, 0xbb, "mov", read_instr_mov_to_1632);
- register_opcode(proc->opcodes[X86_OP_MOV_ESP], 0x66, 0xbc, "mov", read_instr_mov_to_1632);
- register_opcode(proc->opcodes[X86_OP_MOV_EBP], 0x66, 0xbd, "mov", read_instr_mov_to_1632);
- register_opcode(proc->opcodes[X86_OP_MOV_ESI], 0x66, 0xbe, "mov", read_instr_mov_to_1632);
- register_opcode(proc->opcodes[X86_OP_MOV_EDI], 0x66, 0xbf, "mov", read_instr_mov_to_1632);
-
-
}
@@ -307,20 +292,36 @@ asm_instr *x86_fetch_instruction(const asm_x86_processor *proc, const uint8_t *d
{
asm_x86_instr *result; /* Résultat à faire remonter */
X86Opcodes i; /* Boucle de parcours */
+ off_t tmp; /* Tête de lecture */
result = NULL;
for (i = 0; i < X86_OP_COUNT; i++)
{
- if ((proc->opcodes[i].prefix > 0 && data[*pos] == proc->opcodes[i].prefix && data[*pos + 1] == proc->opcodes[i].opcode)
- || (proc->opcodes[i].prefix == 0 && data[*pos] == proc->opcodes[i].opcode))
+ if (proc->opcodes[i].prefix > 0 && data[*pos] == proc->opcodes[i].prefix && data[*pos + 1] == proc->opcodes[i].opcode)
+ {
+ tmp = *pos + 2;
+ goto find_instr;
+ }
+
+ if (proc->opcodes[i].opt_prefix && data[*pos] == proc->opcodes[i].opcode)
{
- result = proc->opcodes[i].read(data, pos, len, offset, proc);
- if (result != NULL) result->type = i;
- else printf("err while decoding :: [0x%02hhx] 0x%02hhx\n", proc->opcodes[i].prefix, proc->opcodes[i].opcode);
- break;
+ tmp = *pos + 1;
+ goto find_instr;
}
+ continue;
+
+ find_instr:
+
+ if (proc->opcodes[i].has_op_ext && (data[tmp] & EXT_OPCODE_MASK) != proc->opcodes[i].op_ext)
+ continue;
+
+ result = proc->opcodes[i].read(data, pos, len, offset, proc);
+ if (result != NULL) result->type = i;
+ else printf("err while decoding :: [0x%02hhx] 0x%02hhx\n", proc->opcodes[i].prefix, proc->opcodes[i].opcode);
+ break;
+
}
return ASM_INSTRUCTION(result);