-
Notifications
You must be signed in to change notification settings - Fork 0
/
asm.h
376 lines (314 loc) · 13.8 KB
/
asm.h
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
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
#ifndef ASM_H
#define ASM_H
#include <stddef.h>
#include <inttypes.h>
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint8_t u8;
typedef int16_t i16;
typedef int32_t i32;
typedef int8_t i8;
#define c_byte(b) *LOC++ = b
#define c_word(b) do { *((u16*)LOC) = (b); LOC += 2; } while(0)
#define c_dword(b) do { *((u32*)LOC) = (b); LOC += 4; } while(0)
#define EAX (0)
#define ECX (1)
#define EDX (2)
#define EBX (3)
#define ESP (4)
#define EBP (5)
#define ESI (6)
#define EDI (7)
#define R8D (8)
#define R9D (9)
#define R10D (10)
#define R11D (11)
#define R12D (12)
#define R13D (13)
#define R14D (14)
#define R15D (15)
#define RAX (0)
#define RCX (1)
#define RDX (2)
#define RBX (3)
#define RSP (4)
#define RBP (5)
#define RSI (6)
#define RDI (7)
#define R8 (8)
#define R9 (9)
#define R10 (10)
#define R11 (11)
#define R12 (12)
#define R13 (13)
#define R14 (14)
#define R15 (15)
#define AL (0)
#define CL (1)
#define DL (2)
#define BL (3)
#define AH (4)
#define CH (5)
#define DH (6)
#define BH (7)
#define R8B (8)
#define R9B (9)
#define R10B (10)
#define R11B (11)
#define R12B (12)
#define R13B (13)
#define R14B (14)
#define R15B (15)
#define AX (0)
#define CX (1)
#define DX (2)
#define BX (3)
#define SP (4)
#define BP (5)
#define SI (6)
#define DI (7)
#define R8W (8)
#define R9W (9)
#define R10W (10)
#define R11W (11)
#define R12W (12)
#define R13W (13)
#define R14W (14)
#define R15W (15)
#define RMASK (0x7)
#define RM_EAX (0)
#define RM_ECX (1)
#define RM_EDX (2)
#define RM_EBX (3)
#define RM_EBP (5)
#define RM_ESI (6)
#define RM_EDI (7)
#define RM_RAX (0)
#define RM_RCX (1)
#define RM_RDX (2)
#define RM_RBX (3)
#define RM_RBP (5)
#define RM_RSI (6)
#define RM_RDI (7)
#define RM_SIB (4)
// c_sib(SIBR_DISP, ...)
#define SIBR_DISP (5)
#define SIBMOD_DISP32 (0)
#define MOD_M (0)
#define MOD_MD8 (1)
#define MOD_MD32 (2)
#define MOD_R (3)
#define SS_1 (0)
#define SS_2 (1)
#define SS_4 (2)
#define SS_8 (3)
#define X86_ADD8_R (0x00)
#define X86_ADD_R (0x01)
#define X86_ADD8 (0x02)
#define X86_ADD (0x03)
#define X86_ADC8_R (0x10)
#define X86_ADC_R (0x11)
#define X86_ADC8 (0x12)
#define X86_ADC (0x13)
#define X86_SBB8_R (0x18)
#define X86_SBB_R (0x19)
#define X86_SBB8 (0x1A)
#define X86_SBB (0x1B)
#define X86_SUB8_R (0x28)
#define X86_SUB_R (0x29)
#define X86_SUB8 (0x2A)
#define X86_SUB (0x2B)
#define X86_XOR8_R (0x30)
#define X86_XOR_R (0x31)
#define X86_XOR8 (0x32)
#define X86_XOR (0x33)
#define X86_CMP8_R (0x38)
#define X86_CMP_R (0x39)
#define X86_CMP8 (0x3A)
#define X86_CMP (0x3B)
#define X86_TEST8 (0x84)
#define X86_TEST (0x85)
#define X86_MOV8 (0x8A)
#define X86_MOV (0x8B)
#define X86_MOV8_R (0x88)
#define X86_MOV_R (0x89)
#define X86_RETN (0xC3)
#define X86_CALLREL (0xE8)
#define JCND_JZ (0x74)
#define JCND_JNZ (0x75)
#define JCND_JBE (0x76)
#define REX(r, b, x, w) (0x40 + (b) + 2*(x) + 4*(r) + 8*(w))
#define c_rex(r, b, x, w) do { \
u8 _rex = REX(r,b,x,w); \
if(_rex != 0x40) c_byte(_rex); \
} while(0)
#define c_check_index(index) do { assert(index != RSP); } while(0)
// r, [b + x*...]
// r, b
#define c_rex_for(r, b, x, w) c_rex((r)>>3, (b)>>3, (x)>>3, w)
#define c_wide() c_byte(REX(0, 0, 0, 1))
// For mod != MOD_R, rm cannot be ESP/RSP (RM_SIB replaces ESP/RSP)
#define c_modrm(mod, r, rm) c_byte(((mod)<<6)+((r)<<3)+(rm))
// index uses register constants
#define c_sib(base, index, ss) c_byte(((ss)<<6)+((index)<<3)+(base))
#define c_modm(r, rm) c_modrm(MOD_M, (r)&RMASK, (rm)&RMASK)
#define c_modr(rd, rs) c_modrm(MOD_R, (rd)&RMASK, (rs)&RMASK)
#define c_modm_d8(r, rm, d) do { c_modrm(MOD_MD8, (r)&RMASK, (rm)&RMASK); c_byte(d); } while(0)
#define c_modm_d32(r, rm, d) do { c_modrm(MOD_MD32, (r)&RMASK, (rm)&RMASK); c_dword(d); } while(0)
#define c_modmq(r, rm) c_modm(r, rm)
#define c_modrq(rd, rs) c_modr(rd, rs)
#define c_modmq_d8(r, rm, d) c_modm_d8(r, rm, d)
#define c_modmq_d32(r, rm, d) c_modm_d32(r, rm, d)
#define c_modexm(rm) c_modm(REXT, rm)
#define c_modexr(rs) c_modr(REXT, rs)
#define c_modexm_d8(rm, d) c_modm_d8(REXT, rm, d)
#define c_modexm_d32(rm, d) c_modm_d32(REXT, rm, d)
#define c_modexmq(rm) c_modmq(REXT, rm)
#define c_modexrq(rs) c_modrq(REXT, rs)
#define c_modexmq_d8(rm, d) c_modmq_d8(REXT, rm, d)
#define c_modexmq_d32(rm, d) c_modmq_d32(REXT, rm, d)
#define c_rex_modm(r, rm) c_rex_for(r, rm, 0, 0)
#define c_rex_modr(rd, rs) c_rex_for(rd, rs, 0, 0)
#define c_rex_modm_d8(r, rm, d) c_rex_for(r, rm, 0, 0)
#define c_rex_modm_d32(r, rm, d) c_rex_for(r, rm, 0, 0)
#define c_rex_modmq(r, rm) c_rex_for(r, rm, 0, 1)
#define c_rex_modrq(rd, rs) c_rex_for(rd, rs, 0, 1)
#define c_rex_modmq_d8(r, rm, d) c_rex_for(r, rm, 0, 1)
#define c_rex_modmq_d32(r, rm, d) c_rex_for(r, rm, 0, 1)
#define c_rex_modexm(rm) c_rex_for(0, rm, 0, 0)
#define c_rex_modexr(rs) c_rex_for(0, rs, 0, 0)
#define c_rex_modexm_d8(rm, d) c_rex_for(0, rm, 0, 0)
#define c_rex_modexm_d32(rm, d) c_rex_for(0, rm, 0, 0)
#define c_rex_modexmq(rm) c_rex_for(0, rm, 0, 1)
#define c_rex_modexrq(rs) c_rex_for(0, rs, 0, 1)
#define c_rex_modexmq_d8(rm, d) c_rex_for(0, rm, 0, 1)
#define c_rex_modexmq_d32(rm, d) c_rex_for(0, rm, 0, 1)
// index cannot be RSP/ESP
// r, [base + index*ss + ...]
#define c_modm_sib(r, base, index, ss) do { \
c_check_index(index); \
if((base) == SIBR_DISP) { \
/* Must encode with a zero-offset */ \
c_modrm(MOD_MD8, (r)&RMASK, RM_SIB); c_sib((base)&RMASK, (index)&RMASK, (ss)); c_byte(0); \
} else { \
c_modrm(MOD_M, (r)&RMASK, RM_SIB); c_sib((base)&RMASK, (index)&RMASK, (ss)); \
} \
} while(0)
// r, [base + index*ss + d]
#define c_modm_sib_d8(r, base, index, ss, d) do { c_check_index(index); c_modrm(MOD_MD8, (r)&RMASK, RM_SIB); c_sib((base)&RMASK, (index)&RMASK, ss); c_byte(d); } while(0)
// r, [base + index*ss + d]
#define c_modm_sib_d32(r, base, index, ss, d) do { c_check_index(index); c_modrm(MOD_MD32, (r)&RMASK, RM_SIB); c_sib((base)&RMASK, (index)&RMASK, ss); c_dword(d); } while(0)
// r, [index*ss + d]
#define c_modm_si_d32(r, index, ss, d) do { c_modrm(SIBMOD_DISP32, (r)&RMASK, RM_SIB); c_sib(SIBR_DISP, (index)&RMASK, ss); c_dword(d); } while(0)
#define c_modexm_sib(base, index, ss) c_modm_sib(REXT, base, index, ss)
#define c_modexm_sib_d8(base, index, ss, d) c_modm_sib_d8(REXT, base, index, ss, d)
#define c_modexm_sib_d32(base, index, ss, d) c_modm_sib_d32(REXT, base, index, ss, d)
#define c_modexm_si_d32(index, ss,d ) c_modm_si_d32(REXT, index, ss, d)
#define c_modmq_sib(r, base, index, ss) c_modm_sib(r, base, index, ss)
#define c_modmq_sib_d8(r, base, index, ss, d) c_modm_sib_d8(r, base, index, ss)
#define c_modmq_sib_d32(r, base, index, ss, d) c_modm_sib_d32(r, base, index, ss)
#define c_modmq_si_d32(r, index, ss, d) c_modm_si_d32(r, index, ss)
#define c_rex_modm_sib(r, base, index, ss) c_rex_for(r, base, index, 0)
#define c_rex_modm_sib_d8(r, base, index, ss, d) c_rex_for(r, base, index, 0)
#define c_rex_modm_sib_d32(r, base, index, ss, d) c_rex_for(r, base, index, 0)
#define c_rex_modm_si_d32(r, index, ss, d) c_rex_for(r, 0, index, 0)
#define c_rex_modmq_sib(r, base, index, ss) c_rex_for(r, base, index, 1)
#define c_rex_modmq_sib_d8(r, base, index, ss, d) c_rex_for(r, base, index, 1)
#define c_rex_modmq_sib_d32(r, base, index, ss, d) c_rex_for(r, base, index, 1)
#define c_rex_modmq_si_d32(r, index, ss, d) c_rex_for(r, 0, index, 1)
#define c_rex_modexm_sib(base, index, ss) c_rex_for(0, base, index, 0)
#define c_rex_modexm_sib_d8(base, index, ss, d) c_rex_for(0, base, index, 0)
#define c_rex_modexm_sib_d32(base, index, ss, d) c_rex_for(0, base, index, 0)
#define c_rex_modexm_si_d32(index, ss, d) c_rex_for(0, 0, index, 0)
#define c_rex_modexmq_sib(base, index, ss) c_rex_for(0, base, index, 1)
#define c_rex_modexmq_sib_d8(base, index, ss, d) c_rex_for(0, base, index, 1)
#define c_rex_modexmq_sib_d32(base, index, ss, d) c_rex_for(0, base, index, 1)
#define c_rex_modexmq_si_d32(index, ss, d) c_rex_for(0, 0, index, 1)
#define c_adsize() c_byte(0x67)
#define c_opsize() c_byte(0x66)
#define c_op16 c_opsize
// _r: reverse (destination is memory)
// _k: literal
#define c_movzx_b(modrm) do { c_rex_mod##modrm; c_word(0xB60F); c_mod##modrm; } while(0)
#define c_movzx_w(modrm) do { c_rex_mod##modrm; c_word(0xB70F); c_mod##modrm; } while(0)
#define c_1b_modrm(b, modrm) do { c_rex_mod##modrm; c_byte(b); c_mod##modrm; } while(0)
#define c_mov(modrm) c_1b_modrm(X86_MOV, modrm)
#define c_mov16(modrm) do { c_op16(); c_1b_modrm(X86_MOV, modrm); } while(0)
#define c_mov8(modrm) c_1b_modrm(X86_MOV8, modrm)
#define c_mov_r(modrm) c_1b_modrm(X86_MOV_R, modrm)
#define c_mov16_r(modrm) do { c_op16(); c_1b_modrm(X86_MOV_R, modrm); } while(0)
#define c_mov8_r(modrm) c_1b_modrm(X86_MOV8_R, modrm)
#define c_add(modrm) c_1b_modrm(X86_ADD, modrm)
#define c_add16(modrm) do { c_op16(); c_1b_modrm(X86_ADD, modrm); } while(0)
#define c_add8(modrm) c_1b_modrm(X86_ADD8, modrm)
#define c_add_r(modrm) c_1b_modrm(X86_ADD_R, modrm)
#define c_add16_r(modrm) do { c_op16(); c_1b_modrm(X86_ADD_R, modrm); } while(0)
#define c_add8_r(modrm) c_1b_modrm(X86_ADD8_R, modrm)
#define c_adc(modrm) c_1b_modrm(X86_ADC, modrm)
#define c_adc16(modrm) do { c_op16(); c_1b_modrm(X86_ADC, modrm); } while(0)
#define c_adc8(modrm) c_1b_modrm(X86_ADC8, modrm)
#define c_adc_r(modrm) c_1b_modrm(X86_ADC_R, modrm)
#define c_adc16_r(modrm) do { c_op16(); c_1b_modrm(X86_ADC_R, modrm); } while(0)
#define c_adc8_r(modrm) c_1b_modrm(X86_ADC8_R, modrm)
#define c_sbb(modrm) c_1b_modrm(X86_SBB, modrm)
#define c_sbb16(modrm) do { c_op16(); c_1b_modrm(X86_SBB, modrm); } while(0)
#define c_sbb8(modrm) c_1b_modrm(X86_SBB8, modrm)
#define c_sbb_r(modrm) c_1b_modrm(X86_SBB_R, modrm)
#define c_sbb16_r(modrm) do { c_op16(); c_1b_modrm(X86_SBB_R, modrm); } while(0)
#define c_sbb8_r(modrm) c_1b_modrm(X86_SBB8_R, modrm)
#define c_sub(modrm) c_1b_modrm(X86_SUB, modrm)
#define c_sub16(modrm) do { c_op16(); c_1b_modrm(X86_SUB, modrm); } while(0)
#define c_sub8(modrm) c_1b_modrm(X86_SUB8, modrm)
#define c_sub_r(modrm) c_1b_modrm(X86_SUB_R, modrm)
#define c_sub16_r(modrm) do { c_op16(); c_1b_modrm(X86_SUB_R, modrm); } while(0)
#define c_sub8_r(modrm) c_1b_modrm(X86_SUB8_R, modrm)
#define c_xor(modrm) c_1b_modrm(X86_XOR, modrm)
#define c_xor16(modrm) do { c_op16(); c_1b_modrm(X86_XOR, modrm); } while(0)
#define c_xor8(modrm) c_1b_modrm(X86_XOR8, modrm)
#define c_xor_r(modrm) c_1b_modrm(X86_XOR_R, modrm)
#define c_xor16_r(modrm) do { c_op16(); c_1b_modrm(X86_XOR_R, modrm); } while(0)
#define c_xor8_r(modrm) c_1b_modrm(X86_XOR8_R, modrm)
#define c_cmp(modrm) c_1b_modrm(X86_CMP, modrm)
#define c_cmp16(modrm) do { c_op16(); c_1b_modrm(X86_CMP, modrm); } while(0)
#define c_cmp8(modrm) c_1b_modrm(X86_CMP8, modrm)
#define c_cmp_r(modrm) c_1b_modrm(X86_CMP_R, modrm)
#define c_cmp16_r(modrm) do { c_op16(); c_1b_modrm(X86_CMP_R, modrm); } while(0)
#define c_cmp8_r(modrm) c_1b_modrm(X86_CMP8_R, modrm)
#define c_test(modrm) c_1b_modrm(X86_TEST, modrm)
#define c_test8(modrm) c_1b_modrm(X86_TEST8, modrm)
#define c_retn() c_byte(X86_RETN)
#define c_callrel(p) do { c_byte(X86_CALLREL); c_dword((u8*)p - (LOC + 4)); } while(0)
#define c_push_q(r) do { u32 _r = (r); c_rex_for(0, _r, 0, 0); c_byte(0x50 + (_r&RMASK)); } while(0)
#define c_pop_q(r) do { u32 _r = (r); c_rex_for(0, _r, 0, 0); c_byte(0x58 + (_r&RMASK)); } while(0)
#define c_mov_k(r, k) do { u32 _r = (r); c_rex_for(0, _r, 0, 0); c_byte(0xB8 + (_r&RMASK)); c_dword(k); } while(0)
#define c_add_k8(modrm, k8) do { u32 REXT = 0; c_rex_modex##modrm; c_byte(0x83); c_modex##modrm; c_byte(k8); } while(0)
#define c_or_k8(modrm, k8) do { u32 REXT = 1; c_rex_modex##modrm; c_byte(0x83); c_modex##modrm; c_byte(k8); } while(0)
#define c_cmp8_k(modrm, k8) do { u32 REXT = 7; c_rex_modex##modrm; c_byte(0x80); c_modex##modrm; c_byte(k8); } while(0)
#define c_add16_k(modrm, k16) do { u32 REXT = 0; c_op16(); c_rex_modex##modrm; c_byte(0x81); c_modex##modrm; c_word(k16); } while(0)
#define c_sub16_k(modrm, k16) do { u32 REXT = 5; c_op16(); c_rex_modex##modrm; c_byte(0x81); c_modex##modrm; c_word(k16); } while(0)
#define c_cmp16_k(modrm, k16) do { u32 REXT = 7; c_op16(); c_rex_modex##modrm; c_byte(0x81); c_modex##modrm; c_word(k16); } while(0)
#define c_mov16_k(modrm, k16) do { u32 REXT = 0; c_op16(); c_rex_modex##modrm; c_byte(0xC7); c_modex##modrm; c_word(k16); } while(0)
#define c_inc16(modrm) do { u32 REXT = 0; c_op16(); c_rex_modex##modrm; c_byte(0xFF); c_modex##modrm; } while(0)
#define c_dec16(modrm) do { u32 REXT = 1; c_op16(); c_rex_modex##modrm; c_byte(0xFF); c_modex##modrm; } while(0)
#define c_jmp_ind(modrm) do { u32 REXT = 4; c_rex_modex##modrm; c_byte(0xFF); c_modex##modrm; } while(0)
#define c_jz8(o) do { c_byte(0x74); c_byte(o); } while(0)
#define c_jnz8(o) do { c_byte(0x75); c_byte(o); } while(0)
#define c_jbe8(o) do { c_byte(0x76); c_byte(o); } while(0)
#define c_jz(o) do { c_word(0x840F); c_dword(o); } while(0)
#define c_jnz(o) do { c_byte(0x850F); c_dword(o); } while(0)
#define c_jbe(o) do { c_byte(0x860F); c_dword(o); } while(0)
#define c_label8(l) do { ((i8*)(l))[-1] = (LOC - (l)); } while(0)
#define c_label32(l) do { ((i32*)(l))[-1] = (LOC - (l)); } while(0)
#define c_jcnd_far(cnd, pos) do { c_word(0x100F + ((cnd) << 8)); c_dword((u8*)(pos) - (LOC + 4)); } while(0)
#define c_jmp_far(pos) do { c_byte(0xE9); c_dword((u8*)(pos) - (LOC + 4)); } while(0)
#define c_jmp(pos) do { \
u8* _pos = (u8*)(pos); \
ptrdiff_t _diff = ((u8*)(pos) - (LOC + 2)); \
if(_diff >= -128 && _diff <= 127) { \
c_byte(0xEB); c_byte(_diff); \
} else { \
c_byte(0xE9); c_dword(_diff - 3); \
} \
} while(0)
void* mcode_alloc(size_t sz, int prot);
#endif // ASM_H