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