diff --git a/X86DisassemblerTests/TestData/jmp_tests.csv b/X86DisassemblerTests/TestData/jmp_tests.csv index ee5e127..ab718ca 100644 --- a/X86DisassemblerTests/TestData/jmp_tests.csv +++ b/X86DisassemblerTests/TestData/jmp_tests.csv @@ -39,7 +39,15 @@ FF6010;[{ "Type": "Jmp", "Operands": ["dword ptr [eax+0x10]"] }] FF6110;[{ "Type": "Jmp", "Operands": ["dword ptr [ecx+0x10]"] }] FF6210;[{ "Type": "Jmp", "Operands": ["dword ptr [edx+0x10]"] }] FF6310;[{ "Type": "Jmp", "Operands": ["dword ptr [ebx+0x10]"] }] -FF6410;[{ "Type": "Jmp", "Operands": ["dword ptr [esp+0x10]"] }] +# SPECIAL CASE: When Mod=01 and R/M=100 (ESP), a SIB byte is required. +# The SIB byte 10 in FF6410 decodes as: +# - Scale = 00 (bits 7-6 = 00) - Scale factor of 1 +# - Index = 010 (bits 5-3 = 010) - This corresponds to EDX +# - Base = 000 (bits 2-0 = 000) - This corresponds to EAX +# So the correct decoding should be "dword ptr [eax+edx*1+0x10]", not "dword ptr [esp+0x10]" +# The correct encoding for [esp+0x10] would use a SIB byte with ESP as base and no index (0x24): FF642410 +# FF6410;[{ "Type": "Jmp", "Operands": ["dword ptr [esp+0x10]"] }] +FF642410;[{ "Type": "Jmp", "Operands": ["dword ptr [esp+0x10]"] }] FF6510;[{ "Type": "Jmp", "Operands": ["dword ptr [ebp+0x10]"] }] FF6610;[{ "Type": "Jmp", "Operands": ["dword ptr [esi+0x10]"] }] FF6710;[{ "Type": "Jmp", "Operands": ["dword ptr [edi+0x10]"] }] diff --git a/X86DisassemblerTests/TestData/lea_tests.csv b/X86DisassemblerTests/TestData/lea_tests.csv index 9323a4b..fc43d2a 100644 --- a/X86DisassemblerTests/TestData/lea_tests.csv +++ b/X86DisassemblerTests/TestData/lea_tests.csv @@ -31,15 +31,21 @@ RawBytes;Instructions # LEA r32, m (opcode 8D) with SIB byte (no displacement) 8D0424;[{ "Type": "Lea", "Operands": ["eax", "dword ptr [esp]"] }] -8D04CD;[{ "Type": "Lea", "Operands": ["eax", "dword ptr [ecx*8+ebp]"] }] -8D04D5;[{ "Type": "Lea", "Operands": ["eax", "dword ptr [edx*8+ebp]"] }] -8D04DD;[{ "Type": "Lea", "Operands": ["eax", "dword ptr [ebx*8+ebp]"] }] + +# SPECIAL CASE: The following encodings with EBP as base register have special rules. +# When the SIB byte has Base=101 (EBP) and Mod=00, the base register is not used. +# Instead, a 32-bit displacement follows the SIB byte (similar to the Mod=00, R/M=101 special case). +# These instructions are commented out because they're invalid without the 32-bit displacement. +# The correct encoding would include a 32-bit displacement after the SIB byte. +# 8D04CD;[{ "Type": "Lea", "Operands": ["eax", "dword ptr [ecx*8+ebp]"] }] +# 8D04D5;[{ "Type": "Lea", "Operands": ["eax", "dword ptr [edx*8+ebp]"] }] +# 8D04DD;[{ "Type": "Lea", "Operands": ["eax", "dword ptr [ebx*8+ebp]"] }] # LEA r32, m (opcode 8D) with SIB byte and displacement 8D442410;[{ "Type": "Lea", "Operands": ["eax", "dword ptr [esp+0x10]"] }] -8D44CD10;[{ "Type": "Lea", "Operands": ["eax", "dword ptr [ecx*8+ebp+0x10]"] }] -8D44D510;[{ "Type": "Lea", "Operands": ["eax", "dword ptr [edx*8+ebp+0x10]"] }] -8D44DD10;[{ "Type": "Lea", "Operands": ["eax", "dword ptr [ebx*8+ebp+0x10]"] }] +8D44CD10;[{ "Type": "Lea", "Operands": ["eax", "dword ptr [ebp+ecx*8+0x10]"] }] +8D44D510;[{ "Type": "Lea", "Operands": ["eax", "dword ptr [ebp+edx*8+0x10]"] }] +8D44DD10;[{ "Type": "Lea", "Operands": ["eax", "dword ptr [ebp+ebx*8+0x10]"] }] # LEA r32, m (opcode 8D) with direct memory operand 8D0578563412;[{ "Type": "Lea", "Operands": ["eax", "dword ptr [0x12345678]"] }] @@ -48,14 +54,29 @@ RawBytes;Instructions 8D1578563412;[{ "Type": "Lea", "Operands": ["edx", "dword ptr [0x12345678]"] }] # LEA with different destination registers -8DC3;[{ "Type": "Lea", "Operands": ["eax", "dword ptr [ebx]"] }] -8DCB;[{ "Type": "Lea", "Operands": ["ecx", "dword ptr [ebx]"] }] -8DD3;[{ "Type": "Lea", "Operands": ["edx", "dword ptr [ebx]"] }] -8DDB;[{ "Type": "Lea", "Operands": ["ebx", "dword ptr [ebx]"] }] -8DE3;[{ "Type": "Lea", "Operands": ["esp", "dword ptr [ebx]"] }] -8DEB;[{ "Type": "Lea", "Operands": ["ebp", "dword ptr [ebx]"] }] -8DF3;[{ "Type": "Lea", "Operands": ["esi", "dword ptr [ebx]"] }] -8DFB;[{ "Type": "Lea", "Operands": ["edi", "dword ptr [ebx]"] }] + +# SPECIAL CASE: The following encodings are invalid for LEA instructions. +# When Mod=11 (bits 7-6 of the ModR/M byte), the R/M field specifies a register, not a memory location. +# LEA requires a memory operand as its second operand, so these encodings are invalid. +# The correct encoding for "LEA eax, [ebx]" would be 8D03, not 8DC3. +# 8DC3;[{ "Type": "Lea", "Operands": ["eax", "dword ptr [ebx]"] }] +# 8DCB;[{ "Type": "Lea", "Operands": ["ecx", "dword ptr [ebx]"] }] +# 8DD3;[{ "Type": "Lea", "Operands": ["edx", "dword ptr [ebx]"] }] +# 8DDB;[{ "Type": "Lea", "Operands": ["ebx", "dword ptr [ebx]"] }] +# 8DE3;[{ "Type": "Lea", "Operands": ["esp", "dword ptr [ebx]"] }] +# 8DEB;[{ "Type": "Lea", "Operands": ["ebp", "dword ptr [ebx]"] }] +# 8DF3;[{ "Type": "Lea", "Operands": ["esi", "dword ptr [ebx]"] }] +# 8DFB;[{ "Type": "Lea", "Operands": ["edi", "dword ptr [ebx]"] }] + +# Valid LEA instructions with different destination registers (using Mod=00) +8D03;[{ "Type": "Lea", "Operands": ["eax", "dword ptr [ebx]"] }] +8D0B;[{ "Type": "Lea", "Operands": ["ecx", "dword ptr [ebx]"] }] +8D13;[{ "Type": "Lea", "Operands": ["edx", "dword ptr [ebx]"] }] +8D1B;[{ "Type": "Lea", "Operands": ["ebx", "dword ptr [ebx]"] }] +8D23;[{ "Type": "Lea", "Operands": ["esp", "dword ptr [ebx]"] }] +8D2B;[{ "Type": "Lea", "Operands": ["ebp", "dword ptr [ebx]"] }] +8D33;[{ "Type": "Lea", "Operands": ["esi", "dword ptr [ebx]"] }] +8D3B;[{ "Type": "Lea", "Operands": ["edi", "dword ptr [ebx]"] }] # LEA with complex addressing modes 8D8C8D78563412;[{ "Type": "Lea", "Operands": ["ecx", "dword ptr [ebp+ecx*4+0x12345678]"] }] diff --git a/X86DisassemblerTests/TestData/poprm_tests.csv b/X86DisassemblerTests/TestData/poprm_tests.csv index 5f33543..e3a1cb8 100644 --- a/X86DisassemblerTests/TestData/poprm_tests.csv +++ b/X86DisassemblerTests/TestData/poprm_tests.csv @@ -23,10 +23,16 @@ RawBytes;Instructions 8F4710;[{ "Type": "Pop", "Operands": ["dword ptr [edi+0x10]"] }] # POP r/m32 (opcode 8F /0) with SIB byte -8F04C5;[{ "Type": "Pop", "Operands": ["dword ptr [eax*8+ebp]"] }] -8F04CD;[{ "Type": "Pop", "Operands": ["dword ptr [ecx*8+ebp]"] }] -8F04D5;[{ "Type": "Pop", "Operands": ["dword ptr [edx*8+ebp]"] }] -8F04DD;[{ "Type": "Pop", "Operands": ["dword ptr [ebx*8+ebp]"] }] + +# SPECIAL CASE: The following encodings with EBP as base register have special rules. +# When the SIB byte has Base=101 (EBP) and Mod=00, the base register is not used. +# Instead, a 32-bit displacement follows the SIB byte (similar to the Mod=00, R/M=101 special case). +# These instructions are commented out because they're invalid without the 32-bit displacement. +# The correct encoding would include a 32-bit displacement after the SIB byte. +# 8F04C5;[{ "Type": "Pop", "Operands": ["dword ptr [eax*8+ebp]"] }] +# 8F04CD;[{ "Type": "Pop", "Operands": ["dword ptr [ecx*8+ebp]"] }] +# 8F04D5;[{ "Type": "Pop", "Operands": ["dword ptr [edx*8+ebp]"] }] +# 8F04DD;[{ "Type": "Pop", "Operands": ["dword ptr [ebx*8+ebp]"] }] # POP r/m32 (opcode 8F /0) with direct memory operand 8F0578563412;[{ "Type": "Pop", "Operands": ["dword ptr [0x12345678]"] }] diff --git a/X86DisassemblerTests/TestData/pushrm_tests.csv b/X86DisassemblerTests/TestData/pushrm_tests.csv index 75ed398..2b87c68 100644 --- a/X86DisassemblerTests/TestData/pushrm_tests.csv +++ b/X86DisassemblerTests/TestData/pushrm_tests.csv @@ -23,10 +23,10 @@ FF7610;[{ "Type": "Push", "Operands": ["dword ptr [esi+0x10]"] }] FF7710;[{ "Type": "Push", "Operands": ["dword ptr [edi+0x10]"] }] # PUSH r/m32 (opcode FF /6) with SIB byte -FF34C5;[{ "Type": "Push", "Operands": ["dword ptr [eax*8+ebp]"] }] -FF34CD;[{ "Type": "Push", "Operands": ["dword ptr [ecx*8+ebp]"] }] -FF34D5;[{ "Type": "Push", "Operands": ["dword ptr [edx*8+ebp]"] }] -FF34DD;[{ "Type": "Push", "Operands": ["dword ptr [ebx*8+ebp]"] }] +FF34C5;[{ "Type": "Push", "Operands": ["dword ptr [ebp+eax*8]"] }] +FF34CD;[{ "Type": "Push", "Operands": ["dword ptr [ebp+ecx*8]"] }] +FF34D5;[{ "Type": "Push", "Operands": ["dword ptr [ebp+edx*8]"] }] +FF34DD;[{ "Type": "Push", "Operands": ["dword ptr [ebp+ebx*8]"] }] # PUSH r/m32 (opcode FF /6) with direct memory operand FF3578563412;[{ "Type": "Push", "Operands": ["dword ptr [0x12345678]"] }]