https://github.com/akkartik/mu/blob/master/017jump_disp8.cc
  1 //: jump to 8-bit offset
  2 
  3 //:: jump
  4 
  5 :(before "End Initialize Op Names")
  6 put_new(Name, "eb", "jump disp8 bytes away (jmp)");
  7 
  8 :(code)
  9 void test_jump_disp8() {
 10   run(
 11       "== code 0x1\n"
 12       // op     ModR/M  SIB   displacement  immediate
 13       "  eb                   05                        \n"  // skip 1 instruction
 14       "  05                                 00 00 00 01 \n"
 15       "  05                                 00 00 00 02 \n"
 16   );
 17   CHECK_TRACE_CONTENTS(
 18       "run: 0x00000001 opcode: eb\n"
 19       "run: jump 5\n"
 20       "run: 0x00000008 opcode: 05\n"
 21   );
 22   CHECK_TRACE_DOESNT_CONTAIN("run: 0x00000003 opcode: 05");
 23 }
 24 
 25 :(before "End Single-Byte Opcodes")
 26 case 0xeb: {  // jump disp8
 27   int8_t offset = static_cast<int>(next());
 28   trace(Callstack_depth+1, "run") << "jump " << NUM(offset) << end();
 29   EIP += offset;
 30   break;
 31 }
 32 
 33 //:: jump if equal/zero
 34 
 35 :(before "End Initialize Op Names")
 36 put_new(Name, "74", "jump disp8 bytes away if equal, if ZF is set (jcc/jz/je)");
 37 
 38 :(code)
 39 void test_je_disp8_success() {
 40   ZF = true;
 41   run(
 42       "== code 0x1\n"
 43       // op     ModR/M  SIB   displacement  immediate
 44       "  74                   05                        \n"  // skip 1 instruction
 45       "  05                                 00 00 00 01 \n"
 46       "  05                                 00 00 00 02 \n"
 47   );
 48   CHECK_TRACE_CONTENTS(
 49       "run: 0x00000001 opcode: 74\n"
 50       "run: jump 5\n"
 51       "run: 0x00000008 opcode: 05\n"
 52   );
 53   CHECK_TRACE_DOESNT_CONTAIN("run: 0x00000003 opcode: 05");
 54 }
 55 
 56 :(before "End Single-Byte Opcodes")
 57 case 0x74: {  // jump disp8 if ZF
 58   const int8_t offset = static_cast<int>(next());
 59   if (ZF) {
 60     trace(Callstack_depth+1, "run") << "jump " << NUM(offset) << end();
 61     EIP += offset;
 62   }
 63   break;
 64 }
 65 
 66 :(code)
 67 void test_je_disp8_fail() {
 68   ZF = false;
 69   run(
 70       "== code 0x1\n"
 71       // op     ModR/M  SIB   displacement  immediate
 72       "  74                   05                        \n"  // skip 1 instruction
 73       "  05                                 00 00 00 01 \n"
 74       "  05                                 00 00 00 02 \n"
 75   );
 76   CHECK_TRACE_CONTENTS(
 77       "run: 0x00000001 opcode: 74\n"
 78       "run: 0x00000003 opcode: 05\n"
 79       "run: 0x00000008 opcode: 05\n"
 80   );
 81   CHECK_TRACE_DOESNT_CONTAIN("run: jump 5");
 82 }
 83 
 84 //:: jump if not equal/not zero
 85 
 86 :(before "End Initialize Op Names")
 87 put_new(Name, "75", "jump disp8 bytes away if not equal, if ZF is not set (jcc/jnz/jne)");
 88 
 89 :(code)
 90 void test_jne_disp8_success() {
 91   ZF = false;
 92   run(
 93       "== code 0x1\n"
 94       // op     ModR/M  SIB   displacement  immediate
 95       "  75                   05                        \n"  // skip 1 instruction
 96       "  05                                 00 00 00 01 \n"
 97       "  05                                 00 00 00 02 \n"
 98   );
 99   CHECK_TRACE_CONTENTS(
100       "run: 0x00000001 opcode: 75\n"
101       "run: jump 5\n"
102       "run: 0x00000008 opcode: 05\n"
103   );
104   CHECK_TRACE_DOESNT_CONTAIN("run: 0x00000003 opcode: 05");
105 }
106 
107 :(before "End Single-Byte Opcodes")
108 case 0x75: {  // jump disp8 if !ZF
109   const int8_t offset = static_cast<int>(next());
110   if (!ZF) {
111     trace(Callstack_depth+1, "run") << "jump " << NUM
114 break; 115 } 116 117 :(code) 118 void test_jne_disp8_fail() { 119 ZF = true; 120 run( 121 "== code 0x1\n" 122 // op ModR/M SIB displacement immediate 123 " 75 05 \n" // skip 1 instruction 124 " 05 00 00 00 01 \n" 125 " 05 00 00 00 02 \n" 126 ); 127 CHECK_TRACE_CONTENTS( 128 "run: 0x00000001 opcode: 75\n" 129 "run: 0x00000003 opcode: 05\n" 130 "run: 0x00000008 opcode: 05\n" 131 ); 132 CHECK_TRACE_DOESNT_CONTAIN("run: jump 5"); 133 } 134 135 //:: jump if greater 136 137 :(before "End Initialize Op Names") 138 put_new(Name, "7f", "jump disp8 bytes away if greater, if ZF is unset and SF == OF (jcc/jg/jnle)"); 139 put_new(Name, "77", "jump disp8 bytes away if greater (addr, float), if ZF is unset and CF is unset (jcc/ja/jnbe)"); 140 141 :(code) 142 void test_jg_disp8_success() { 143 ZF = false; 144 SF = false; 145 OF = false; 146 run( 147 "== code 0x1\n" 148 // op ModR/M SIB displacement immediate 149 " 7f 05 \n" // skip 1 instruction 150 " 05 00 00 00 01 \n" 151 " 05 00 00 00 02 \n" 152 ); 153 CHECK_TRACE_CONTENTS( 154 "run: 0x00000001 opcode: 7f\n" 155 "run: jump 5\n" 156 "run: 0x00000008 opcode: 05\n" 157 ); 158 CHECK_TRACE_DOESNT_CONTAIN("run: 0x00000003 opcode: 05"); 159 } 160 161 :(before "End Single-Byte Opcodes") 162 case 0x7f: { // jump disp8 if SF == OF and !ZF 163 const int8_t offset = static_cast<int>(next()); 164 if (SF == OF && !ZF) { 165 trace(Callstack_depth+1, "run") << "jump " << NUM(offset) << end(); 166 EIP += offset; 167 } 168 break; 169 } 170 case 0x77: { // jump disp8 if !CF and !ZF 171 const int8_t offset = static_cast<int>(next()); 172 if (!CF && !ZF) { 173 trace(Callstack_depth+1, "run") << "jump " << NUM(offset) << end(); 174 EIP += offset; 175 } 176 break; 177 } 178 179 :(code) 180 void test_jg_disp8_fail() { 181 ZF = false; 182 SF = true; 183 OF = false; 184 run( 185 "== code 0x1\n" 186 // op ModR/M SIB displacement immediate 187 " 7f 05 \n" // skip 1 instruction 188 " 05 00 00 00 01 \n" 189 " 05 00 00 00 02 \n" 190 ); 191 CHECK_TRACE_CONTENTS( 192 "run: 0x00000001 opcode: 7f\n" 193 "run: 0x00000003 opcode: 05\n" 194 "run: 0x00000008 opcode: 05\n" 195 ); 196 CHECK_TRACE_DOESNT_CONTAIN("run: jump 5"); 197 } 198 199 //:: jump if greater or equal 200 201 :(before "End Initialize Op Names") 202 put_new(Name, "7d", "jump disp8 bytes away if greater or equal, if SF == OF (jcc/jge/jnl)"); 203 put_new(Name, "73", "jump disp8 bytes away if greater or equal (addr, float), if CF is unset (jcc/jae/jnb)"); 204 205 :(code) 206 void test_jge_disp8_success() { 207 SF = false; 208 OF = false; 209 run( 210 "== code 0x1\n" 211 // op ModR/M SIB displacement immediate 212 " 7d 05 \n" // skip 1 instruction 213 " 05 00 00 00 01 \n" 214 " 05 00 00 00 02 \n" 215 ); 216 CHECK_TRACE_CONTENTS( 217 "run: 0x00000001 opcode: 7d\n" 218 "run: jump 5\n" 219 "run: 0x00000008 opcode: 05\n" 220 ); 221 CHECK_TRACE_DOESNT_CONTAIN("run: 0x00000003 opcode: 05"); 222 } 223 224 :(before "End Single-Byte Opcodes") 225 case 0x7d: { // jump disp8 if SF == OF 226 const int8_t offset = static_cast<int>(next()); 227 if (SF == OF) { 228 trace(Callstack_depth+1, "run") << "jump " << NUM(offset) << end(); 229 EIP += offset; 230 } 231 break; 232 } 233 case 0x73: { // jump disp8 if !CF 234 const int8_t offset = static_cast<int>(next()); 235 if (!CF) { 236 trace(Callstack_depth+1, "run") << "jump " << NUM(offset) << end(); 237 EIP += offset; 238 } 239 break; 240 } 241 242 :(code) 243 void test_jge_disp8_fail() { 244 SF = true; 245 OF = false; 246 run( 247 "== code 0x1\n" 248 // op ModR/M SIB displacement immediate 249 " 7d 05 \n" // skip 1 instruction 250 " 05 00 00 00 01 \n" 251 " 05 00 00 00 02 \n" 252 ); 253 CHECK_TRACE_CONTENTS( 254 "run: 0x00000001 opcode: 7d\n" 255 "run: 0x00000003 opcode: 05\n" 256 "run: 0x00000008 opcode: 05\n" 257 ); 258 CHECK_TRACE_DOESNT_CONTAIN("run: jump 5"); 259 } 260 261 //:: jump if lesser 262 263 :(before "End Initialize Op Names") 264 put_new(Name, "7c", "jump disp8 bytes away if lesser, if SF != OF (jcc/jl/jnge)"); 265 put_new(Name, "72", "jump disp8 bytes away if lesser (addr, float), if CF is set (jcc/jb/jnae)"); 266 267 :(code) 268 void test_jl_disp8_success() { 269 ZF = false; 270 SF = true; 271 OF = false; 272 run( 273 "== code 0x1\n" 274 // op ModR/M SIB displacement immediate 275 " 7c 05 \n" // skip 1 instruction 276 " 05 00 00 00 01 \n" 277 " 05 00 00 00 02 \n" 278 ); 279 CHECK_TRACE_CONTENTS( 280 "run: 0x00000001 opcode: 7c\n" 281 "run: jump 5\n" 282 "run: 0x00000008 opcode: 05\n" 283 ); 284 CHECK_TRACE_DOESNT_CONTAIN("run: 0x00000003 opcode: 05"); 285 } 286 287 :(before "End Single-Byte Opcodes") 288 case 0x7c: { // jump disp8 if SF != OF 289 const int8_t offset = static_cast<int>(next()); 290 if (SF != OF) { 291 trace(Callstack_depth+1, "run") << "jump " << NUM(offset) << end(); 292 EIP += offset; 293 } 294 break; 295 } 296 case 0x72: { // jump disp8 if CF 297 const int8_t offset = static_cast<int>(next()); 298 if (CF) { 299 trace(Callstack_depth+1, "run") << "jump " << NUM(offset) << end(); 300 EIP += offset; 301 } 302 break; 303 } 304 305 :(code) 306 void test_jl_disp8_fail() { 307 ZF = false; 308 SF = false; 309 OF = false; 310 run( 311 "== code 0x1\n" 312 // op ModR/M SIB displacement immediate 313 " 7c 05 \n" // skip 1 instruction 314 " 05 00 00 00 01 \n" 315 " 05 00 00 00 02 \n" 316 ); 317 CHECK_TRACE_CONTENTS( 318 "run: 0x00000001 opcode: 7c\n" 319 "run: 0x00000003 opcode: 05\n" 320 "run: 0x00000008 opcode: 05\n" 321 ); 322 CHECK_TRACE_DOESNT_CONTAIN("run: jump 5"); 323 } 324 325 //:: jump if lesser or equal 326 327 :(before "End Initialize Op Names") 328 put_new(Name, "7e", "jump disp8 bytes away if lesser or equal, if ZF is set or SF != OF (jcc/jle/jng)"); 329 put_new(Name, "76", "jump disp8 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_disp8_equal() { 333 ZF = true; 334 SF = false; 335 OF = false; 336 run( 337 "== code 0x1\n" 338 // op ModR/M SIB displacement immediate 339 " 7e 05 \n" // skip 1 instruction 340 " 05 00 00 00 01 \n" 341 " 05 00 00 00 02 \n" 342 ); 343 CHECK_TRACE_CONTENTS( 344 "run: 0x00000001 opcode: 7e\n" 345 "run: jump 5\n" 346 "run: 0x00000008 opcode: 05\n" 347 ); 348 CHECK_TRACE_DOESNT_CONTAIN("run: 0x00000003 opcode: 05"); 349 } 350 351 :(code) 352 void test_jle_disp8_lesser() { 353 ZF = false; 354 SF = true; 355 OF = false; 356 run( 357 "== code 0x1\n" 358 // op ModR/M SIB displacement immediate 359 " 7e 05 \n" // skip 1 instruction 360 " 05 00 00 00 01 \n" 361 " 05 00 00 00 02 \n" 362 ); 363 CHECK_TRACE_CONTENTS( 364 "run: 0x00000001 opcode: 7e\n" 365 "run: jump 5\n" 366 "run: 0x00000008 opcode: 05\n" 367 ); 368 CHECK_TRACE_DOESNT_CONTAIN("run: 0x00000003 opcode: 05"); 369 } 370 371 :(before "End Single-Byte Opcodes") 372 case 0x7e: { // jump disp8 if ZF or SF != OF 373 const int8_t offset = static_cast<int>(next()); 374 if (ZF || SF != OF) { 375 trace(Callstack_depth+1, "run") << "jump " << NUM(offset) << end(); 376 EIP += offset; 377 } 378 break; 379 } 380 case 0x76: { // jump disp8 if ZF or CF 381 const int8_t offset = static_cast<int>(next()); 382 if (ZF || CF) { 383 trace(Callstack_depth+1, "run") << "jump " << NUM(offset) << end(); 384 EIP += offset; 385 } 386 break; 387 } 388 389 :(code) 390 void test_jle_disp8_greater() { 391 ZF = false; 392 SF = false; 393 OF = false; 394 run( 395 "== code 0x1\n" 396 // op ModR/M SIB displacement immediate 397 " 7e 05 \n" // skip 1 instruction 398 " 05 00 00 00 01 \n" 399 " 05 00 00 00 02 \n" 400 ); 401 CHECK_TRACE_CONTENTS( 402 "run: 0x00000001 opcode: 7e\n" 403 "run: 0x00000003 opcode: 05\n" 404 "run: 0x00000008 opcode: 05\n" 405 ); 406 CHECK_TRACE_DOESNT_CONTAIN("run: jump 5"); 407 }