https://github.com/akkartik/mu/blob/master/subx/018jump_disp32.cc

      1 //: jump to 32-bit offset
      2
      3 //:: jump
      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       "== 0x1\n"  // code segment
     12       // op     ModR/M  SIB   displacement  immediate
     13       "  e9                   05 00 00 00               \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: 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: {  // jump disp32
     27   const int32_t offset = next32();
     28   trace(Callstack_depth+1, "run") << "jump " << 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_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       "== 0x1\n"  // code segment
     43       // op     ModR/M  SIB   displacement  immediate
     44       "  0f 84                05 00 00 00               \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: 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: {  // jump disp32 if ZF
     58   const int32_t offset = next32();
     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_disp32_fail() {
     68   ZF = false;
     69   run(
     70       "== 0x1\n"  // code segment
     71       // op     ModR/M  SIB   displacement  immediate
     72       "  0f 84                05 00 00 00               \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: 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 //:: jump if not equal/not zero
     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       "== 0x1\n"  // code segment
     94       // op     ModR/M  SIB   displacement  immediate
     95       "  0f 85                05 00 00 00               \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: 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: {  // jump disp32 unless ZF
    109   const int32_t offset = next32();
    110   if (!ZF) {
    111     trace(Callstack_depth+1, "run") << "jump " << NUM(offset) << end();
    112     EIP += offset;
    113   }
    114   break;
    115 }
    116
    117 :(code)
    118 void test_jne_disp32_fail() {
    119   ZF = true;
    120   run(
    121       "== 0x1\n"  // code segment
    122       // op     ModR/M  SIB   displacement  immediate
    123       "  0f 85                05 00 00 00               \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: 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 //:: jump if greater
    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
    140 :(code)
    141 void test_jg_disp32_success() {
    142   ZF = false;
    143   SF = false;
    144   OF = false;
    145   run(
    146       "== 0x1\n"  // code segment
    147       // op     ModR/M  SIB   displacement  immediate
    148       "  0f 8f                05 00 00 00               \n"  // skip 1 instruction
    149       "  05                                 00 00 00 01 \n"
    150       "  05                                 00 00 00 02 \n"
    151   );
    152   CHECK_TRACE_CONTENTS(
    153       "run: 0x00000001 opcode: 0f\n"
    154       "run: jump 5\n"
    155       "run: 0x0000000c opcode: 05\n"
    156   );
    157   CHECK_TRACE_DOESNT_CONTAIN("run: 0x00000007 opcode: 05");
    158 }
    159
    160 :(before "End Two-Byte Opcodes Starting With 0f")
    161 case 0x8f: {  // jump disp32 if !SF and !ZF
    162   const int32_t offset = next32();
    163   if (!ZF && SF == OF) {
    164     trace(Callstack_depth+1, "run") << "jump " << NUM(offset) << end();
    165     EIP += offset;
    166   }
    167   break;
    168 }
    169
    170 :(code)
    171 void test_jg_disp32_fail() {
    172   ZF = false;
    173   SF = true;
    174   OF = false;
    175   run(
    176       "== 0x1\n"  // code segment
    177       // op     ModR/M  SIB   displacement  immediate
    178       "  0f 8f                05 00 00 00               \n"  // skip 1 instruction
    179       "  05                                 00 00 00 01 \n"
    180       "  05                                 00 00 00 02 \n"
    181   );
    182   CHECK_TRACE_CONTENTS(
    183       "run: 0x00000001 opcode: 0f\n"
    184       "run: 0x00000007 opcode: 05\n"
    185       "run: 0x0000000c opcode: 05\n"
    186   );
    187   CHECK_TRACE_DOESNT_CONTAIN("run: jump 5");
    188 }
    189
    190 //:: jump if greater or equal
    191
    192 :(before "End Initialize Op Names")
    193 put_new(Name_0f, "8d", "jump disp32 bytes away if greater or equal, if SF == OF (jcc/jge/jnl)");
    194
    195 :(code)
    196 void test_jge_disp32_success() {
    197   SF = false;
    198   OF = false;
    199   run(
    200       "== 0x1\n"  // code segment
    201       // op     ModR/M  SIB   displacement  immediate
    202       "  0f 8d                05 00 00 00               \n"  // skip 1 instruction
    203       "  05                                 00 00 00 01 \n"
    204       "  05                                 00 00 00 02 \n"
    205   );
    206   CHECK_TRACE_CONTENTS(
    207       "run: 0x00000001 opcode: 0f\n"
    208       "run: jump 5\n"
    209       "run: 0x0000000c opcode: 05\n"
    210   );
    211   CHECK_TRACE_DOESNT_CONTAIN("run: 0x00000007 opcode: 05");
    212 }
    213
    214 :(before "End Two-Byte Opcodes Starting With 0f")
    215 case 0x8d: {  // jump disp32 if !SF
    216   const int32_t offset = next32();
    217   if (SF == OF) {
    218     trace(Callstack_depth+1, "run") << "jump " << NUM(offset) << end();
    219     EIP += offset;
    220   }
    221   break;
    222 }
    223
    224 :(code)
    225 void test_jge_disp32_fail() {
    226   SF = true;
    227   OF = false;
    228   run(
    229       "== 0x1\n"  // code segment
    230       // op     ModR/M  SIB   displacement  immediate
    231       "  0f 8d                05 00 00 00               \n"  // skip 1 instruction
    232       "  05                                 00 00 00 01 \n"
    233       "  05                                 00 00 00 02 \n"
    234   );
    235   CHECK_TRACE_CONTENTS(
    236       "run: 0x00000001 opcode: 0f\n"
    237       "run: 0x00000007 opcode: 05\n"
    238       "run: 0x0000000c opcode: 05\n"
    239   );
    240   CHECK_TRACE_DOESNT_CONTAIN("run: jump 5");
    241 }
    242
    243 //:: jump if lesser
    244
    245 :(before "End Initialize Op Names")
    246 put_new(Name_0f, "8c", "jump disp32 bytes away if lesser, if SF != OF (jcc/jl/jnge)");
    247
    248 :(code)
    249 void test_jl_disp32_success() {
    250   ZF = false;
    251   SF = true;
    252   OF = false;
    253   run(
    254       "== 0x1\n"  // code segment
    255       // op     ModR/M  SIB   displacement  immediate
    256       "  0f 8c                05 00 00 00               \n"  // skip 1 instruction
    257       "  05                                 00 00 00 01 \n"
    258       "  05                                 00 00 00 02 \n"
    259   );
    260   CHECK_TRACE_CONTENTS(
    261       "run: 0x00000001 opcode: 0f\n"
    262       "run: jump 5\n"
    263       "run: 0x0000000c opcode: 05\n"
    264   );
    265   CHECK_TRACE_DOESNT_CONTAIN("run: 0x00000007 opcode: 05");
    266 }
    267
    268 :(before "End Two-Byte Opcodes Starting With 0f")
    269 case 0x8c: {  // jump disp32 if SF and !ZF
    270   const int32_t offset = next32();
    271   if (SF != OF) {
    272     trace(Callstack_depth+1, "run") << "jump " << NUM(offset) << end();
    273     EIP += offset;
    274   }
    275   break;
    276 }
    277
    278 :(code)
    279 void test_jl_disp32_fail() {
    280   ZF = false;
    281   SF = false;
    282   OF = false;
    283   run(
    284       "== 0x1\n"  // code segment
    285       // op     ModR/M  SIB   displacement  immediate
    286       "  0f 8c                05 00 00 00               \n"  // skip 1 instruction
    287       "  05                                 00 00 00 01 \n"
    288       "  05                                 00 00 00 02 \n"
    289   );
    290   CHECK_TRACE_CONTENTS(
    291       "run: 0x00000001 opcode: 0f\n"
    292       "run: 0x00000007 opcode: 05\n"
    293       "run: 0x0000000c opcode: 05\n"
    294   );
    295   CHECK_TRACE_DOESNT_CONTAIN("run: jump 5");
    296 }
    297
    298 //:: jump if lesser or equal
    299
    300 :(before "End Initialize Op Names")
    301 put_new(Name_0f, "8e", "jump disp32 bytes away if lesser or equal, if ZF is set or SF != OF (jcc/jle/jng)");
    302
    303 :(code)
    304 void test_jle_disp32_equal() {
    305   ZF = true;
    306   SF = false;
    307   OF = false;
    308   run(
    309       "== 0x1\n"  // code segment
    310       // op     ModR/M  SIB   displacement  immediate
    311       "  0f 8e                05 00 00 00               \n"  // skip 1 instruction
    312       "  05                                 00 00 00 01 \n"
    313       "  05                                 00 00 00 02 \n"
    314   );
    315   CHECK_TRACE_CONTENTS(
    316       "run: 0x00000001 opcode: 0f\n"
    317       "run: jump 5\n"
    318       "run: 0x0000000c opcode: 05\n"
    319   );
    320   CHECK_TRACE_DOESNT_CONTAIN("run: 0x00000007 opcode: 05");
    321 }
    322
    323 :(code)
    324 void test_jle_disp32_lesser() {
    325   ZF = false;
    326   SF = true;
    327   OF = false;
    328   run(
    329       "== 0x1\n"  // code segment
    330       // op     ModR/M  SIB   displacement  immediate
    331       "  0f 8e                05 00 00 00               \n"  // skip 1 instruction
    332       "  05                                 00 00 00 01 \n"
    333       "  05                                 00 00 00 02 \n"
    334   );
    335   CHECK_TRACE_CONTENTS(
    336       "run: 0x00000001 opcode: 0f\n"
    337       "run: jump 5\n"
    338       "run: 0x0000000c opcode: 05\n"
    339   );
    340   CHECK_TRACE_DOESNT_CONTAIN("run: 0x00000007 opcode: 05");
    341 }
    342
    343 :(before "End Two-Byte Opcodes Starting With 0f")
    344 case 0x8e: {  // jump disp32 if SF or ZF
    345   const int32_t offset = next32();
    346   if (ZF || SF != OF) {
    347     trace(Callstack_depth+1, "run") << "jump " << NUM(offset) << end();
    348     EIP += offset;
    349   }
    350   break;
    351 }
    352
    353 :(code)
    354 void test_jle_disp32_greater() {
    355   ZF = false;
    356   SF = false;
    357   OF = false;
    358   run(
    359       "== 0x1\n"  // code segment
    360       // op     ModR/M  SIB   displacement  immediate
    361       "  0f 8e                05 00 00 00               \n"  // skip 1 instruction
    362       "  05                                 00 00 00 01 \n"
    363       "  05                                 00 00 00 02 \n"
    364   );
    365   CHECK_TRACE_CONTENTS(
    366       "run: 0x00000001 opcode: 0f\n"
    367       "run: 0x00000007 opcode: 05\n"
    368       "run: 0x0000000c opcode: 05\n"
    369   );
    370   CHECK_TRACE_DOESNT_CONTAIN("run: jump 5");
    371 }