diff options
| -rw-r--r-- | CHANGELOG | 5 | ||||
| -rw-r--r-- | src/long_mode/display.rs | 5 | ||||
| -rw-r--r-- | src/long_mode/mod.rs | 2 | ||||
| -rw-r--r-- | src/protected_mode/display.rs | 5 | ||||
| -rw-r--r-- | src/protected_mode/mod.rs | 7 | ||||
| -rw-r--r-- | src/real_mode/display.rs | 5 | ||||
| -rw-r--r-- | test/long_mode/mod.rs | 11 | ||||
| -rw-r--r-- | test/protected_mode/mod.rs | 13 | ||||
| -rw-r--r-- | test/real_mode/mod.rs | 3 | 
9 files changed, 41 insertions, 15 deletions
@@ -1,3 +1,8 @@ +## 1.3.0 + +* fix 32-bit call/jmp not respecting 66 prefix if set - such cases use 16-bit +  operands, but decoded as if they used 32-bit operands. +  ## 1.2.2  * fix `hreset` reporting two operands, with a second operand of `Nothing`. diff --git a/src/long_mode/display.rs b/src/long_mode/display.rs index f765fb7..4f4e739 100644 --- a/src/long_mode/display.rs +++ b/src/long_mode/display.rs @@ -4245,9 +4245,8 @@ impl <T: fmt::Write, Y: YaxColors> ShowContextual<u64, [Option<alloc::string::St      }  } -// TODO: should include CALL -static RELATIVE_BRANCHES: [Opcode; 21] = [ -    Opcode::JMP, Opcode::JRCXZ, +static RELATIVE_BRANCHES: [Opcode; 22] = [ +    Opcode::JMP, Opcode::CALL, Opcode::JRCXZ,      Opcode::LOOP, Opcode::LOOPZ, Opcode::LOOPNZ,      Opcode::JO, Opcode::JNO,      Opcode::JB, Opcode::JNB, diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs index fab8fde..3c25506 100644 --- a/src/long_mode/mod.rs +++ b/src/long_mode/mod.rs @@ -7660,6 +7660,8 @@ fn read_operands<                      .with_id(modrm_start - 8)              );              if instruction.operands[0] == OperandSpec::RegMMM { +                // in 64-bit mode, operand size overrides do not actually shink the operand for +                // `call`/`jmp`.                  if opcode == Opcode::CALL || opcode == Opcode::JMP {                      instruction.regs[1].bank = RegisterBank::Q;                      if opcode == Opcode::CALL { diff --git a/src/protected_mode/display.rs b/src/protected_mode/display.rs index 38b5891..1db34cb 100644 --- a/src/protected_mode/display.rs +++ b/src/protected_mode/display.rs @@ -2797,9 +2797,8 @@ impl <T: fmt::Write, Y: YaxColors> ShowContextual<u64, [Option<alloc::string::St      }  } -// TODO: should include CALL -static RELATIVE_BRANCHES: [Opcode; 21] = [ -    Opcode::JMP, Opcode::JECXZ, +static RELATIVE_BRANCHES: [Opcode; 22] = [ +    Opcode::JMP, Opcode::CALL, Opcode::JECXZ,      Opcode::LOOP, Opcode::LOOPZ, Opcode::LOOPNZ,      Opcode::JO, Opcode::JNO,      Opcode::JB, Opcode::JNB, diff --git a/src/protected_mode/mod.rs b/src/protected_mode/mod.rs index f2b10f5..38f8310 100644 --- a/src/protected_mode/mod.rs +++ b/src/protected_mode/mod.rs @@ -7529,11 +7529,8 @@ fn read_operands<                      .with_id(modrm_start - 8)              );              if instruction.operands[0] == OperandSpec::RegMMM { -                if opcode == Opcode::CALL || opcode == Opcode::JMP { -                    instruction.regs[1].bank = RegisterBank::D; -                    if opcode == Opcode::CALL { -                        instruction.mem_size = 4; -                    } +                if opcode == Opcode::CALL { +                    instruction.mem_size = 4;                  } else if opcode == Opcode::PUSH || opcode == Opcode::POP {                      if instruction.prefixes.operand_size() {                          instruction.mem_size = 2; diff --git a/src/real_mode/display.rs b/src/real_mode/display.rs index b76f47e..90b4f0a 100644 --- a/src/real_mode/display.rs +++ b/src/real_mode/display.rs @@ -2797,9 +2797,8 @@ impl <T: fmt::Write, Y: YaxColors> ShowContextual<u64, [Option<alloc::string::St      }  } -// TODO: should include CALL -static RELATIVE_BRANCHES: [Opcode; 21] = [ -    Opcode::JMP, Opcode::JCXZ, +static RELATIVE_BRANCHES: [Opcode; 22] = [ +    Opcode::JMP, Opcode::CALL, Opcode::JCXZ,      Opcode::LOOP, Opcode::LOOPZ, Opcode::LOOPNZ,      Opcode::JO, Opcode::JNO,      Opcode::JB, Opcode::JNB, diff --git a/test/long_mode/mod.rs b/test/long_mode/mod.rs index d8cb0ef..917d16a 100644 --- a/test/long_mode/mod.rs +++ b/test/long_mode/mod.rs @@ -1303,14 +1303,25 @@ fn test_control_flow() {      test_display(&[0x73, 0x31], "jnb $+0x31");      test_display(&[0x72, 0x5a], "jb $+0x5a");      test_display(&[0x72, 0xf0], "jb $-0x10"); +    test_display(&[0xe8, 0x01, 0x00, 0x00, 0x00], "call $+0x1"); +    test_display(&[0xe8, 0x80, 0x00, 0x00, 0x00], "call $+0x80"); +    test_display(&[0xe8, 0xff, 0xff, 0xff, 0xff], "call $-0x1"); +    test_display(&[0xe9, 0x01, 0x00, 0x00, 0x00], "jmp $+0x1"); +    test_display(&[0xe9, 0x80, 0x00, 0x00, 0x00], "jmp $+0x80"); +    test_display(&[0xe9, 0xff, 0xff, 0xff, 0xff], "jmp $-0x1");      test_display(&[0x0f, 0x86, 0x8b, 0x01, 0x00, 0x00], "jna $+0x18b");      test_display(&[0x0f, 0x85, 0x3b, 0x25, 0x00, 0x00], "jnz $+0x253b");      test_display(&[0x74, 0x47], "jz $+0x47");      test_display(&[0xff, 0x15, 0x7e, 0x72, 0x24, 0x00], "call qword [rip + 0x24727e]"); +    test_display(&[0xff, 0x15, 0x7e, 0x72, 0x24, 0x00], "call qword [rip + 0x24727e]");      test_display(&[0xff, 0x24, 0xcd, 0x70, 0xa0, 0xbc, 0x01], "jmp qword [rcx * 8 + 0x1bca070]"); +    test_display(&[0xff, 0x14, 0xcd, 0x70, 0xa0, 0xbc, 0x01], "call qword [rcx * 8 + 0x1bca070]");      test_display(&[0xff, 0xe0], "jmp rax"); +    test_display(&[0xff, 0xd0], "call rax");      test_display(&[0x66, 0xff, 0xe0], "jmp rax");      test_display(&[0x67, 0xff, 0xe0], "jmp rax"); +    test_display(&[0x66, 0xff, 0xd0], "call rax"); +    test_display(&[0x67, 0xff, 0xd0], "call rax");      test_invalid(&[0xff, 0xd8]);      test_display(&[0xff, 0x18], "callf mword [rax]");      test_display(&[0xe0, 0x12], "loopnz $+0x12"); diff --git a/test/protected_mode/mod.rs b/test/protected_mode/mod.rs index 0f3a6ff..8fecdab 100644 --- a/test/protected_mode/mod.rs +++ b/test/protected_mode/mod.rs @@ -1123,13 +1123,24 @@ fn test_control_flow() {      test_display(&[0x73, 0x31], "jnb $+0x31");      test_display(&[0x72, 0x5a], "jb $+0x5a");      test_display(&[0x72, 0xf0], "jb $-0x10"); +    test_display(&[0xe8, 0x01, 0x00, 0x00, 0x00], "call $+0x1"); +    test_display(&[0xe8, 0x80, 0x00, 0x00, 0x00], "call $+0x80"); +    test_display(&[0xe8, 0xff, 0xff, 0xff, 0xff], "call $-0x1"); +    test_display(&[0xe9, 0x01, 0x00, 0x00, 0x00], "jmp $+0x1"); +    test_display(&[0xe9, 0x80, 0x00, 0x00, 0x00], "jmp $+0x80"); +    test_display(&[0xe9, 0xff, 0xff, 0xff, 0xff], "jmp $-0x1");      test_display(&[0x0f, 0x86, 0x8b, 0x01, 0x00, 0x00], "jna $+0x18b"); +    test_display(&[0x0f, 0x85, 0x3b, 0x25, 0x00, 0x00], "jnz $+0x253b");      test_display(&[0x74, 0x47], "jz $+0x47");      test_display(&[0xff, 0x15, 0x7e, 0x72, 0x24, 0x00], "call dword [0x24727e]");      test_display(&[0xff, 0x24, 0xcd, 0x70, 0xa0, 0xbc, 0x01], "jmp dword [ecx * 8 + 0x1bca070]"); +    test_display(&[0xff, 0x14, 0xcd, 0x70, 0xa0, 0xbc, 0x01], "call dword [ecx * 8 + 0x1bca070]");      test_display(&[0xff, 0xe0], "jmp eax"); -    test_display(&[0x66, 0xff, 0xe0], "jmp eax"); +    test_display(&[0xff, 0xd0], "call eax"); +    test_display(&[0x66, 0xff, 0xe0], "jmp ax");      test_display(&[0x67, 0xff, 0xe0], "jmp eax"); +    test_display(&[0x66, 0xff, 0xd0], "call ax"); +    test_display(&[0x67, 0xff, 0xd0], "call eax");      test_invalid(&[0xff, 0xd8]);      test_display(&[0xff, 0x18], "callf far [eax]");      test_display(&[0xe0, 0x12], "loopnz $+0x12"); diff --git a/test/real_mode/mod.rs b/test/real_mode/mod.rs index c5b1548..844a95e 100644 --- a/test/real_mode/mod.rs +++ b/test/real_mode/mod.rs @@ -16950,6 +16950,7 @@ fn test_real_mode() {      test_display(&[0x66, 0xf3, 0x0f, 0x01, 0xe8], "setssbsy");      test_display(&[0x66, 0xf3, 0x0f, 0x01, 0xea], "saveprevssp");      test_display(&[0x66, 0xf3, 0x0f, 0xbd, 0xc1], "lzcnt eax, ecx"); +    test_display(&[0x66, 0xff, 0xd0], "call eax");      test_display(&[0x66, 0xff, 0xe0], "jmp eax");      test_display(&[0x67, 0x0f, 0x5b, 0x01], "cvtdq2ps xmm0, xmmword [ecx]");      test_display(&[0x67, 0x66, 0x0f, 0x28, 0x00], "movapd xmm0, xmmword [eax]"); @@ -16960,6 +16961,7 @@ fn test_real_mode() {      test_display(&[0x67, 0x66, 0x0f, 0x38, 0xdf, 0x0f], "aesdeclast xmm1, xmmword [edi]");      test_display(&[0x67, 0x66, 0x65, 0x3e, 0x0f, 0x6d, 0xd1], "punpckhqdq xmm2, xmm1");      test_display(&[0x67, 0xe5, 0x99], "in ax, 0x99"); +    test_display(&[0x67, 0xff, 0xd0], "call ax");      test_display(&[0x67, 0xff, 0xe0], "jmp ax");      test_display(&[0x68, 0x7f, 0x63], "push 0x637f");      test_display(&[0x6b, 0x43, 0x6f, 0x6d], "imul ax, word [bp + di * 1 + 0x6f], 0x6d"); @@ -17945,6 +17947,7 @@ fn test_real_mode() {      test_display(&[0xff, 0x75, 0x08], "push word [di + 0x8]");      test_display(&[0xff, 0x75, 0xb8], "push word [di - 0x48]");      test_display(&[0xff, 0xe0], "jmp ax"); +    test_display(&[0xff, 0xd0], "call ax");  }  #[test]  | 
