/
common.c
169 lines (144 loc) · 4.34 KB
/
common.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
/**************************************************
** **
** BJ Peter DeLaCruz **
** October , 2010 **
** ICS 611 **
** **
** Project #4 **
** **
** **
** **
**************************************************/
#include "common.h"
#include "constants.h"
unsigned char code_stack[CODE_STACK_SIZE];
unsigned char fixup_stack[FIXUP_STACK_SIZE];
int code_stack_pos = 0;
int fixup_stack_pos = 0;
extern int prev_code_stack_pos;
int common(int opcode_operand, int reg_operand, int other_operand, int displ, int direction) {
unsigned char byte = 0x00;
/* It is assumed that the direction bit in opcode_operand is turned on. */
byte |= opcode_operand;
if (reg_operand >= AX && reg_operand <= DI && opcode_operand != LEA) {
byte++;
}
if (direction == OFF) {
byte ^= 0x02;
}
add_to_code_stack(byte);
/* e.g. SUB BL, CL */
if (displ == NO_DISPL) {
byte = 0xC0; /* mm = 11 */
byte |= (reg_operand << REG_FIELD);
byte |= other_operand; /* r/m field = second register */
if (reg_operand >= AX && reg_operand <= BX) {
byte ^= 0x08;
}
add_to_code_stack(byte);
return 0;
}
/* e.g. SUB BX, [BX + 0005H] */
if (other_operand == INDIRECT_BX || other_operand == INDIRECT_BP) {
if (displ > 0xFF) { /* 16-bit displacement */
byte = 0x80;
}
else if (displ == 0x00) { /* no displacement */
byte = 0x00;
}
else { /* 8-bit displacement */
byte = 0x40;
}
byte |= (reg_operand << REG_FIELD);
/* Set mm = 10 if the displacement is 16-bit. */
if (displ > 0xFF) {
byte ^= 0x40;
}
if (other_operand == INDIRECT_BX) {
byte |= 0x07;
}
else {
byte |= 0x06;
}
}
/* e.g. SUB BX, [2A43H] */
else {
byte = 0x06; /* r/m = 110 */
byte |= (reg_operand << REG_FIELD);
/* Set mm = 00 if register is 16-bit. */
if (reg_operand >= AX && reg_operand <= DI) {
byte ^= 0x40;
}
}
add_to_code_stack(byte);
/* Add displacement to the code stack. */
if (displ > 0xFF) { /* 16-bit displacement */
/* Store low-order byte first, e.g. 05H. */
byte = displ;
add_to_code_stack(byte);
byte = displ >> 8; /* Then store high-order byte, e.g. 00H. */
add_to_code_stack(byte);
}
else { /* 8-bit displacement */
byte = displ;
add_to_code_stack(byte);
byte = 0x00;
add_to_code_stack(byte);
}
if (other_operand == DIRECT) {
fix_offset();
}
return 0;
}
void fix_offset() {
int size = code_stack_pos - prev_code_stack_pos - 2;
if (size < 0x0100) {
fixup_stack[fixup_stack_pos++] = 0xC4;
}
else if (size >= 0x0100 && size < 0x0200) {
fixup_stack[fixup_stack_pos++] = 0xC5;
}
else if (size >= 0x0200 && size < 0x0300) {
fixup_stack[fixup_stack_pos++] = 0xC6;
}
else if (size >= 0x0300) {
fixup_stack[fixup_stack_pos++] = 0xC7;
}
fixup_stack[fixup_stack_pos++] = size;
fixup_stack[fixup_stack_pos++] = 0x54;
fixup_stack[fixup_stack_pos++] = 0x02; /* assumes 2nd segdef */
}
void add_to_code_stack(char code) {
code_stack[code_stack_pos++] = code;
}
void print_character_in_binary(char character) {
int i;
for (i = 7; i >= 0; i--) {
if ((1 << i) & character) {
printf("1");
}
else {
printf("0");
}
}
}
void print_code_stack() {
int i, count;
for (i = 0, count = 1; i < code_stack_pos; i++, count++) {
print_character_in_binary(code_stack[i]);
printf(" ");
if (count % 7 == 0) {
printf("\n");
}
}
}
void print_code_stack_in_hex() {
int i, count;
for (i = 0, count = 1; i < code_stack_pos; i++, count++) {
if (code_stack[i] < 0x10) { printf("0"); }
printf("%X ", code_stack[i]);
if (count % 7 == 0) {
printf("\n");
}
}
}