https://github.com/akkartik/mu/blob/main/linux/bootstrap/018jump_disp32.cc
1
2
3
4
5 :(before "End Initialize Op Names")
6 put_new(Name, "e9", "jump disp32 bytes away (jmp)");
7
8 :(code)
9 void test_jump_disp32() {
10 run(
11 "== code 0x1\n"
12
13 " e9 05 00 00 00 \n"
14 " 05 00 00 00 01 \n"
15 " 05 00 00 00 02 \n"
16 );
17 CHECK_TRACE_CONTENTS(
18 "run: 0x00000001 opcode: e9\n"
19 "run: jump 5\n"
20 "run: 0x0000000b opcode: 05\n"
21 );
22 CHECK_TRACE_DOESNT_CONTAIN("run: 0x00000006 opcode: 05");
23 }
24
25 :(before "End Single-Byte Opcodes")
26 case 0xe9: {
27 const int32_t offset = next32();
28 trace(Callstack_depth+1, "run") << "jump " << offset << end();
29 EIP += offset;
30 break;
31 }
32
33
34
35 :(before "End Initialize Op Names")
36 put_new(Name_0f, "84", "jump disp32 bytes away if equal, if ZF is set (jcc/jz/je)");
37
38 :(code)
39 void test_je_disp32_success() {
40 ZF = true;
41 run(
42 "== code 0x1\n"
43
44 " 0f 84 05 00 00 00 \n"
45 " 05 00 00 00 01 \n"
46 " 05 00 00 00 02 \n"
47 );
48 CHECK_TRACE_CONTENTS(
49 "run: 0x00000001 opcode: 0f\n"
50 "run: jump 5\n"
51 "run: 0x0000000c opcode: 05\n"
52 );
53 CHECK_TRACE_DOESNT_CONTAIN("run: 0x00000007 opcode: 05");
54 }
55
56 :(before "End Two-Byte Opcodes Starting With 0f")
57 case 0x84: {
58 const int32_t offset = next32();
59 if (ZF) {
60 trace(Callstack_depth+1, "run") << "jump " << offset << end();
61 EIP += offset;
62 }
63 break;
64 }
65
66 :(code)
67 void test_je_disp32_fail() {
68 ZF = false;
69 run(
70 "== code 0x1\n"
71
72 " 0f 84 05 00 00 00 \n"
73 " 05 00 00 00 01 \n"
74 " 05 00 00 00 02 \n"
75 );
76 CHECK_TRACE_CONTENTS(
77 "run: 0x00000001 opcode: 0f\n"
78 "run: 0x00000007 opcode: 05\n"
79 "run: 0x0000000c opcode: 05\n"
80 );
81 CHECK_TRACE_DOESNT_CONTAIN("run: jump 5");
82 }
83
84
85
86 :(before "End Initialize Op Names")
87 put_new(Name_0f, "85", "jump disp32 bytes away if not equal, if ZF is not set (jcc/jnz/jne)");
88
89 :(code)
90 void test_jne_disp32_success() {
91 ZF = false;
92 run(
93 "== code 0x1\n"
94
95 " 0f 85 05 00 00 00 \n"
96 " 05 00 00 00 01 \n"
97 " 05 00 00 00 02 \n"
98 );
99 CHECK_TRACE_CONTENTS(
100 "run: 0x00000001 opcode: 0f\n"
101 "run: jump 5\n"
102 "run: 0x0000000c opcode: 05\n"
103 );
104 CHECK_TRACE_DOESNT_CONTAIN("run: 0x00000007 opcode: 05");
105 }
106
107 :(before "End Two-Byte Opcodes Starting With 0f")
108 case 0x85: {
109 const int32_t offset = next32();
110 if (!ZF) {
111 trace(Callstack_depth+1, "run") << "jump " << offset << end();
112 EIP += offset;
113 }
114 break;
115 }
116
117 :(code)
118 void test_jne_disp32_fail() {
119 ZF = true;
120 run(
121 "== code 0x1\n"
122
123 " 0f 85 05 00 00 00 \n"
124 " 05 00 00 00 01 \n"
125 " 05 00 00 00 02 \n"
126 );
127 CHECK_TRACE_CONTENTS(
128 "run: 0x00000001 opcode: 0f\n"
129 "run: 0x00000007 opcode: 05\n"
130 "run: 0x0000000c opcode: 05\n"
131 );
132 CHECK_TRACE_DOESNT_CONTAIN("run: jump 5");
133 }
134
135
136
137 :(before "End Initialize Op Names")
138 put_new(Name_0f, "8f", "jump disp32 bytes away if greater, if ZF is unset and SF == OF (jcc/jg/jnle)");
139 put_new(Name_0f, "87", "jump disp32 bytes away if greater (addr, float), if ZF is unset and CF is unset (jcc/ja/jnbe)");
140
141 :(code)
142 void test_jg_disp32_success() {
143 ZF = false;
144 SF = false;
145 OF = false;
146 run(
147 "== code 0x1\n"
148
149 " 0f 8f 05 00 00 00 \n"
150 " 05 00 00 00 01 \n"
151 " 05 00 00 00 02 \n"
152 );
153 CHECK_TRACE_CONTENTS(
154 "run: 0x00000001 opcode: 0f\n"
155 "run: jump 5\n"
156 "run: 0x0000000c opcode: 05\n"
157 );
158 CHECK_TRACE_DOESNT_CONTAIN("run: 0x00000007 opcode: 05");
159 }
160
161 :(before "End Two-Byte Opcodes Starting With 0f")
162 case 0x8f: {
163 const int32_t offset = next32();
164 if (!ZF && SF == OF) {
165 trace(Callstack_depth+1, "run") << "jump " << offset << end();
166 EIP += offset;
167 }
168 break;
169 }
170 case 0x87: {
171 const int32_t offset = next32();
172 if (!CF && !ZF) {
173 trace(Callstack_depth+1, "run") << "jump " << offset << end();
174 EIP += offset;
175 }
176 break;
177 }
178
179 :(code)
180 void test_jg_disp32_fail() {
181 ZF = false;
182 SF = true;
183 OF = false;
184 run(
185 "== code 0x1\n"
186
187 " 0f 8f 05 00 00 00 \n"
188 " 05 00 00 00 01 \n"
189 " 05 00 00 00 02 \n"
190 );
191 CHECK_TRACE_CONTENTS(
192 "run: 0x00000001 opcode: 0f\n"
193 "run: 0x00000007 opcode: 05\n"
194 "run: 0x0000000c opcode: 05\n"
195 );
196 CHECK_TRACE_DOESNT_CONTAIN("run: jump 5");
197 }
198
199
200
201 :(before "End Initialize Op Names")
202 put_new(Name_0f, "8d", "jump disp32 bytes away if greater or equal, if SF == OF (jcc/jge/jnl)");
203 put_new(Name_0f, "83", "jump disp32 bytes away if greater or equal (addr, float), if CF is unset (jcc/jae/jnb)");
204
205 :(code)
206 void test_jge_disp32_success() {
207 SF = false;
208 OF = false;
209 run(
210 "== code 0x1\n"
211
212 " 0f 8d 05 00 00 00 \n"
213 " 05 00 00 00 01 \n"
214 " 05 00 00 00 02 \n"
215 );
216 CHECK_TRACE_CONTENTS(
217 "run: 0x00000001 opcode: 0f\n"
218 "run: jump 5\n"
219 "run: 0x0000000c opcode: 05\n"
220 );
221 CHECK_TRACE_DOESNT_CONTAIN("run: 0x00000007 opcode: 05");
222 }
223
224 :(before "End Two-Byte Opcodes Starting With 0f")
225 case 0x8d: {
226 const int32_t offset = next32();
227 if (SF == OF) {
228 trace(Callstack_depth+1, "run") << "jump " << offset << end();
229 EIP += offset;
230 }
231 break;
232 }
233 case 0x83: {
234 const int32_t offset = next32();
235 if (!CF) {
236 trace(Callstack_depth+1, "run") << "jump " << offset << end();
237 EIP += offset;
238 }
239 break;
240 }
241
242 :(code)
243 void test_jge_disp32_fail() {
244 SF = true;
245 OF = false;
246 run(
247 "== code 0x1\n"
248
249 " 0f 8d 05 00 00 00 \n"
250 " 05 00 00 00 01 \n"
251 " 05 00 00 00 02 \n"
252 );
253 CHECK_TRACE_CONTENTS(
254 "run: 0x00000001 opcode: 0f\n"
255 "run: 0x00000007 opcode: 05\n"
256 "run: 0x0000000c opcode: 05\n"
257 );
258 CHECK_TRACE_DOESNT_CONTAIN("run: jump 5");
259 }
260
261
262
263 :(before "End Initialize Op Names")
264 put_new(Name_0f, "8c", "jump disp32 bytes away if lesser, if SF != OF (jcc/jl/jnge)");
265 put_new(Name_0f, "82", "jump disp32 bytes away if lesser (addr, float), if CF is set (jcc/jb/jnae)");
266
267 :(code)
268 void test_jl_disp32_success() {
269 ZF = false;
270 SF = true;
271 OF = false;
272 run(
273 "== code 0x1\n"
274
275 " 0f 8c 05 00 00 00 \n"
276 " 05 00 00 00 01 \n"
277 " 05 00 00 00 02 \n"
278 );
279 CHECK_TRACE_CONTENTS(
280 "run: 0x00000001 opcode: 0f\n"
281 "run: jump 5\n"
282 "run: 0x0000000c opcode: 05\n"
283 );
284 CHECK_TRACE_DOESNT_CONTAIN("run: 0x00000007 opcode: 05");
285 }
286
287 :(before "End Two-Byte Opcodes Starting With 0f")
288 case 0x8c: {
289 const int32_t offset = next32();
290 if (SF != OF) {
291 trace(Callstack_depth+1, "run") << "jump " << offset << end();
292 EIP += offset;
293 }
294 break;
295 }
296 case 0x82: {
297 const int32_t offset = next32();
298 if (CF) {
299 trace(Callstack_depth+1, "run") << "jump " << offset << end();
300 EIP += offset;
301 }
302 break;
303 }
304
305 :(code)
306 void test_jl_disp32_fail() {
307 ZF = false;
308 SF = false;
309 OF = false;
310 run(
311 "== code 0x1\n"
312
313 " 0f 8c 05 00 00 00 \n"
314 " 05 00 00 00 01 \n"
315 " 05 00 00 00 02 \n"
316 );
317 CHECK_TRACE_CONTENTS(
318 "run: 0x00000001 opcode: 0f\n"
319 "run: 0x00000007 opcode: 05\n"
320 "run: 0x0000000c opcode: 05\n"
321 );
322 CHECK_TRACE_DOESNT_CONTAIN("run: jump 5");
323 }
324
325
326
327 :(before "End Initialize Op Names")
328 put_new(Name_0f, "8e", "jump disp32 bytes away if lesser or equal, if ZF is set or SF != OF (jcc/jle/jng)");
329 put_new(Name_0f, "86", "jump disp32 bytes away if lesser or equal (addr, float), if ZF is set or CF is set (jcc/jbe/jna)");
330
331 :(code)
332 void test_jle_disp32_equal() {
333 ZF = true;
334 SF = false;
335 OF = false;
336 run(
337 "== code 0x1\n"
338
339 " 0f 8e 05 00 00 00 \n"
340 " 05 00 00 00 01 \n"
341 " 05 00 00 00 02 \n"
342 );
343 CHECK_TRACE_CONTENTS(
344 "run: 0x00000001 opcode: 0f\n"
345 "run: jump 5\n"
346 "run: 0x0000000c opcode: 05\n"
347 );
348 CHECK_TRACE_DOESNT_CONTAIN("run: 0x00000007 opcode: 05");
349 }
350
351 :(code)
352 void test_jle_disp32_lesser() {
353 ZF = false;
354 SF = true;
355 OF = false;
356 run(
357 "== code 0x1\n"
358
359 " 0f 8e 05 00 00 00 \n"
360 " 05 00 00 00 01 \n"
361 " 05 00 00 00 02 \n"
362 );
363 CHECK_TRACE_CONTENTS(
364 "run: 0x00000001 opcode: 0f\n"
365 "run: jump 5\n"
366 "run: 0x0000000c opcode: 05\n"
367 );
368 CHECK_TRACE_DOESNT_CONTAIN("run: 0x00000007 opcode: 05");
369 }
370
371 :(before "End Two-Byte Opcodes Starting With 0f")
372 case 0x8e: {
373 const int32_t offset = next32();
374 if (ZF || SF != OF) {
375 trace(Callstack_depth+1, "run") << "jump " << offset << end();
376 EIP += offset;
377 }
378 break;
379 }
380 case 0x86: {
381 const int32_t offset = next32();
382 if (ZF || CF) {
383 trace(Callstack_depth+1, "run") << "jump " << offset << end();
384 EIP += offset;
385 }
386 break;
387 }
388
389 :(code)
390 void test_jle_disp32_greater() {
391 ZF = false;
392 SF = false;
393 OF = false;
394 run(
395 "== code 0x1\n"
396
397 " 0f 8e 05 00 00 00 \n"
398 " 05 00 00 00 01 \n"
399 " 05 00 00 00 02 \n"
400 );
401 CHECK_TRACE_CONTENTS(
402 "run: 0x00000001 opcode: 0f\n"
403 "run: 0x00000007 opcode: 05\n"
404 "run: 0x0000000c opcode: 05\n"
405 );
406 CHECK_TRACE_DOESNT_CONTAIN("run: jump 5");
407 }
408
409
410
411 :(before "End Initialize Op Names")
412 put_new(Name_0f, "80", "jump disp32 bytes away if OF is set (jcc/jo)");
413 put_new(Name_0f, "81", "jump disp32 bytes away if OF is unset (jcc/jno)");
414
415 :(before "End Two-Byte Opcodes Starting With 0f")
416 case 0x80: {
417 const int32_t offset = next32();
418 if (OF) {
419 trace(Callstack_depth+1, "run") << "jump " << NUM(offset) << end();
420 EIP += offset;
421 }
422 break;
423 }
424 case 0x81: {
425 const int32_t offset = next32();
426 if (!OF) {
427 trace(Callstack_depth+1, "run") << "jump " << NUM(offset) << end();
428 EIP += offset;
429 }
430 break;
431 }