1
2
3 :(scenario add_imm32_to_r32)
4 % Reg[3].i = 1;
5
6 81 c3 0a 0b 0c 0d
7 +run: combine imm32 0x0d0c0b0a with effective address
8 +run: effective address is reg 3
9 +run: subop add
10 +run: storing 0x0d0c0b0b
11
12 :(before "End Single-Byte Opcodes")
13 case 0x81: {
14 uint8_t modrm = next();
15 int32_t arg2 = imm32();
16 trace(2, "run") << "combine imm32 0x" << HEXWORD << arg2 << " with effective address" << end();
17 int32_t* arg1 = effective_address(modrm);
18 uint8_t subop = (modrm>>3)&0x7;
19 switch (subop) {
20 case 0:
21 ¦ trace(2, "run") << "subop add" << end();
22 ¦ BINARY_ARITHMETIC_OP(+, *arg1, arg2);
23 ¦ break;
24
25 default:
26 ¦ cerr << "unrecognized sub-opcode after 81: " << NUM(subop) << '\n';
27 ¦ exit(1);
28 }
29 break;
30 }
31
32
33
34 :(scenario add_imm32_to_mem_at_r32)
35 % Reg[3].i = 0x60;
36 % SET_WORD_IN_MEM(0x60, 1);
37
38 81 03 0a 0b 0c 0d
39 +run: combine imm32 0x0d0c0b0a with effective address
40 +run: effective address is mem at address 0x60 (reg 3)
41 +run: subop add
42 +run: storing 0x0d0c0b0b
43
44
45
46 :(scenario subtract_imm32_from_eax)
47 % Reg[EAX].i = 0x0d0c0baa;
48
49 2d 0a 0b 0c 0d
50 +run: subtract imm32 0x0d0c0b0a from reg EAX
51 +run: storing 0x000000a0
52
53 :(before "End Single-Byte Opcodes")
54 case 0x2d: {
55 int32_t arg2 = imm32();
56 trace(2, "run") << "subtract imm32 0x" << HEXWORD << arg2 << " from reg EAX" << end();
57 BINARY_ARITHMETIC_OP(-, Reg[EAX].i, arg2);
58 break;
59 }
60
61
62
63 :(scenario subtract_imm32_from_mem_at_r32)
64 % Reg[3].i = 0x60;
65 % SET_WORD_IN_MEM(0x60, 10);
66
67 81 2b 01 00 00 00
68 +run: combine imm32 0x00000001 with effective address
69 +run: effective address is mem at address 0x60 (reg 3)
70 +run: subop subtract
71 +run: storing 0x00000009
72
73
74
75 :(scenario subtract_imm32_from_r32)
76 % Reg[3].i = 10;
77
78 81 eb 01 00 00 00
79 +run: combine imm32 0x00000001 with effective address
80 +run: effective address is reg 3
81 +run: subop subtract
82 +run: storing 0x00000009
83
84 :(before "End Op 81 Subops")
85 case 5: {
86 trace(2, "run") << "subop subtract" << end();
87 BINARY_ARITHMETIC_OP(-, *arg1, arg2);
88 break;
89 }
90
91
92
93 :(scenario and_imm32_with_eax)
94 % Reg[EAX].i = 0xff;
95
96 25 0a 0b 0c 0d
97 +run: and imm32 0x0d0c0b0a with reg EAX
98 +run: storing 0x0000000a
99
100 :(before "End Single-Byte Opcodes")
101 case 0x25: {
102 int32_t arg2 = imm32();
103 trace(2, "run") << "and imm32 0x" << HEXWORD << arg2 << " with reg EAX" << end();
104 BINARY_BITWISE_OP(&, Reg[EAX].i, arg2);
105 break;
106 }
107
108
109
110 :(scenario and_imm32_with_mem_at_r32)
111 % Reg[3].i = 0x60;
112 % SET_WORD_IN_MEM(0x60, 0x000000ff);
113
114 81 23 0a 0b 0c 0d
115 +run: combine imm32 0x0d0c0b0a with effective address
116 +run: effective address is mem at address 0x60 (reg 3)
117 +run: subop and
118 +run: storing 0x0000000a
119
120
121
122 :(scenario and_imm32_with_r32)
123 % Reg[3].i = 0xff;
124
125 81 e3 0a 0b 0c 0d
126 +run: combine imm32 0x0d0c0b0a with effective address
127 +run: effective address is reg 3
128 +run: subop and
129 +run: storing 0x0000000a
130
131 :(before "End Op 81 Subops")
132 case 4: {
133 trace(2, "run") << "subop and" << end();
134 BINARY_BITWISE_OP(&, *arg1, arg2);
135 break;
136 }
137
138
139
140 :(scenario or_imm32_with_eax)
141 % Reg[EAX].i = 0xd0c0b0a0;
142
143 0d 0a 0b 0c 0d
144 +run: or imm32 0x0d0c0b0a with reg EAX
145 +run: storing 0xddccbbaa
146
147 :(before "End Single-Byte Opcodes")
148 case 0x0d: {
149 int32_t arg2 = imm32();
150 trace(2, "run") << "or imm32 0x" << HEXWORD << arg2 << " with reg EAX" << end();
151 BINARY_BITWISE_OP(|, Reg[EAX].i, arg2);
152 break;
153 }
154
155
156
157 :(scenario or_imm32_with_mem_at_r32)
158 % Reg[3].i = 0x60;
159 % SET_WORD_IN_MEM(0x60, 0xd0c0b0a0);
160
161 81 0b 0a 0b 0c 0d
162 +run: combine imm32 0x0d0c0b0a with effective address
163 +run: effective address is mem at address 0x60 (reg 3)
164 +run: subop or
165 +run: storing 0xddccbbaa
166
167
168
169 :(scenario or_imm32_with_r32)
170 % Reg[3].i = 0xd0c0b0a0;
171
172 81 cb 0a 0b 0c 0d
173 +run: combine imm32 0x0d0c0b0a with effective address
174 +run: effective address is reg 3
175 +run: subop or
176 +run: storing 0xddccbbaa
177
178 :(before "End Op 81 Subops")
179 case 1: {
180 trace(2, "run") << "subop or" << end();
181 BINARY_BITWISE_OP(|, *arg1, arg2);
182 break;
183 }
184
185
186
187 :(scenario xor_imm32_with_eax)
188 % Reg[EAX].i = 0xddccb0a0;
189
190 35 0a 0b 0c 0d
191 +run: xor imm32 0x0d0c0b0a with reg EAX
192 +run: storing 0xd0c0bbaa
193
194 :(before "End Single-Byte Opcodes")
195 case 0x35: {
196 int32_t arg2 = imm32();
197 trace(2, "run") << "xor imm32 0x" << HEXWORD << arg2 << " with reg EAX" << end();
198 BINARY_BITWISE_OP(^, Reg[EAX].i, arg2);
199 break;
200 }
201
202
203
204 :(scenario xor_imm32_with_mem_at_r32)
205 % Reg[3].i = 0x60;
206 % SET_WORD_IN_MEM(0x60, 0xd0c0b0a0);
207
208 81 33 0a 0b 0c 0d
209 +run: combine imm32 0x0d0c0b0a with effective address
210 +run: effective address is mem at address 0x60 (reg 3)
211 +run: subop xor
212 +run: storing 0xddccbbaa
213
214
215
216 :(scenario xor_imm32_with_r32)
217 % Reg[3].i = 0xd0c0b0a0;
218
219 81 f3 0a 0b 0c 0d
220 +run: combine imm32 0x0d0c0b0a with effective address
221 +run: effective address is reg 3
222 +run: subop xor
223 +run: storing 0xddccbbaa
224
225 :(before "End Op 81 Subops")
226 case 6: {
227 trace(2, "run") << "subop xor" << end();
228 BINARY_BITWISE_OP(^, *arg1, arg2);
229 break;
230 }
231
232
233
234 :(scenario compare_imm32_with_eax_greater)
235 % Reg[0].i = 0x0d0c0b0a;
236
237 3d 07 0b 0c 0d
238 +run: compare reg EAX and imm32 0x0d0c0b07
239 +run: SF=0; ZF=0; OF=0
240
241 :(before "End Single-Byte Opcodes")
242 case 0x3d: {
243 int32_t arg1 = Reg[EAX].i;
244 int32_t arg2 = imm32();
245 trace(2, "run") << "compare reg EAX and imm32 0x" << HEXWORD << arg2 << end();
246 int32_t tmp1 = arg1 - arg2;
247 SF = (tmp1 < 0);
248 ZF = (tmp1 == 0);
249 int64_t tmp2 = arg1 - arg2;
250 OF = (tmp1 != tmp2);
251 trace(2, "run") << "SF=" << SF << "; ZF=" << ZF << "; OF=" << OF << end();
252 break;
253 }
254
255 :(scenario compare_imm32_with_eax_lesser)
256 % Reg[0].i = 0x0d0c0b07;
257
258 3d 0a 0b 0c 0d
259 +run: compare reg EAX and imm32 0x0d0c0b0a
260 +run: SF=1; ZF=0; OF=0
261
262 :(scenario compare_imm32_with_eax_equal)
263 % Reg[0].i = 0x0d0c0b0a;
264
265 3d 0a 0b 0c 0d
266 +run: compare reg EAX and imm32 0x0d0c0b0a
267 +run: SF=0; ZF=1; OF=0
268
269
270
271 :(scenario compare_imm32_with_r32_greater)
272 % Reg[3].i = 0x0d0c0b0a;
273
274 81 fb 07 0b 0c 0d
275 +run: combine imm32 0x0d0c0b07 with effective address
276 +run: effective address is reg 3
277 +run: SF=0; ZF=0; OF=0
278
279 :(before "End Op 81 Subops")
280 case 7: {
281 trace(2, "run") << "subop compare" << end();
282 int32_t tmp1 = *arg1 - arg2;
283 SF = (tmp1 < 0);
284 ZF = (tmp1 == 0);
285 int64_t tmp2 = *arg1 - arg2;
286 OF = (tmp1 != tmp2);
287 trace(2, "run") << "SF=" << SF << "; ZF=" << ZF << "; OF=" << OF << end();
288 break;
289 }
290
291 :(scenario compare_imm32_with_r32_lesser)
292 % Reg[3].i = 0x0d0c0b07;
293
294 81 fb 0a 0b 0c 0d
295 +run: combine imm32 0x0d0c0b0a with effective address
296 +run: effective address is reg 3
297 +run: SF=1; ZF=0; OF=0
298
299 :(scenario compare_imm32_with_r32_equal)
300 % Reg[3].i = 0x0d0c0b0a;
301
302 81 fb 0a 0b 0c 0d
303 +run: combine imm32 0x0d0c0b0a with effective address
304 +run: effective address is reg 3
305 +run: SF=0; ZF=1; OF=0
306
307 :(scenario compare_imm32_with_mem_at_r32_greater)
308 % Reg[3].i = 0x60;
309 % SET_WORD_IN_MEM(0x60, 0x0d0c0b0a);
310
311 81 3b 07 0b 0c 0d
312 +run: combine imm32 0x0d0c0b07 with effective address
313 +run: effective address is mem at address 0x60 (reg 3)
314 +run: SF=0; ZF=0; OF=0
315
316 :(scenario compare_imm32_with_mem_at_r32_lesser)
317 % Reg[3].i = 0x60;
318 % SET_WORD_IN_MEM(0x60, 0x0d0c0b07);
319
320 81 3b 0a 0b 0c 0d
321 +run: combine imm32 0x0d0c0b0a with effective address
322 +run: effective address is mem at address 0x60 (reg 3)
323 +run: SF=1; ZF=0; OF=0
324
325 :(scenario compare_imm32_with_mem_at_r32_equal)
326 % Reg[3].i = 0x0d0c0b0a;
327 % Reg[3].i = 0x60;
328 % SET_WORD_IN_MEM(0x60, 0x0d0c0b0a);
329
330 81 3b 0a 0b 0c 0d
331 +run: combine imm32 0x0d0c0b0a with effective address
332 +run: effective address is mem at address 0x60 (reg 3)
333 +run: SF=0; ZF=1; OF=0
334
335
336
337 :(scenario copy_imm32_to_r32)
338
339 b8 03 0a 0b 0c 0d
340 +run: copy imm32 0x0d0c0b0a to reg 3
341
342 :(before "End Single-Byte Opcodes")
343 case 0xb8: {
344 uint8_t modrm = next();
345 int32_t arg2 = imm32();
346 uint8_t reg1 = modrm&0x7;
347 trace(2, "run") << "copy imm32 0x" << HEXWORD << arg2 << " to reg " << NUM(reg1) << end();
348 Reg[reg1].i = arg2;
349 break;
350 }
351
352
353 :(scenario copy_imm32_to_mem_at_r32)
354 % Reg[3].i = 0x60;
355
356 c7 03 0a 0b 0c 0d
357 +run: copy imm32 0x0d0c0b0a to effective address
358 +run: effective address is mem at address 0x60 (reg 3)
359
360 :(before "End Single-Byte Opcodes")
361 case 0xc7: {
362 uint8_t modrm = next();
363 int32_t arg2 = imm32();
364 trace(2, "run") << "copy imm32 0x" << HEXWORD << arg2 << " to effective address" << end();
365 int32_t* arg1 = effective_address(modrm);
366 *arg1 = arg2;
367 break;
368 }
369
370
371
372 :(scenario jump_rel8)
373
374 eb 05
375 05 00 00 00 01
376 05 00 00 00 02
377 +run: inst: 0x00000001
378 +run: jump 5
379 +run: inst: 0x00000008
380 -run: inst: 0x00000003
381
382 :(before "End Single-Byte Opcodes")
383 case 0xeb: {
384 int8_t offset = static_cast<int>(next());
385 trace(2, "run") << "jump " << NUM(offset) << end();
386 EIP += offset;
387 break;
388 }
389
390
391
392 :(scenario jump_rel16)
393
394 e9 05 00
395 05 00 00 00 01
396 05 00 00 00 02
397 +run: inst: 0x00000001
398 +run: jump 5
399 +run: inst: 0x00000009
400 -run: inst: 0x00000003
401
402 :(before "End Single-Byte Opcodes")
403 case 0xe9: {
404 int16_t offset = imm16();
405 trace(2, "run") << "jump " << offset << end();
406 EIP += offset;
407 break;
408 }
409 :(code)
410 int16_t imm16() {
411 int16_t result = next();
412 result |= (next()<<8);
413 return result;
414 }