#!/usr/bin/python

import sys
from keystone import *

successCount = 0
testCount = 0

def printTest(x64, ip, expectedData, asm, data):
    print("  \"%s\", IP: 0x%X, Mode: %s" % (asm, ip, "x64" if x64 else "x32"))
    sys.stdout.write("Expected (%.2d) " % len(expectedData))
    for i in range(0, len(expectedData)):
        sys.stdout.write("%02X " % expectedData[i])
    print("")
    sys.stdout.write("Actual   (%.2d) " % len(data))
    for i in range(0, len(data)):
        sys.stdout.write("%02X " % data[i])
    print("\n")

def runTest(n, x64, ip, expectedData, asm):
    global successCount
    global testCount
    testCount = testCount + 1
    mode = KS_MODE_32
    if x64:
        mode = KS_MODE_64
    ks = Ks(KS_ARCH_X86, mode)
    try:
        data, _ = ks.asm(asm, ip)
        if len(expectedData) != len(data):
            print("Test %d failed: Output hex length mismatch (expected %d, actual %d)" % (n, len(expectedData), len(data)))
            printTest(x64, ip, expectedData, asm, data)
            return False
        elif expectedData != data:
            print("Test %d failed: Output hex mismatch" % n)
            printTest(x64, ip, expectedData, asm, data)
            return False
        else:
            successCount = successCount + 1
            return True
    except KsError as e:
        if len(expectedData) == 0:
            successCount = successCount + 1
            return True
        else:
            print("Test %d failed: error ks.asm: %s" % (n, e))
            printTest(x64, ip, expectedData, asm, [])
            return False

