-
Notifications
You must be signed in to change notification settings - Fork 9
/
instructions_60.c
153 lines (144 loc) · 3.76 KB
/
instructions_60.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include "instruction_defs.h"
#include "emulator_functions.h"
#include "modrm.h"
#include "io.h"
/*
* pushad: 1 bytes
* Pushes contents of general-purpose registers into stack.
* 1 byte: op (60)
*/
void pushad(Emulator *emu)
{
uint32_t original_esp = get_register32(emu, ESP);
push32(emu, get_register32(emu, EAX));
push32(emu, get_register32(emu, ECX));
push32(emu, get_register32(emu, EDX));
push32(emu, get_register32(emu, EBX));
push32(emu, original_esp);
push32(emu, get_register32(emu, EBP));
push32(emu, get_register32(emu, ESI));
push32(emu, get_register32(emu, EDI));
emu->eip += 1;
}
/*
* popad: 1 bytes
* Pops from stack into general-purpose registers.
* 1 byte: op (61)
*/
void popad(Emulator *emu)
{
set_register32(emu, EDI, pop32(emu));
set_register32(emu, ESI, pop32(emu));
set_register32(emu, EBP, pop32(emu));
/* Skips original ESP value by incrementing ESP by 4 bytes. */
set_register32(emu, ESP, get_register32(emu, ESP) + 4);
set_register32(emu, EBX, pop32(emu));
set_register32(emu, EDX, pop32(emu));
set_register32(emu, ECX, pop32(emu));
set_register32(emu, EAX, pop32(emu));
emu->eip += 1;
}
/*
* push imm32: 5 bytes
* Pushes 32-bit immediate value into stack.
* 1 byte: op (68)
* 4 bytes: immediate 32-bit value
*/
void push_imm32(Emulator *emu)
{
uint32_t value = get_code32(emu, 1);
push32(emu, value);
emu->eip += 5;
}
static void imul_r32_rm32_imm(Emulator *emu, ModRM *modrm, int32_t imm_val)
{
uint64_t result;
if (modrm->mod == 3)
{
/* r32 = r32 * signed imm */
int32_t r32_val = get_register32(emu, modrm->reg_index);
result = (int64_t)r32_val * (int64_t)imm_val;
}
else
{
/* r32 = rm32 * signed imm */
int32_t rm32_val = get_rm32(emu, modrm);
result = (int64_t)rm32_val * (int64_t)imm_val;
}
uint32_t res_upper_half = result >> 32;
uint32_t res_lower_half = (uint32_t)result;
update_eflags_mul(emu, res_upper_half);
set_register32(emu, modrm->reg_index, res_lower_half);
}
/*
* imul r32 imm8 | imul r32 rm32 imm32: 6|7 bytes
* Performs signed multiplication (r32 = (r32|rm32) * imm32).
* 1 byte: op (69)
* 1|2 bytes: ModRm
* 4 bytes: imm32 value
*/
void imul_r32_rm32_imm32(Emulator *emu)
{
/* Proceed 1 byte for op code 6B. */
emu->eip += 1;
ModRM modrm = create_modrm();
parse_modrm(emu, &modrm);
int32_t imm32_val = get_code32(emu, 0);
emu->eip += 4;
imul_r32_rm32_imm(emu, &modrm, imm32_val);
}
/*
* push imm8: 2 bytes
* Pushes 8-bit immediate value into stack.
* 1 byte: op (6A)
* 1 byte: immediate 8-bit value
*/
void push_imm8(Emulator *emu)
{
uint8_t value = get_code8(emu, 1);
push32(emu, (uint32_t)value);
emu->eip += 2;
}
/*
* imul r32 imm8 | imul r32 rm32 imm8: 3|4 bytes
* Performs signed multiplication (r32 = (r32|rm32) * imm8).
* 1 byte: op (6B)
* 1|2 bytes: ModRm
* 1 bytes: imm8 value
*/
void imul_r32_rm32_imm8(Emulator *emu)
{
/* Proceed 1 byte for op code 6B. */
emu->eip += 1;
ModRM modrm = create_modrm();
parse_modrm(emu, &modrm);
int8_t imm8_val = get_code8(emu, 0);
emu->eip += 1;
imul_r32_rm32_imm(emu, &modrm, imm8_val);
}
/*
* ins m32 dx
* Inputs dword from DX port into ES:EDI
* 1 byte: op (6D)
*/
void ins_m32_dx(Emulator *emu)
{
uint16_t dx_val = get_register16(emu, EDX);
uint32_t in_val = io_in32(emu, dx_val);
uint32_t edi_val = get_register32(emu, EDI);
set_memory32(emu, ES, edi_val, in_val);
if (is_direction_down(emu))
{
set_register32(emu, EDI, edi_val - 4);
}
else
{
set_register32(emu, EDI, edi_val + 4);
}
emu->eip += 1;
}