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 :(before "End Op 81 Subops")
168 case 1: {
169 trace(2, "run") << "subop or" << end();
170 BINARY_BITWISE_OP(|, *arg1, arg2);
171 break;
172 }
173
174 :(scenario or_imm32_with_r32)
175 % Reg[3].i = 0xd0c0b0a0;
176
177 81 cb 0a 0b 0c 0d
178 +run: combine imm32 0x0d0c0b0a with effective address
179 +run: effective address is reg 3
180 +run: subop or
181 +run: storing 0xddccbbaa
182
183
184
185 :(scenario xor_imm32_with_eax)
186 % Reg[EAX].i = 0xddccb0a0;
187
188 35 0a 0b 0c 0d
189 +run: xor imm32 0x0d0c0b0a with reg EAX
190 +run: storing 0xd0c0bbaa
191
192 :(before "End Single-Byte Opcodes")
193 case 0x35: {
194 int32_t arg2 = imm32();
195 trace(2, "run") << "xor imm32 0x" << HEXWORD << arg2 << " with reg EAX" << end();
196 BINARY_BITWISE_OP(^, Reg[EAX].i, arg2);
197 break;
198 }
199
200
201
202 :(scenario xor_imm32_with_mem_at_r32)
203 % Reg[3].i = 0x60;
204 % SET_WORD_IN_MEM(0x60, 0xd0c0b0a0);
205
206 81 33 0a 0b 0c 0d
207 +run: combine imm32 0x0d0c0b0a with effective address
208 +run: effective address is mem at address 0x60 (reg 3)
209 +run: subop xor
210 +run: storing 0xddccbbaa
211
212 :(before "End Op 81 Subops")
213 case 6: {
214 trace(2, "run") << "subop xor" << end();
215 BINARY_BITWISE_OP(^, *arg1, arg2);
216 break;
217 }
218
219 :(scenario xor_imm32_with_r32)
220 % Reg[3].i = 0xd0c0b0a0;
221
222 81 f3 0a 0b 0c 0d
223 +run: combine imm32 0x0d0c0b0a with effective address
224 +run: effective address is reg 3
225 +run: subop xor
226 +run: storing 0xddccbbaa
227
228
229
230 :(scenario compare_imm32_with_eax_greater)
231 % Reg[0].i = 0x0d0c0b0a;
232
233 3d 07 0b 0c 0d
234 +run: compare reg EAX and imm32 0x0d0c0b07
235 +run: SF=0; ZF=0; OF=0
236
237 :(before "End Single-Byte Opcodes")
238 case 0x3d: {
239 int32_t arg1 = Reg[EAX].i;
240 int32_t arg2 = imm32();
241 trace(2, "run") << "compare reg EAX and imm32 0x" << HEXWORD << arg2 << end();
242 int32_t tmp1 = arg1 - arg2;
243 SF = (tmp1 < 0);
244 ZF = (tmp1 == 0);
245 int64_t tmp2 = arg1 - arg2;
246 OF = (tmp1 != tmp2);
247 trace(2, "run") << "SF=" << SF << "; ZF=" << ZF << "; OF=" << OF << end();
248 break;
249 }
250
251 :(scenario compare_imm32_with_eax_lesser)
252 % Reg[0].i = 0x0d0c0b07;
253
254 3d 0a 0b 0c 0d
255 +run: compare reg EAX and imm32 0x0d0c0b0a
256 +run: SF=1; ZF=0; OF=0
257
258 :(scenario compare_imm32_with_eax_equal)
259 % Reg[0].i = 0x0d0c0b0a;
260
261 3d 0a 0b 0c 0d
262 +run: compare reg EAX and imm32 0x0d0c0b0a
263 +run: SF=0; ZF=1; OF=0
264
265
266
267 :(scenario compare_imm32_with_r32_greater)
268 % Reg[3].i = 0x0d0c0b0a;
269
270 81 fb 07 0b 0c 0d
271 +run: combine imm32 0x0d0c0b07 with effective address
272 +run: effective address is reg 3
273 +run: SF=0; ZF=0; OF=0
274
275 :(before "End Op 81 Subops")
276 case 7: {
277 trace(2, "run") << "subop compare" << end();
278 int32_t tmp1 = *arg1 - arg2;
279 SF = (tmp1 < 0);
280 ZF = (tmp1 == 0);
281 int64_t tmp2 = *arg1 - arg2;
282 OF = (tmp1 != tmp2);
283 trace(2, "run") << "SF=" << SF << "; ZF=" << ZF << "; OF=" << OF << end();
284 break;
285 }
286
287 :(scenario compare_imm32_with_r32_lesser)
288 % Reg[3].i = 0x0d0c0b07;
289
290 81 fb 0a 0b 0c 0d
291 +run: combine imm32 0x0d0c0b0a with effective address
292 +run: effective address is reg 3
293 +run: SF=1; ZF=0; OF=0
294
295 :(scenario compare_imm32_with_r32_equal)
296 % Reg[3].i = 0x0d0c0b0a;
297
298 81 fb 0a 0b 0c 0d
299 +run: combine imm32 0x0d0c0b0a with effective address
300 +run: effective address is reg 3
301 +run: SF=0; ZF=1; OF=0
302
303 :(scenario compare_imm32_with_mem_at_r32_greater)
304 % Reg[3].i = 0x60;
305 % SET_WORD_IN_MEM(0x60, 0x0d0c0b0a);
306
307 81 3b 07 0b 0c 0d
308 +run: combine imm32 0x0d0c0b07 with effective address
309 +run: effective address is mem at address 0x60 (reg 3)
310 +run: SF=0; ZF=0; OF=0
311
312 :(scenario compare_imm32_with_mem_at_r32_lesser)
313 % Reg[3].i = 0x60;
314 % SET_WORD_IN_MEM(0x60, 0x0d0c0b07);
315
316 81 3b 0a 0b 0c 0d
317 +run: combine imm32 0x0d0c0b0a with effective address
318 +run: effective address is mem at address 0x60 (reg 3)
319 +run: SF=1; ZF=0; OF=0
320
321 :(scenario compare_imm32_with_mem_at_r32_equal)
322 % Reg[3].i = 0x0d0c0b0a;
323 % Reg[3].i = 0x60;
324 % SET_WORD_IN_MEM(0x60, 0x0d0c0b0a);
325
326 81 3b 0a 0b 0c 0d
327 +run: combine imm32 0x0d0c0b0a with effective address
328 +run: effective address is mem at address 0x60 (reg 3)
329 +run: SF=0; ZF=1; OF=0
330
331
332
333 :(scenario copy_imm32_to_r32)
334
335 bb 0a 0b 0c 0d
336 +run: copy imm32 0x0d0c0b0a to reg 3
337
338 :(before "End Single-Byte Opcodes")
339 case 0xb8:
340 case 0xb9:
341 case 0xba:
342 case 0xbb:
343 case 0xbc:
344 case 0xbd:
345 case 0xbe:
346 case 0xbf: {
347 uint8_t reg1 = op & 0x7;
348 int32_t arg2 = imm32();
349 trace(2, "run") << "copy imm32 0x" << HEXWORD << arg2 << " to reg " << NUM(reg1) << end();
350 Reg[reg1].i = arg2;
351 break;
352 }
353
354
355
356 :(scenario copy_imm32_to_mem_at_r32)
357 % Reg[3].i = 0x60;
358
359 c7 03 0a 0b 0c 0d
360 +run: copy imm32 0x0d0c0b0a to effective address
361 +run: effective address is mem at address 0x60 (reg 3)
362
363 :(before "End Single-Byte Opcodes")
364 case 0xc7: {
365 uint8_t modrm = next();
366 int32_t arg2 = imm32();
367 trace(2, "run") << "copy imm32 0x" << HEXWORD << arg2 << " to effective address" << end();
368 int32_t* arg1 = effective_address(modrm);
369 *arg1 = arg2;
370 break;
371 }
372
373
374
375 :(scenario push_imm32)
376 % Reg[ESP].u = 0x14;
377
378 68 af 00 00 00
379 +run: push imm32 0x000000af
380 +run: ESP is now 0x00000010
381 +run: contents at ESP: 0x000000af
382
383 :(before "End Single-Byte Opcodes")
384 case 0x68: {
385 int32_t val = imm32();
386 trace(2, "run") << "push imm32 0x" << HEXWORD << val << end();
387 Reg[ESP].u -= 4;
388 *reinterpret_cast<uint32_t*>(&Mem.at(Reg[ESP].u)) = val;
389 trace(2, "run") << "ESP is now 0x" << HEXWORD << Reg[ESP].u << end();
390 trace(2, "run") << "contents at ESP: 0x" << HEXWORD << *reinterpret_cast<uint32_t*>(&Mem.at(Reg[ESP].u)) << end();
391 break;
392 }