1
2
3 :(scenario add_r32_to_mem_at_r32)
4 % Reg[3].i = 0x10;
5 % Reg[0].i = 0x60;
6 % SET_WORD_IN_MEM(0x60, 1);
7
8 01 18
9 +run: add reg 3 to effective address
10 +run: effective address is mem at address 0x60 (reg 0)
11 +run: storing 0x00000011
12
13 :(before "End Mod Special-cases")
14 case 0:
15
16 switch (rm) {
17 default:
18 ¦ trace(2, "run") << "effective address is mem at address 0x" << std::hex << Reg[rm].u << " (reg " << NUM(rm) << ")" << end();
19 ¦ assert(Reg[rm].u + sizeof(int32_t) <= Mem.size());
20 ¦ result = reinterpret_cast<int32_t*>(&Mem.at(Reg[rm].u));
21 ¦ break;
22
23 }
24 break;
25
26
27
28 :(scenario add_mem_at_r32_to_r32)
29 % Reg[0].i = 0x60;
30 % Reg[3].i = 0x10;
31 % SET_WORD_IN_MEM(0x60, 1);
32
33 03 18
34 +run: add effective address to reg 3
35 +run: effective address is mem at address 0x60 (reg 0)
36 +run: storing 0x00000011
37
38 :(before "End Single-Byte Opcodes")
39 case 0x03: {
40 uint8_t modrm = next();
41 uint8_t arg1 = (modrm>>3)&0x7;
42 trace(2, "run") << "add effective address to reg " << NUM(arg1) << end();
43 const int32_t* arg2 = effective_address(modrm);
44 BINARY_ARITHMETIC_OP(+, Reg[arg1].i, *arg2);
45 break;
46 }
47
48
49
50 :(scenario subtract_r32_from_mem_at_r32)
51 % Reg[0].i = 0x60;
52 % SET_WORD_IN_MEM(0x60, 10);
53 % Reg[3].i = 1;
54
55 29 18
56 +run: subtract reg 3 from effective address
57 +run: effective address is mem at address 0x60 (reg 0)
58 +run: storing 0x00000009
59
60
61
62 :(scenario subtract_mem_at_r32_from_r32)
63 % Reg[0].i = 0x60;
64 % SET_WORD_IN_MEM(0x60, 1);
65 % Reg[3].i = 10;
66
67 2b 18
68 +run: subtract effective address from reg 3
69 +run: effective address is mem at address 0x60 (reg 0)
70 +run: storing 0x00000009
71
72 :(before "End Single-Byte Opcodes")
73 case 0x2b: {
74 uint8_t modrm = next();
75 uint8_t arg1 = (modrm>>3)&0x7;
76 trace(2, "run") << "subtract effective address from reg " << NUM(arg1) << end();
77 const int32_t* arg2 = effective_address(modrm);
78 BINARY_ARITHMETIC_OP(-, Reg[arg1].i, *arg2);
79 break;
80 }
81
82
83
84 :(scenario and_r32_with_mem_at_r32)
85 % Reg[0].i = 0x60;
86 % SET_WORD_IN_MEM(0x60, 0x0a0b0c0d);
87 % Reg[3].i = 0xff;
88
89 21 18
90 +run: and reg 3 with effective address
91 +run: effective address is mem at address 0x60 (reg 0)
92 +run: storing 0x0000000d
93
94
95
96 :(scenario and_mem_at_r32_with_r32)
97 % Reg[0].i = 0x60;
98 % SET_WORD_IN_MEM(0x60, 0x000000ff);
99 % Reg[3].i = 0x0a0b0c0d;
100
101 23 18
102 +run: and effective address with reg 3
103 +run: effective address is mem at address 0x60 (reg 0)
104 +run: storing 0x0000000d
105
106 :(before "End Single-Byte Opcodes")
107 case 0x23: {
108 uint8_t modrm = next();
109 uint8_t arg1 = (modrm>>3)&0x7;
110 trace(2, "run") << "and effective address with reg " << NUM(arg1) << end();
111 const int32_t* arg2 = effective_address(modrm);
112 BINARY_BITWISE_OP(&, Reg[arg1].u, *arg2);
113 break;
114 }
115
116
117
118 :(scenario or_r32_with_mem_at_r32)
119 % Reg[0].i = 0x60;
120 % SET_WORD_IN_MEM(0x60, 0x0a0b0c0d);
121 % Reg[3].i = 0xa0b0c0d0;
122
123 09 18
124 +run: or reg 3 with effective address
125 +run: effective address is mem at address 0x60 (reg 0)
126 +run: storing 0xaabbccdd
127
128
129
130 :(scenario or_mem_at_r32_with_r32)
131 % Reg[0].i = 0x60;
132 % SET_WORD_IN_MEM(0x60, 0x0a0b0c0d);
133 % Reg[3].i = 0xa0b0c0d0;
134
135 0b 18
136 +run: or effective address with reg 3
137 +run: effective address is mem at address 0x60 (reg 0)
138 +run: storing 0xaabbccdd
139
140 :(before "End Single-Byte Opcodes")
141 case 0x0b: {
142 uint8_t modrm = next();
143 uint8_t arg1 = (modrm>>3)&0x7;
144 trace(2, "run") << "or effective address with reg " << NUM(arg1) << end();
145 const int32_t* arg2 = effective_address(modrm);
146 BINARY_BITWISE_OP(|, Reg[arg1].u, *arg2);
147 break;
148 }
149
150
151
152 :(scenario xor_r32_with_mem_at_r32)
153 % Reg[0].i = 0x60;
154 % SET_WORD_IN_MEM(0x60, 0xaabb0c0d);
155 % Reg[3].i = 0xa0b0c0d0;
156
157 31 18
158 +run: xor reg 3 with effective address
159 +run: effective address is mem at address 0x60 (reg 0)
160 +run: storing 0x0a0bccdd
161
162
163
164 :(scenario xor_mem_at_r32_with_r32)
165 % Reg[0].i = 0x60;
166 % SET_WORD_IN_MEM(0x60, 0x0a0b0c0d);
167 % Reg[3].i = 0xa0b0c0d0;
168
169 33 18
170 +run: xor effective address with reg 3
171 +run: effective address is mem at address 0x60 (reg 0)
172 +run: storing 0xaabbccdd
173
174 :(before "End Single-Byte Opcodes")
175 case 0x33: {
176 uint8_t modrm = next();
177 uint8_t arg1 = (modrm>>3)&0x7;
178 trace(2, "run") << "xor effective address with reg " << NUM(arg1) << end();
179 const int32_t* arg2 = effective_address(modrm);
180 BINARY_BITWISE_OP(|, Reg[arg1].u, *arg2);
181 break;
182 }
183
184
185
186 :(scenario not_r32_with_mem_at_r32)
187 % Reg[3].i = 0x60;
188
189 % SET_WORD_IN_MEM(0x60, 0x0f0f00ff);
190
191 f7 03
192 +run: 'not' of effective address
193 +run: effective address is mem at address 0x60 (reg 3)
194 +run: storing 0xf0f0ff00
195
196
197
198 :(scenario compare_mem_at_r32_with_r32_greater)
199 % Reg[0].i = 0x60;
200 % SET_WORD_IN_MEM(0x60, 0x0a0b0c0d);
201 % Reg[3].i = 0x0a0b0c07;
202
203 39 18
204 +run: compare reg 3 with effective address
205 +run: effective address is mem at address 0x60 (reg 0)
206 +run: SF=0; ZF=0; OF=0
207
208 :(scenario compare_mem_at_r32_with_r32_lesser)
209 % Reg[0].i = 0x60;
210 % SET_WORD_IN_MEM(0x60, 0x0a0b0c07);
211 % Reg[3].i = 0x0a0b0c0d;
212
213 39 18
214 +run: compare reg 3 with effective address
215 +run: effective address is mem at address 0x60 (reg 0)
216 +run: SF=1; ZF=0; OF=0
217
218 :(scenario compare_mem_at_r32_with_r32_equal)
219 % Reg[0].i = 0x60;
220 % SET_WORD_IN_MEM(0x60, 0x0a0b0c0d);
221 % Reg[3].i = 0x0a0b0c0d;
222
223 39 18
224 +run: compare reg 3 with effective address
225 +run: effective address is mem at address 0x60 (reg 0)
226 +run: SF=0; ZF=1; OF=0
227
228
229
230 :(scenario compare_r32_with_mem_at_r32_greater)
231 % Reg[0].i = 0x60;
232 % SET_WORD_IN_MEM(0x60, 0x0a0b0c07);
233 % Reg[3].i = 0x0a0b0c0d;
234
235 3b 18
236 +run: compare effective address with reg 3
237 +run: effective address is mem at address 0x60 (reg 0)
238 +run: SF=0; ZF=0; OF=0
239
240 :(before "End Single-Byte Opcodes")
241 case 0x3b: {
242 uint8_t modrm = next();
243 uint8_t reg1 = (modrm>>3)&0x7;
244 trace(2, "run") << "compare effective address with reg " << NUM(reg1) << end();
245 int32_t arg1 = Reg[reg1].i;
246 int32_t* arg2 = effective_address(modrm);
247 int32_t tmp1 = arg1 - *arg2;
248 SF = (tmp1 < 0);
249 ZF = (tmp1 == 0);
250 int64_t tmp2 = arg1 - *arg2;
251 OF = (tmp1 != tmp2);
252 trace(2, "run") << "SF=" << SF << "; ZF=" << ZF << "; OF=" << OF << end();
253 break;
254 }
255
256 :(scenario compare_r32_with_mem_at_r32_lesser)
257 % Reg[0].i = 0x60;
258 % SET_WORD_IN_MEM(0x60, 0x0a0b0c0d);
259 % Reg[3].i = 0x0a0b0c07;
260
261 3b 18
262 +run: compare effective address with reg 3
263 +run: effective address is mem at address 0x60 (reg 0)
264 +run: SF=1; ZF=0; OF=0
265
266 :(scenario compare_r32_with_mem_at_r32_equal)
267 % Reg[0].i = 0x60;
268 % SET_WORD_IN_MEM(0x60, 0x0a0b0c0d);
269 % Reg[3].i = 0x0a0b0c0d;
270
271 3b 18
272 +run: compare effective address with reg 3
273 +run: effective address is mem at address 0x60 (reg 0)
274 +run: SF=0; ZF=1; OF=0
275
276
277
278 :(scenario copy_r32_to_mem_at_r32)
279 % Reg[3].i = 0xaf;
280 % Reg[0].i = 0x60;
281
282 89 18
283 +run: copy reg 3 to effective address
284 +run: effective address is mem at address 0x60 (reg 0)
285 +run: storing 0x000000af
286
287
288
289 :(scenario copy_mem_at_r32_to_r32)
290 % Reg[0].i = 0x60;
291 % SET_WORD_IN_MEM(0x60, 0x000000af);
292
293 8b 18
294 +run: copy effective address to reg 3
295 +run: effective address is mem at address 0x60 (reg 0)
296 +run: storing 0x000000af
297
298 :(before "End Single-Byte Opcodes")
299 case 0x8b: {
300 uint8_t modrm = next();
301 uint8_t reg1 = (modrm>>3)&0x7;
302 trace(2, "run") << "copy effective address to reg " << NUM(reg1) << end();
303 int32_t* arg2 = effective_address(modrm);
304 Reg[reg1].i = *arg2;
305 trace(2, "run") << "storing 0x" << HEXWORD << *arg2 << end();
306 break;
307 }
308
309
310
311 :(scenario jump_mem_at_r32)
312 % Reg[0].i = 0x60;
313 % SET_WORD_IN_MEM(0x60, 8);
314
315 ff 20
316 05 00 00 00 01
317 05 00 00 00 02
318 +run: inst: 0x00000001
319 +run: jump to effective address
320 +run: effective address is mem at address 0x60 (reg 0)
321 +run: jumping to 0x00000008
322 +run: inst: 0x00000008
323 -run: inst: 0x00000003
324
325 :(before "End Single-Byte Opcodes")
326 case 0xff: {
327 uint8_t modrm = next();
328 uint8_t subop = (modrm>>3)&0x7;
329 switch (subop) {
330 ¦ case 4: {
331 ¦ ¦ trace(2, "run") << "jump to effective address" << end();
332 ¦ ¦ int32_t* arg2 = effective_address(modrm);
333 ¦ ¦ EIP = *arg2;
334 ¦ ¦ trace(2, "run") << "jumping to 0x" << HEXWORD << EIP << end();
335 ¦ ¦ break;
336 ¦ }
337 ¦
338 }
339 break;
340 }
341
342
343
344 :(scenario push_mem_at_r32)
345 % Reg[0].i = 0x60;
346 % SET_WORD_IN_MEM(0x60, 0x000000af);
347 % Reg[ESP].u = 0x14;
348
349 ff 30
350 +run: push effective address
351 +run: effective address is mem at address 0x60 (reg 0)
352 +run: decrementing ESP to 0x00000010
353 +run: pushing value 0x000000af
354
355 :(before "End Op ff Subops")
356 case 6: {
357 trace(2, "run") << "push effective address" << end();
358 const int32_t* val = effective_address(modrm);
359 push(*val);
360 break;
361 }
362
363
364
365 :(scenario pop_mem_at_r32)
366 % Reg[0].i = 0x60;
367 % Reg[ESP].u = 0x10;
368 % SET_WORD_IN_MEM(0x10, 0x00000030);
369
370 8f 00
371 +run: pop into effective address
372 +run: effective address is mem at address 0x60 (reg 0)
373 +run: popping value 0x00000030
374 +run: incrementing ESP to 0x00000014
375
376 :(before "End Single-Byte Opcodes")
377 case 0x8f: {
378 uint8_t modrm = next();
379 uint8_t subop = (modrm>>3)&0x7;
380 switch (subop) {
381 ¦ case 0: {
382 ¦ ¦ trace(2, "run") << "pop into effective address" << end();
383 ¦ ¦ int32_t* dest = effective_address(modrm);
384 ¦ ¦ *dest = pop();
385 ¦ ¦ break;
386 ¦ }
387 }
388 break;
389 }