-
Notifications
You must be signed in to change notification settings - Fork 9
/
instructions_A0.c
282 lines (260 loc) · 6.89 KB
/
instructions_A0.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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
#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"
/*
* mov al moffs8: 5 bytes
* Copies moffs value to AL. (8 bit)
* 1 byte: op (A0)
* 4 byte: moffs
*/
void mov_al_moffs8(Emulator *emu)
{
uint32_t offset = get_code32(emu, 1);
uint8_t mem_val = get_memory8(emu, DS, offset);
set_register8(emu, AL, mem_val);
emu->eip += 5;
}
/*
* mov eax moffs16/32: 5 bytes
* Copies moffs value to AX/EAX. (16/32 bit)
* 1 byte: op (A1)
* 4 byte: moffs
*/
void mov_eax_moffs32(Emulator *emu)
{
uint32_t offset = get_code32(emu, 1);
uint32_t mem_val = get_memory32(emu, DS, offset);
set_register32(emu, EAX, mem_val);
emu->eip += 5;
}
/*
* mov moffs8 al: 5 bytes
* Copies AL value to moffs. (8 bit)
* 1 byte: op (A2)
* 4 byte: moffs
*/
void mov_moffs8_al(Emulator *emu)
{
uint32_t offset = get_code32(emu, 1);
uint8_t al_val = get_register8(emu, AL);
set_memory8(emu, DS, offset, al_val);
emu->eip += 5;
}
/*
* mov moffs16 ax: 5 bytes
* Copies AX value to moffs. (16 bit)
* 1 byte: op (A3)
* 4 byte: moffs
*/
void mov_moffs16_ax(Emulator *emu)
{
uint32_t offset = get_code32(emu, 1);
uint16_t ax_val = get_register32(emu, EAX);
set_memory16(emu, DS, offset, ax_val);
emu->eip += 5;
}
/*
* mov moffs16/32 eax: 5 bytes
* Copies AX/EAX value to moffs. (16/32 bit)
* 1 byte: op (A3)
* 4 byte: moffs
*/
void mov_moffs32_eax(Emulator *emu)
{
uint32_t offset = get_code32(emu, 1);
uint32_t eax_val = get_register32(emu, EAX);
set_memory32(emu, DS, offset, eax_val);
emu->eip += 5;
}
static void update_counter(Emulator *emu, int reg_index, uint32_t val, uint32_t byte_num)
{
if (is_direction_down(emu))
{
set_register32(emu, reg_index, val - byte_num);
}
else
{
set_register32(emu, reg_index, val + byte_num);
}
}
static void update_esi_edi(Emulator *emu, uint32_t esi_val, uint32_t edi_val, uint32_t byte_num)
{
update_counter(emu, ESI, esi_val, byte_num);
update_counter(emu, EDI, edi_val, byte_num);
}
/*
* movsb: 1 byte
* Moves byte at DS:SI/ESI to ES:DI/EDI.
* 1 byte: op (A4)
*/
void movsb(Emulator *emu)
{
uint32_t esi_val = get_register32(emu, ESI);
uint32_t edi_val = get_register32(emu, EDI);
uint8_t ds_esi_val = get_memory8(emu, DS, esi_val);
set_memory8(emu, ES, edi_val, ds_esi_val);
update_esi_edi(emu, esi_val, edi_val, 1);
emu->eip += 1;
}
/*
* movsd: 1 byte
* Moves word/double word at DS:SI/ESI to ES:DI/EDI.
* 1 byte: op (A5)
*/
void movsd(Emulator *emu)
{
uint32_t esi_val = get_register32(emu, ESI);
uint32_t edi_val = get_register32(emu, EDI);
uint32_t ds_esi_val = get_memory32(emu, DS, esi_val);
set_memory32(emu, ES, edi_val, ds_esi_val);
update_esi_edi(emu, esi_val, edi_val, 4);
emu->eip += 1;
}
/*
* cmpsd: 1 byte
* Compares byte of DS:SI/ESI value and ES:DI/EDI by subtracting in order.
* 1 byte: op (A6)
*/
void cmpsb(Emulator *emu)
{
uint32_t esi_val = get_register32(emu, ESI);
uint32_t edi_val = get_register32(emu, EDI);
uint8_t ds_esi_val = get_memory8(emu, DS, esi_val);
uint8_t es_edi_val = get_memory8(emu, ES, edi_val);
uint64_t result = (uint16_t)ds_esi_val - (uint16_t)es_edi_val;
update_eflags_sub(emu, ds_esi_val, es_edi_val, result);
update_esi_edi(emu, esi_val, edi_val, 1);
emu->eip += 1;
}
/*
* cmpsd: 1 byte
* Compares dword of DS:SI/ESI value and ES:DI/EDI by subtracting in order.
* 1 byte: op (A7)
*/
void cmpsd(Emulator *emu)
{
uint32_t esi_val = get_register32(emu, ESI);
uint32_t edi_val = get_register32(emu, EDI);
uint32_t ds_esi_val = get_memory32(emu, DS, esi_val);
uint32_t es_edi_val = get_memory32(emu, ES, edi_val);
uint64_t result = (uint64_t)ds_esi_val - (uint64_t)es_edi_val;
update_eflags_sub(emu, ds_esi_val, es_edi_val, result);
update_esi_edi(emu, esi_val, edi_val, 4);
emu->eip += 1;
}
/*
* test al imm8: 2 bytes
* Performs logical AND of operands and updates flags. No result store.
* 1 byte: op (A8)
* 1 byte: imm8 value
*/
void test_al_imm8(Emulator *emu)
{
uint8_t imm8_val = get_code8(emu, 1);
uint8_t al_val = get_register8(emu, AL);
uint8_t result = al_val & imm8_val;
update_eflags_logical_ops_8bit(emu, result);
emu->eip += 2;
}
/*
* test eax imm32: 5 bytes
* Performs logical AND of operands and updates flags. No result store.
* 1 byte: op (A9)
* 4 bytes: imm32 value
*/
void test_eax_imm32(Emulator *emu)
{
uint32_t eax_val = get_register32(emu, EAX);
uint32_t imm32_val = get_code32(emu, 1);
uint32_t result = eax_val & imm32_val;
update_eflags_logical_ops(emu, result);
emu->eip += 5;
}
/*
* stosb: 1 byte
* Stores byte value of AL to ES:DI/EDI.
* 1 byte: op (AA)
*/
void stosb(Emulator *emu)
{
uint8_t al_val = get_register8(emu, AL);
uint32_t edi_val = get_register32(emu, EDI);
set_memory8(emu, ES, edi_val, al_val);
update_counter(emu, EDI, edi_val, 1);
emu->eip += 1;
}
/*
* stosb: 1 byte
* Stores double word value of EAX to ES:DI/EDI.
* 1 byte: op (AB)
*/
void stosd(Emulator *emu)
{
uint32_t eax_val = get_register32(emu, EAX);
uint32_t edi_val = get_register32(emu, EDI);
set_memory32(emu, ES, edi_val, eax_val);
update_counter(emu, EDI, edi_val, 4);
emu->eip += 1;
}
/*
* lodsb: 1 byte
* Loads byte value DS:SI/ESI to AL.
* 1 byte: op (AC)
*/
void lodsb(Emulator *emu)
{
uint32_t esi_val = get_register32(emu, ESI);
uint8_t ds_esi_val = get_memory8(emu, DS, esi_val);
set_register8(emu, AL, ds_esi_val);
update_counter(emu, ESI, esi_val, 1);
emu->eip += 1;
}
/*
* lodsd: 1 byte
* Loads double word value DS:SI/ESI to EAX.
* 1 byte: op (AD)
*/
void lodsd(Emulator *emu)
{
uint32_t esi_val = get_register32(emu, ESI);
uint32_t ds_esi_val = get_memory32(emu, DS, esi_val);
set_register32(emu, EAX, ds_esi_val);
update_counter(emu, ESI, esi_val, 4);
emu->eip += 1;
}
/*
* scasb: 1 byte
* Compares AL and ES:DI/EDI by subtracting in order.
* 1 byte: op (AE)
*/
void scasb(Emulator *emu)
{
uint8_t al_val = get_register8(emu, AL);
uint32_t edi_val = get_register32(emu, EDI);
uint8_t es_edi_val = get_memory8(emu, ES, edi_val);
uint64_t result = (uint16_t)al_val - (uint16_t)es_edi_val;
update_eflags_sub(emu, al_val, es_edi_val, result);
update_counter(emu, EDI, edi_val, 1);
emu->eip += 1;
}
/*
* scasd: 1 byte
* Compares EAX and ES:DI/EDI by subtracting in order.
* 1 byte: op (AF)
*/
void scasd(Emulator *emu)
{
uint32_t eax_val = get_register32(emu, EAX);
uint32_t edi_val = get_register32(emu, EDI);
uint32_t es_edi_val = get_memory32(emu, ES, edi_val);
uint64_t result = (uint64_t)eax_val - (uint64_t)es_edi_val;
update_eflags_sub(emu, eax_val, es_edi_val, result);
update_counter(emu, EDI, edi_val, 4);
emu->eip += 1;
}