1
2
3 :(before "End Initialize Op Names(name)")
4 put(name, "81", "combine rm32 with imm32 based on subop");
5
6 :(scenario add_imm32_to_r32)
7 % Reg[EBX].i = 1;
8 == 0x1
9
10 81 c3 0a 0b 0c 0d
11
12 +run: combine imm32 0x0d0c0b0a with r/m32
13 +run: r/m32 is EBX
14 +run: subop add
15 +run: storing 0x0d0c0b0b
16
17 :(before "End Single-Byte Opcodes")
18 case 0x81: {
19 uint8_t modrm = next();
20 int32_t arg2 = imm32();
21 trace(90, "run") << "combine imm32 0x" << HEXWORD << arg2 << " with r/m32" << end();
22 int32_t* arg1 = effective_address(modrm);
23 uint8_t subop = (modrm>>3)&0x7;
24 switch (subop) {
25 case 0:
26 trace(90, "run") << "subop add" << end();
27 BINARY_ARITHMETIC_OP(+, *arg1, arg2);
28 break;
29
30 default:
31 cerr << "unrecognized sub-opcode after 81: " << NUM(subop) << '\n';
32 exit(1);
33 }
34 break;
35 }
36
37
38
39 :(scenario add_imm32_to_mem_at_r32)
40 % Reg[EBX].i = 0x60;
41 == 0x01
42
43 81 03 0a 0b 0c 0d
44
45 == 0x60
46 01 00 00 00
47 +run: combine imm32 0x0d0c0b0a with r/m32
48 +run: effective address is 0x60 (EBX)
49 +run: subop add
50 +run: storing 0x0d0c0b0b
51
52
53
54 :(before "End Initialize Op Names(name)")
55 put(name, "2d", "subtract imm32 from R0 (EAX)");
56
57 :(scenario subtract_imm32_from_eax)
58 % Reg[EAX].i = 0x0d0c0baa;
59 == 0x1
60
61 2d 0a 0b 0c 0d
62 +run: subtract imm32 0x0d0c0b0a from EAX
63 +run: storing 0x000000a0
64
65 :(before "End Single-Byte Opcodes")
66 case 0x2d: {
67 int32_t arg2 = imm32();
68 trace(90, "run") << "subtract imm32 0x" << HEXWORD << arg2 << " from EAX" << end();
69 BINARY_ARITHMETIC_OP(-, Reg[EAX].i, arg2);
70 break;
71 }
72
73
74
75 :(scenario subtract_imm32_from_mem_at_r32)
76 % Reg[EBX].i = 0x60;
77 == 0x01
78
79 81 2b 01 00 00 00
80
81 == 0x60
82 0a 00 00 00
83 +run: combine imm32 0x00000001 with r/m32
84 +run: effective address is 0x60 (EBX)
85 +run: subop subtract
86 +run: storing 0x00000009
87
88 :(before "End Op 81 Subops")
89 case 5: {
90 trace(90, "run") << "subop subtract" << end();
91 BINARY_ARITHMETIC_OP(-, *arg1, arg2);
92 break;
93 }
94
95
96
97 :(scenario subtract_imm32_from_r32)
98 % Reg[EBX].i = 10;
99 == 0x1
100
101 81 eb 01 00 00 00
102
103 +run: combine imm32 0x00000001 with r/m32
104 +run: r/m32 is EBX
105 +run: subop subtract
106 +run: storing 0x00000009
107
108
109
110 :(before "End Initialize Op Names(name)")
111 put(name, "25", "R0 = bitwise AND of imm32 with R0 (EAX)");
112
113 :(scenario and_imm32_with_eax)
114 % Reg[EAX].i = 0xff;
115 == 0x1
116
117 25 0a 0b 0c 0d
118 +run: and imm32 0x0d0c0b0a with EAX
119 +run: storing 0x0000000a
120
121 :(before "End Single-Byte Opcodes")
122 case 0x25: {
123 int32_t arg2 = imm32();
124 trace(90, "run") << "and imm32 0x" << HEXWORD << arg2 << " with EAX" << end();
125 BINARY_BITWISE_OP(&, Reg[EAX].i, arg2);
126 break;
127 }
128
129
130
131 :(scenario and_imm32_with_mem_at_r32)
132 % Reg[EBX].i = 0x60;
133 == 0x01
134
135 81 23 0a 0b 0c 0d
136
137 == 0x60
138 ff 00 00 00
139 +run: combine imm32 0x0d0c0b0a with r/m32
140 +run: effective address is 0x60 (EBX)
141 +run: subop and
142 +run: storing 0x0000000a
143
144 :(before "End Op 81 Subops")
145 case 4: {
146 trace(90, "run") << "subop and" << end();
147 BINARY_BITWISE_OP(&, *arg1, arg2);
148 break;
149 }
150
151
152
153 :(scenario and_imm32_with_r32)
154 % Reg[EBX].i = 0xff;
155 == 0x1
156
157 81 e3 0a 0b 0c 0d
158
159 +run: combine imm32 0x0d0c0b0a with r/m32
160 +run: r/m32 is EBX
161 +run: subop and
162 +run: storing 0x0000000a
163
164
165
166 :(before "End Initialize Op Names(name)")
167 put(name, "0d", "R0 = bitwise OR of imm32 with R0 (EAX)");
168
169 :(scenario or_imm32_with_eax)
170 % Reg[EAX].i = 0xd0c0b0a0;
171 == 0x1
172
173 0d 0a 0b 0c 0d
174 +run: or imm32 0x0d0c0b0a with EAX
175 +run: storing 0xddccbbaa
176
177 :(before "End Single-Byte Opcodes")
178 case 0x0d: {
179 int32_t arg2 = imm32();
180 trace(90, "run") << "or imm32 0x" << HEXWORD << arg2 << " with EAX" << end();
181 BINARY_BITWISE_OP(|, Reg[EAX].i, arg2);
182 break;
183 }
184
185
186
187 :(scenario or_imm32_with_mem_at_r32)
188 % Reg[EBX].i = 0x60;
189 == 0x01
190
191 81 0b 0a 0b 0c 0d
192
193 == 0x60
194 a0 b0 c0 d0
195 +run: combine imm32 0x0d0c0b0a with r/m32
196 +run: effective address is 0x60 (EBX)
197 +run: subop or
198 +run: storing 0xddccbbaa
199
200 :(before "End Op 81 Subops")
201 case 1: {
202 trace(90, "run") << "subop or" << end();
203 BINARY_BITWISE_OP(|, *arg1, arg2);
204 break;
205 }
206
207 :(scenario or_imm32_with_r32)
208 % Reg[EBX].i = 0xd0c0b0a0;
209 == 0x1
210
211 81 cb 0a 0b 0c 0d
212
213 +run: combine imm32 0x0d0c0b0a with r/m32
214 +run: r/m32 is EBX
215 +run: subop or
216 +run: storing 0xddccbbaa
217
218
219
220 :(before "End Initialize Op Names(name)")
221 put(name, "35", "R0 = bitwise XOR of imm32 with R0 (EAX)");
222
223 :(scenario xor_imm32_with_eax)
224 % Reg[EAX].i = 0xddccb0a0;
225 == 0x1
226
227 35 0a 0b 0c 0d
228 +run: xor imm32 0x0d0c0b0a with EAX
229 +run: storing 0xd0c0bbaa
230
231 :(before "End Single-Byte Opcodes")
232 case 0x35: {
233 int32_t arg2 = imm32();
234 trace(90, "run") << "xor imm32 0x" << HEXWORD << arg2 << " with EAX" << end();
235 BINARY_BITWISE_OP(^, Reg[EAX].i, arg2);
236 break;
237 }
238
239
240
241 :(scenario xor_imm32_with_mem_at_r32)
242 % Reg[EBX].i = 0x60;
243 == 0x01
244
245 81 33 0a 0b 0c 0d
246
247 == 0x60
248 a0 b0 c0 d0
249 +run: combine imm32 0x0d0c0b0a with r/m32
250 +run: effective address is 0x60 (EBX)
251 +run: subop xor
252 +run: storing 0xddccbbaa
253
254 :(before "End Op 81 Subops")
255 case 6: {
256 trace(90, "run") << "subop xor" << end();
257 BINARY_BITWISE_OP(^, *arg1, arg2);
258 break;
259 }
260
261 :(scenario xor_imm32_with_r32)
262 % Reg[EBX].i = 0xd0c0b0a0;
263 == 0x1
264
265 81 f3 0a 0b 0c 0d
266
267 +run: combine imm32 0x0d0c0b0a with r/m32
268 +run: r/m32 is EBX
269 +run: subop xor
270 +run: storing 0xddccbbaa
271
272
273
274 :(before "End Initialize Op Names(name)")
275 put(name, "3d", "subtract imm32 from R0 (EAX)");
276
277 :(scenario compare_imm32_with_eax_greater)
278 % Reg[EAX].i = 0x0d0c0b0a;
279 == 0x1
280
281 3d 07 0b 0c 0d
282 +run: compare EAX and imm32 0x0d0c0b07
283 +run: SF=0; ZF=0; OF=0
284
285 :(before "End Single-Byte Opcodes")
286 case 0x3d: {
287 int32_t arg1 = Reg[EAX].i;
288 int32_t arg2 = imm32();
289 trace(90, "run") << "compare EAX and imm32 0x" << HEXWORD << arg2 << end();
290 int32_t tmp1 = arg1 - arg2;
291 SF = (tmp1 < 0);
292 ZF = (tmp1 == 0);
293 int64_t tmp2 = arg1 - arg2;
294 OF = (tmp1 != tmp2);
295 trace(90, "run") << "SF=" << SF << "; ZF=" << ZF << "; OF=" << OF << end();
296 break;
297 }
298
299 :(scenario compare_imm32_with_eax_lesser)
300 % Reg[EAX].i = 0x0d0c0b07;
301 == 0x1
302
303 3d 0a 0b 0c 0d
304 +run: compare EAX and imm32 0x0d0c0b0a
305 +run: SF=1; ZF=0; OF=0
306
307 :(scenario compare_imm32_with_eax_equal)
308 % Reg[EAX].i = 0x0d0c0b0a;
309 == 0x1
310
311 3d 0a 0b 0c 0d
312 +run: compare EAX and imm32 0x0d0c0b0a
313 +run: SF=0; ZF=1; OF=0
314
315
316
317 :(scenario compare_imm32_with_r32_greater)
318 % Reg[EBX].i = 0x0d0c0b0a;
319 == 0x1
320
321 81 fb 07 0b 0c 0d
322
323 +run: combine imm32 0x0d0c0b07 with r/m32
324 +run: r/m32 is EBX
325 +run: SF=0; ZF=0; OF=0
326
327 :(before "End Op 81 Subops")
328 case 7: {
329 trace(90, "run") << "subop compare" << end();
330 int32_t tmp1 = *arg1 - arg2;
331 SF = (tmp1 < 0);
332 ZF = (tmp1 == 0);
333 int64_t tmp2 = *arg1 - arg2;
334 OF = (tmp1 != tmp2);
335 trace(90, "run") << "SF=" << SF << "; ZF=" << ZF << "; OF=" << OF << end();
336 break;
337 }
338
339 :(scenario compare_imm32_with_r32_lesser)
340 % Reg[EBX].i = 0x0d0c0b07;
341 == 0x1
342
343 81 fb 0a 0b 0c 0d
344
345 +run: combine imm32 0x0d0c0b0a with r/m32
346 +run: r/m32 is EBX
347 +run: SF=1; ZF=0; OF=0
348
349 :(scenario compare_imm32_with_r32_equal)
350 % Reg[EBX].i = 0x0d0c0b0a;
351 == 0x1
352
353 81 fb 0a 0b 0c 0d
354
355 +run: combine imm32 0x0d0c0b0a with r/m32
356 +run: r/m32 is EBX
357 +run: SF=0; ZF=1; OF=0
358
359 :(scenario compare_imm32_with_mem_at_r32_greater)
360 % Reg[EBX].i = 0x60;
361 == 0x01
362
363 81 3b 07 0b 0c 0d
364
365 == 0x60
366 0a 0b 0c 0d
367 +run: combine imm32 0x0d0c0b07 with r/m32
368 +run: effective address is 0x60 (EBX)
369 +run: SF=0; ZF=0; OF=0
370
371 :(scenario compare_imm32_with_mem_at_r32_lesser)
372 % Reg[EBX].i = 0x60;
373 == 0x01
374
375 81 3b 0a 0b 0c 0d
376
377 == 0x60
378 07 0b 0c 0d
379 +run: combine imm32 0x0d0c0b0a with r/m32
380 +run: effective address is 0x60 (EBX)
381 +run: SF=1; ZF=0; OF=0
382
383 :(scenario compare_imm32_with_mem_at_r32_equal)
384 % Reg[EBX].i = 0x0d0c0b0a;
385 % Reg[EBX].i = 0x60;
386 == 0x01
387
388 81 3b 0a 0b 0c 0d
389
390 == 0x60
391 0a 0b 0c 0d
392 +run: combine imm32 0x0d0c0b0a with r/m32
393 +run: effective address is 0x60 (EBX)
394 +run: SF=0; ZF=1; OF=0
395
396
397
398 :(before "End Initialize Op Names(name)")
399 put(name, "b8", "copy imm32 to R0 (EAX)");
400 put(name, "b9", "copy imm32 to R1 (ECX)");
401 put(name, "ba", "copy imm32 to R2 (EDX)");
402 put(name, "bb", "copy imm32 to R3 (EBX)");
403 put(name, "bc", "copy imm32 to R4 (ESP)");
404 put(name, "bd", "copy imm32 to R5 (EBP)");
405 put(name, "be", "copy imm32 to R6 (ESI)");
406 put(name, "bf", "copy imm32 to R7 (EDI)");
407
408 :(scenario copy_imm32_to_r32)
409 == 0x1
410
411 bb 0a 0b 0c 0d
412 +run: copy imm32 0x0d0c0b0a to EBX
413
414 :(before "End Single-Byte Opcodes")
415 case 0xb8:
416 case 0xb9:
417 case 0xba:
418 case 0xbb:
419 case 0xbc:
420 case 0xbd:
421 case 0xbe:
422 case 0xbf: {
423 uint8_t reg1 = op & 0x7;
424 int32_t arg2 = imm32();
425 trace(90, "run") << "copy imm32 0x" << HEXWORD << arg2 << " to " << rname(reg1) << end();
426 Reg[reg1].i = arg2;
427 break;
428 }
429
430
431
432 :(before "End Initialize Op Names(name)")
433 put(name, "c7", "copy imm32 to rm32");
434
435 :(scenario copy_imm32_to_mem_at_r32)
436 % Reg[EBX].i = 0x60;
437 == 0x1
438
439 c7 03 0a 0b 0c 0d
440
441 +run: copy imm32 0x0d0c0b0a to r/m32
442 +run: effective address is 0x60 (EBX)
443
444 :(before "End Single-Byte Opcodes")
445 case 0xc7: {
446 uint8_t modrm = next();
447 int32_t arg2 = imm32();
448 trace(90, "run") << "copy imm32 0x" << HEXWORD << arg2 << " to r/m32" << end();
449 int32_t* arg1 = effective_address(modrm);
450 *arg1 = arg2;
451 break;
452 }
453
454
455
456 :(before "End Initialize Op Names(name)")
457 put(name, "68", "push imm32 to stack");
458
459 :(scenario push_imm32)
460 % Reg[ESP].u = 0x14;
461 == 0x1
462
463 68 af 00 00 00
464 +run: push imm32 0x000000af
465 +run: ESP is now 0x00000010
466 +run: contents at ESP: 0x000000af
467
468 :(before "End Single-Byte Opcodes")
469 case 0x68: {
470 uint32_t val = static_cast<uint32_t>(imm32());
471 trace(90, "run") << "push imm32 0x" << HEXWORD << val << end();
472
473 push(val);
474 trace(90, "run") << "ESP is now 0x" << HEXWORD << Reg[ESP].u << end();
475 trace(90, "run") << "contents at ESP: 0x" << HEXWORD << read_mem_u32(Reg[ESP].u) << end();
476 break;
477 }