-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathinstructions_90.c
157 lines (146 loc) · 3.12 KB
/
instructions_90.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
#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"
/*
* xchg r32 r32: 1 byte
* Exchanges values of EAX and r32.
* 1 byte: op (90 ~ 97)
*/
void xchg_r32_r32(Emulator *emu)
{
uint8_t reg = get_code8(emu, 0) - 0x90;
uint32_t original_val = get_register32(emu, reg);
set_register32(emu, reg, get_register32(emu, EAX));
set_register32(emu, EAX, original_val);
emu->eip += 1;
}
/*
* xchg r16 r16: 1 byte
* Exchanges values of AX and r16.
* 1 byte: op (90 ~ 97)
*/
void xchg_r16_r16(Emulator *emu)
{
uint8_t reg = get_code8(emu, 0) - 0x90;
uint16_t original_val = get_register16(emu, reg);
set_register16(emu, reg, get_register16(emu, EAX));
set_register16(emu, EAX, original_val);
emu->eip += 1;
}
/*
* cwde: 1 byte
* Sign-extend word(AX) to double word(EAX).
* 1 byte: op (98)
*/
void cwde(Emulator *emu)
{
uint32_t eax = get_register32(emu, EAX);
uint16_t ax = (uint16_t)eax;
uint8_t sign = ax >> 15 & 1;
if (sign == 1)
{
uint32_t sign_extended = 0xFFFF0000 | ax;
set_register32(emu, EAX, sign_extended);
}
else
{
set_register32(emu, EAX, (uint32_t)ax);
}
emu->eip += 1;
}
/*
* cdq: 1 byte
* Sign-extend double word(EAX) to quad word(EDX:EAX).
* 1 byte: op (99)
*/
void cdq(Emulator *emu)
{
uint32_t eax = get_register32(emu, EAX);
uint8_t sign = eax >> 31 & 1;
if (sign == 1)
set_register32(emu, EDX, 0xFFFFFFFF);
else
set_register32(emu, EDX, 0);
emu->eip += 1;
}
/*
* call ptr16:16/32: 7 bytes
* Pushes CS and EIP in order and jumps to ptr16:32.
* 1 byte: op (9A)
* 2 byte: cs value
* 2|4 byte: eip (ptr16|32)
*/
void ptr_call(Emulator *emu)
{
push_segment_register(emu, CS);
if (emu->is_pe)
push32(emu, emu->eip + 7);
else
push32(emu, emu->eip + 5);
ptr_jump(emu);
}
/*
* pushf / pushfd: 1 byte
* Pushes EFLAGS into stack.
* 1 byte: op (9C)
*/
void pushfd(Emulator *emu)
{
/*
if (emu->is_pe)
push32(emu, emu->eflags);
else
push16(emu, (uint16_t)emu->eflags);
*/
push32(emu, emu->eflags);
emu->eip += 1;
};
/*
* popf / popfd: 1 byte
* Pops stack into EFLAGS.
* 1 byte: op (9D)
*/
void popfd(Emulator *emu)
{
/*
uint32_t value;
if (emu->is_pe)
value = pop32(emu);
else
value = (uint32_t)pop16(emu);
emu->eflags = value;
*/
emu->eflags = pop32(emu);
emu->eip += 1;
};
/*
* sahf:
* Stores AH into FLAGS (Bit 0, 2, 4, 6, 7).
* 1 byte: op (9E)
*/
void sahf(Emulator *emu)
{
/* AH value AND 1101 0101 128 64 16 4 1 = 213 */
uint8_t ah_val = get_register8(emu, AH) & 213;
/* Higher half of EFLAGS: AND 0xFFFF0000 */
uint32_t eflags_h = emu->eflags & 0xFFFF0000;
emu->eflags = eflags_h | ah_val;
emu->eip += 1;
}
/*
* lahf:
* Load FLAGS into AH (0, 2, 4, 6, 7th bits).
* 1 byte: op (9F)
*/
void lahf(Emulator *emu)
{
uint8_t eflags_l = emu->eflags & 213;
set_register8(emu, AH, eflags_l);
emu->eip += 1;
}