runTest(0, False, 0x77513BEE, [0xEB, 0xFE], "JMP 0x77513BEE")
runTest(1, False, 0x77513BEE, [0xEB, 0x07], "JMP 0x77513BF7")
runTest(2, False, 0x77513BEE, [0xEB, 0xCF], "JMP 0x77513BBF")
runTest(3, False, 0x405C5B, [0xE9, 0xCA, 0x70, 0x00, 0x00], "JMP 0x0040CD2A")
runTest(4, False, 0x405C5B, [0xE9, 0x40, 0xFE, 0xFF, 0xFF], "JMP 0x00405AA0")
runTest(5, False, 0x405C5B, [0xFF, 0x25, 0x00, 0x01, 0x00, 0x00], "JMP DWORD PTR DS:[0x100]")
runTest(6, False, 0x405CCC, [0xFF, 0x15, 0x10, 0x00, 0x00, 0x00], "CALL DWORD PTR DS:[0x10]")
runTest(7, False, 0x405C5B, [0xE8, 0xCA, 0x70, 0x00, 0x00], "CALL 0x0040CD2A")
runTest(8, False, 0x405EF0, [0xE8, 0x06, 0xFF, 0xFF, 0xFF], "CALL 0x00405DFB")
runTest(9, True, 0x7FFCAA022104, [0xEB, 0xFE], "JMP 0x7FFCAA022104")
runTest(10, True, 0x7FFCAA022104, [0xEB, 0x22], "JMP 0x7FFCAA022128")
runTest(11, True, 0x7FFCAA022104, [0xEB, 0xF9], "JMP 0x7FFCAA0220FF")
runTest(12, True, 0x7FFCA9FF197C, [0xE9, 0x35, 0x64, 0x93, 0x53], "JMP 0x7FFCFD927DB6")
runTest(13, True, 0x7FFCAA022104, [0xE9, 0x7C, 0xF4, 0xFC, 0xFF], "JMP 0x7FFCA9FF1585")
#runTest(14, True, 0x123456789, [0xFF, 0x25, 0xFA, 0xFF, 0xFF, 0xFF], "JMP QWORD[0x123456789]")
runTest(15, True, 0x7FFCA9FF1977, [0xFF, 0x25, 0xFA, 0x00, 0xFF, 0xFF], "JMP QWORD PTR DS:[0x7FFCA9FE1A77]")
runTest(16, False, 0x405C6A, [0xFF, 0x35, 0xF4, 0x0A, 0x47, 0x00], "PUSH DWORD PTR DS:[0x470AF4]")
runTest(17, False, 0x405C92, [0x8B, 0x45, 0x08], "MOV EAX,DWORD PTR SS:[EBP+8]")
runTest(18, False, 0x405CB8, [0xC7, 0x45, 0xF4, 0x00, 0x40, 0x99, 0x01], "MOV DWORD PTR SS:[EBP-0xC],0x1994000")
runTest(19, False, 0x405D4C, [0x8A, 0x14, 0x08], "MOV DL,BYTE PTR DS:[EAX+ECX]")
runTest(20, False, 0x405D4C, [0x0F, 0xB7, 0x4C, 0x45, 0x98], "MOVZX ECX,WORD PTR SS:[EAX*2+EBP-0x68]")
runTest(21, False, 0x405D4C, [0xC6, 0x84, 0x30, 0x1D, 0x01, 0x00, 0x00, 0x00], "MOV BYTE PTR DS:[EAX+ESI+0x11D],0")
runTest(22, False, 0x40652A, [0xC0, 0x64, 0x18, 0x50, 0xFF], "SAL BYTE PTR DS:[EAX+EBX+0x50],0xFF")
runTest(23, False, 0x405F1E, [0x6A, 0x0D], "PUSH 0xD")
runTest(24, False, 0x405F1E, [0x68, 0xFF, 0x00, 0x00, 0x00], "PUSH 0xFF")
runTest(25, False, 0x405FF9, [0x83, 0x60, 0x70, 0xFD], "AND DWORD PTR DS:[EAX+0x70],0xFFFFFFFD")
runTest(26, False, 0x405FF9, [0x81, 0x60, 0x70, 0x0D, 0x00, 0x00, 0xF0], "AND DWORD PTR DS:[EAX+0x70],0xF000000D")
runTest(27, False, 0x405C23, [0xF2, 0x0F, 0x11, 0x0D, 0x00, 0x00, 0x00, 0x00], "MOVSD QWORD PTR ds:[0x0],xmm1")
runTest(28, False, 0x405C23, [0x8B, 0x04, 0xCD, 0x00, 0x00, 0x00, 0x00], "MOV EAX,[ECX*8]")
runTest(29, False, 0x405C23, [0x60], "PUSHAD")
runTest(30, False, 0x405C23, [0xCC], "INT3")
runTest(31, False, 0x405C23, [0xCD, 0x03], "INT 3")
runTest(32, False, 0x405C23, [0xE7, 0xE9], "OUT 0xE9, EAX")
runTest(33, False, 0x405C23, [0x69, 0xC0, 0xFF, 0x01, 0x00, 0x00], "IMUL EAX, EAX, 0x1FF")
runTest(34, False, 0x405C23, [0x69, 0xC0, 0xFF, 0x00, 0x00, 0x00], "IMUL EAX, EAX, 0xFF")
runTest(35, False, 0x405C23, [0x69, 0xC0, 0xFE, 0x00, 0x00, 0x00], "IMUL EAX, EAX, 0xFE")
runTest(36, False, 0x405C23, [0x6B, 0xC0, 0x1E], "IMUL EAX, EAX, 0x1E")
runTest(37, False, 0x405C23, [0xB8, 0x78, 0x56, 0x34, 0x12], "MOV EAX, 0x12345678")
runTest(38, False, 0x405C23, [0xB8, 0xFE, 0xFF, 0xFF, 0xFF], "MOV EAX, 0xFFFFFFFE")
runTest(39, False, 0x405C23, [0xDF, 0x3C, 0x24], "FISTP QWORD PTR [ESP]")
runTest(40, False, 0x405C23, [0xD9, 0xF6], "FDECSTP")
runTest(41, False, 0x405C23, [0xD9, 0xFF], "FCOS")
runTest(42, False, 0x405C23, [0xC7, 0x85, 0xE8, 0xFD, 0xFF, 0xFF, 0x00, 0x00, 0x08, 0x02], "MOV DWORD PTR [EBP-0x218],0x2080000")
runTest(43, False, 0x405C23, [0xC7, 0x84, 0x24, 0xE8, 0xFD, 0xFF, 0xFF, 0x00, 0x00, 0x08, 0x02], "MOV DWORD PTR [ESP-0x218],0x2080000")
runTest(44, False, 0x0, [0xC7, 0x05, 0xBA, 0x55, 0x0F, 0x00, 0xFF, 0x00, 0x00, 0x00], "MOV DWORD PTR [0xF55BA], 0xFF")
runTest(45, False, 0x0, [0x66, 0xC7, 0x05, 0xBA, 0x55, 0x0F, 0x00, 0xFF, 0x00], "MOV WORD PTR [0xF55BA], 0xFF")
runTest(46, False, 0x0, [0xC6, 0x05, 0xBA, 0x55, 0x0F, 0x00, 0xFF], "MOV BYTE PTR [0xF55BA], 0xFF")
runTest(47, False, 0x405C23, [], "MOV EAX, DWORD PTR ][")
runTest(48, False, 0x405C23, [], "MOV EAX, DWORD PTR [RAX]")
runTest(49, False, 0x405C23, [], "MOV EAX, DWORD PTR [0xFFFFFFFFF]")
runTest(50, True, 0x7FFCA9FF1977, [0x48, 0xB8, 0x90, 0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x00], "MOV RAX, 0x1234567890")
runTest(51, True, 0x7FFCA9FF1977, [0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00], "MOV RAX, 0")
runTest(52, True, 0x7FFCA9FF1977, [0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00], "MOV RAX, 0x100000000")
runTest(53, True, 0x7FFCA9FF1977, [0x48, 0xC7, 0xC0, 0x8F, 0xFA, 0xFF, 0x00], "MOV RAX, 0xFFFA8F")
runTest(54, True, 0x7FFCA9FF1977, [0x48, 0xB8, 0x90, 0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x00], "MOVABS RAX, 0x1234567890")
runTest(55, True, 0x7FFCA9FF1977, [0x48, 0xB8, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF], "MOVABS RAX, 0xFFFFFFFFFFFFFFFE")
runTest(56, True, 0x7FFCA9FF1977, [0x48, 0xA1, 0x90, 0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x00], "MOV RAX, QWORD PTR DS:[0x1234567890]")
runTest(57, True, 0x7FFCA9FF1977, [0xCC], "INT3")
runTest(58, True, 0x7FFCA9FF1977, [0xCD, 0x03], "INT 3")
runTest(59, True, 0x7FFCA9FF1977, [0x48, 0x63, 0xD0], "MOVSXD RDX, EAX")
runTest(60, True, 0x7FFCA9FF1977, [0x45, 0x0F, 0xBE, 0x24, 0x2F], "MOVSX R12D, BYTE PTR [R15+RBP*1]")
runTest(61, True, 0x7FFCA9FF1977, [0x4D, 0x69, 0xED, 0x10, 0x01, 0x00, 0x00], "IMUL R13, R13, 0x110")
runTest(62, True, 0x7FFCA9FF1977, [0x4D, 0x6B, 0xED, 0x11], "IMUL R13, R13, 0x11")
runTest(63, True, 0x7FFCA9FF1977, [0x48, 0xC7, 0x05, 0xAF, 0x55, 0x0F, 0x00, 0xFF, 0x00, 0x00, 0x00], "MOV QWORD PTR [RIP+0xF55AF], 0xFF")
runTest(64, True, 0x0, [0x48, 0xC7, 0x05, 0xAF, 0x55, 0x0F, 0x00, 0xFF, 0x00, 0x00, 0x00], "MOV QWORD PTR [0xF55BA], 0xFF")
runTest(65, True, 0x7FFCA9FF1977, [0x48, 0xC7, 0x05, 0xAF, 0x55, 0x0F, 0x00, 0xFE, 0xFF, 0xFF, 0xFF], "MOV QWORD PTR [RIP+0xF55AF], 0xFFFFFFFFFFFFFFFE")
runTest(66, True, 0x7FFCA9FF1977, [0x48, 0x0F, 0xC7, 0x08], "CMPXCHG16B [RAX]")
runTest(67, True, 0x7FFCA9FF1977, [0x0F, 0xC7, 0x08], "CMPXCHG8B [RAX]")
runTest(68, True, 0x7FF6845CB974, [0x48, 0x8D, 0x15, 0xA5, 0x16, 0x25, 0x00], "LEA RDX, QWORD PTR DS:[0x7FF68481D020]")
runTest(69, True, 0x7FF6845CB974, [0x48, 0x8D, 0x15, 0xA5, 0x16, 0x25, 0x00], "LEA RDX, QWORD PTR DS:[RIP+0x2516A5]")
runTest(70, True, 0x7FF6845CB974, [0x48, 0x8D, 0x10], "LEA RDX, [RAX]")
runTest(71, True, 0x7FF6845CB982, [0x48, 0x83, 0x05, 0x63, 0x0F, 0x25, 0x00, 0x01], "ADD QWORD PTR [0x7FF68481C8ED], 0x1")
runTest(72, True, 0x7FF6845CB982, [0x48, 0x83, 0x05, 0x63, 0x0F, 0x25, 0x00, 0x01], "ADD QWORD PTR [RIP+0x250F63], 0x1")
runTest(73, True, 0x0, [0x48, 0x83, 0x05, 0xFF, 0xFF, 0xFF, 0xFF, 0x01], "ADD QWORD PTR [RIP+0xFFFFFFFF], 0x1")
runTest(74, True, 0x7FFB65E2199E, [0x48, 0x83, 0x05, 0xFF, 0xFF, 0xFF, 0xFF, 0x48], "ADD QWORD PTR [0x7FFB65E219A5], 0x48")
runTest(75, True, 0x7FEF18BC878, [0xC7, 0x05, 0x5E, 0x3B, 0xD8, 0xFF, 0x00, 0x00, 0x00, 0x00], "MOV DWORD PTR DS:[0x7FEF16403E0],0")
runTest(76, True, 0x0, [0x66, 0xC7, 0x05, 0x4B, 0xFF, 0x0F, 0x00, 0x00, 0x00], "MOV WORD PTR DS:[0xFFF54],0")
runTest(77, True, 0x0, [0xC6, 0x05, 0x4D, 0xFF, 0x0F, 0x00, 0x00], "MOV BYTE PTR DS:[0xFFF54],0")
runTest(78, False, 0x9123FFE1, [0xF3, 0x67, 0x6C], "rep insb byte ptr es:[di], dx")
runTest(79, False, 0x9123FFE1, [0xF3, 0x67, 0x6D], "rep insd dword ptr es:[di], dx")
runTest(80, False, 0x9123FFE1, [0xF3, 0x67, 0x6E], "rep outsb dx, byte ptr [si]")
runTest(81, False, 0x9123FFE1, [0xF3, 0x67, 0x6F], "rep outsd dx, dword ptr [si]")
runTest(82, False, 0x9123FFE1, [0xF3, 0x67, 0xA4], "rep movsb byte ptr es:[di], byte ptr [si]")
runTest(83, False, 0x9123FFE1, [0xF3, 0x67, 0xA5], "rep movsd dword ptr es:[di], dword ptr [si]")
runTest(84, False, 0x9123FFE1, [0xF3, 0x67, 0xA6], "repe cmpsb byte ptr [si], byte ptr es:[di]")
runTest(85, False, 0x9123FFE1, [0xF3, 0x67, 0xA7], "repe cmpsd dword ptr [si], dword ptr es:[di]")
runTest(86, False, 0x9123FFE1, [0xF3, 0x67, 0xAA], "rep stosb byte ptr es:[di], al")
runTest(87, False, 0x9123FFE1, [0xF3, 0x67, 0xAB], "rep stosd dword ptr es:[di], eax")
runTest(88, False, 0x9123FFE1, [0xF3, 0x67, 0xAC], "rep lodsb al, byte ptr [si]")
runTest(89, False, 0x9123FFE1, [0xF3, 0x67, 0xAD], "rep lodsd eax, dword ptr [si]")
runTest(90, False, 0x9123FFE1, [0xF3, 0x67, 0xAE], "repe scasb al, byte ptr es:[di]")
runTest(91, False, 0x9123FFE1, [0xF3, 0x67, 0xAF], "repe scasd eax, dword ptr es:[di]")
runTest(92, False, 0x9123FFE1, [0xF2, 0x6C], "repne insb byte ptr es:[edi], dx")
runTest(93, False, 0x9123FFE1, [0xF2, 0x66, 0x6D], "repne insw word ptr es:[edi], dx")
runTest(94, False, 0x9123FFE1, [0xF2, 0x6E], "repne outsb dx, byte ptr [esi]")
runTest(95, False, 0x9123FFE1, [0xF2, 0x66, 0x6F], "repne outsw dx, word ptr [esi]")
runTest(96, False, 0x9123FFE1, [0xF2, 0xA4], "repne movsb byte ptr es:[edi], byte ptr [esi]")
runTest(97, False, 0x9123FFE1, [0xF2, 0x66, 0xA5], "repne movsw word ptr es:[edi], word ptr [esi]")
runTest(98, False, 0x9123FFE1, [0xF2, 0xA6], "repne cmpsb byte ptr [esi], byte ptr es:[edi]")
runTest(99, False, 0x9123FFE1, [0xF2, 0x66, 0xA7], "repne cmpsw word ptr [esi], word ptr es:[edi]")
runTest(100, False, 0x9123FFE1, [0xF2, 0xAA], "repne stosb byte ptr es:[edi], al")
runTest(101, False, 0x9123FFE1, [0xF2, 0x66, 0xAB], "repne stosw word ptr es:[edi], ax")
runTest(102, False, 0x9123FFE1, [0xF2, 0xAC], "repne lodsb al, byte ptr [esi]")
runTest(103, False, 0x9123FFE1, [0xF2, 0x66, 0xAD], "repne lodsw ax, word ptr [esi]")
runTest(104, False, 0x9123FFE1, [0xF2, 0xAE], "repne scasb al, byte ptr es:[edi]")
runTest(105, False, 0x9123FFE1, [0xF2, 0x66, 0xAF], "repne scasw ax, word ptr es:[edi]")
runTest(106, False, 0x9123FFE1, [0xF3, 0x67, 0x6C], "rep insb byte ptr es:[di], dx")
runTest(107, False, 0x9123FFE1, [0xF3, 0x66, 0x67, 0x6D], "rep insw word ptr es:[di], dx")
runTest(108, False, 0x9123FFE1, [0xF3, 0x67, 0x6E], "rep outsb dx, byte ptr [si]")
runTest(109, False, 0x9123FFE1, [0xF3, 0x66, 0x67, 0x6F], "rep outsw dx, word ptr [si]")
runTest(110, False, 0x9123FFE1, [0xF3, 0x67, 0xA4], "rep movsb byte ptr es:[di], byte ptr [si]")
runTest(111, False, 0x9123FFE1, [0xF3, 0x66, 0x67, 0xA5], "rep movsw word ptr es:[di], word ptr [si]")
runTest(112, False, 0x9123FFE1, [0xF3, 0x67, 0xA6], "repe cmpsb byte ptr [si], byte ptr es:[di]")
runTest(113, False, 0x9123FFE1, [0xF3, 0x66, 0x67, 0xA7], "repe cmpsw word ptr [si], word ptr es:[di]")
runTest(114, False, 0x9123FFE1, [0xF3, 0x67, 0xAA], "rep stosb byte ptr es:[di], al")
runTest(115, False, 0x9123FFE1, [0xF3, 0x66, 0x67, 0xAB], "rep stosw word ptr es:[di], ax")
runTest(116, False, 0x9123FFE1, [0xF3, 0x67, 0xAC], "rep lodsb al, byte ptr [si]")
runTest(117, False, 0x9123FFE1, [0xF3, 0x66, 0x67, 0xAD], "rep lodsw ax, word ptr [si]")
runTest(118, False, 0x9123FFE1, [0xF3, 0x67, 0xAE], "repe scasb al, byte ptr es:[di]")
runTest(119, False, 0x9123FFE1, [0xF3, 0x66, 0x67, 0xAF], "repe scasw ax, word ptr es:[di]")
runTest(120, False, 0x9123FFE1, [0xF3, 0x6C], "rep insb byte ptr es:[edi], dx")
runTest(121, False, 0x9123FFE1, [0xF3, 0x6D], "rep insd dword ptr es:[edi], dx")
runTest(122, False, 0x9123FFE1, [0xF3, 0x6E], "rep outsb dx, byte ptr [esi]")
runTest(123, False, 0x9123FFE1, [0xF3, 0x6F], "rep outsd dx, dword ptr [esi]")
runTest(124, False, 0x9123FFE1, [0xF3, 0xA4], "rep movsb byte ptr es:[edi], byte ptr [esi]")
runTest(125, False, 0x9123FFE1, [0xF3, 0xA5], "rep movsd dword ptr es:[edi], dword ptr [esi]")
runTest(126, False, 0x9123FFE1, [0xF3, 0xA6], "repe cmpsb byte ptr [esi], byte ptr es:[edi]")
runTest(127, False, 0x9123FFE1, [0xF3, 0xA7], "repe cmpsd dword ptr [esi], dword ptr es:[edi]")
runTest(128, False, 0x9123FFE1, [0xF3, 0xAA], "rep stosb byte ptr es:[edi], al")
runTest(129, False, 0x9123FFE1, [0xF3, 0xAB], "rep stosd dword ptr es:[edi], eax")
runTest(130, False, 0x9123FFE1, [0xF3, 0xAC], "rep lodsb al, byte ptr [esi]")
runTest(131, False, 0x9123FFE1, [0xF3, 0xAD], "rep lodsd eax, dword ptr [esi]")
runTest(132, False, 0x9123FFE1, [0xF3, 0xAE], "repe scasb al, byte ptr es:[edi]")
runTest(133, False, 0x9123FFE1, [0xF3, 0xAF], "repe scasd eax, dword ptr es:[edi]")
runTest(134, False, 0x9123FFE1, [0x6C], "insb byte ptr es:[edi], dx")
runTest(135, False, 0x9123FFE1, [0x6D], "insd dword ptr es:[edi], dx")
runTest(136, False, 0x9123FFE1, [0x6E], "outsb dx, byte ptr [esi]")
runTest(137, False, 0x9123FFE1, [0x6F], "outsd dx, dword ptr [esi]")
runTest(138, False, 0x9123FFE1, [0xA4], "movsb byte ptr es:[edi], byte ptr [esi]")
runTest(139, False, 0x9123FFE1, [0xA5], "movsd dword ptr es:[edi], dword ptr [esi]")
runTest(140, False, 0x9123FFE1, [0xA6], "cmpsb byte ptr [esi], byte ptr es:[edi]")
runTest(141, False, 0x9123FFE1, [0xA7], "cmpsd dword ptr [esi], dword ptr es:[edi]")
runTest(142, False, 0x9123FFE1, [0xAA], "stosb byte ptr es:[edi], al")
runTest(143, False, 0x9123FFE1, [0xAB], "stosd dword ptr es:[edi], eax")
runTest(144, False, 0x9123FFE1, [0xAC], "lodsb al, byte ptr [esi]")
runTest(145, False, 0x9123FFE1, [0xAD], "lodsd eax, dword ptr [esi]")
runTest(146, False, 0x9123FFE1, [0xAE], "scasb al, byte ptr es:[edi]")
runTest(147, False, 0x9123FFE1, [0xAF], "scasd eax, dword ptr es:[edi]")
print("%d/%d tests were successful!" % (successCount, testCount))
