-- Generates lots and lots of x86 instructions -- -- Visit http://www.the-interweb.com :) import Data.List -- Defines the mnemonics and their possible operands mnemonics = [ ("jcxz", jcc_targets), -- Start with the jcxz and other instructions which only support relative jumps and can not be used later ("jecxz", jcc_targets), ("loop", [[["start"]]]), ("loope", [[["start"]]]), ("loopne", [[["start"]]]), ("aaa", no_operands), ("aad", no_operands), ("aam", no_operands), ("aas", no_operands), ("adc", typical_binary), ("add", typical_binary), ("and", typical_binary), ("bound", [[r16, "someDword" : mem32], [r32, "someDword" : mem64]]), ("bsf", [[r16, r16], [r32, r32], [r16, mem16], [r32, mem32]]), ("bsr", [[r16, r16], [r32, r32], [r16, mem16], [r32, mem32]]), ("bsr", [[r16, r16], [r32, r32], [r16, mem16], [r32, mem32]]), ("bswap", [[r32]]), ("bt", [[mem16, imm8], [mem32, imm8], [r16, imm8], [r32, imm8], [mem16, r16], [mem32, r32]]), ("btc", [[mem16, imm8], [mem32, imm8], [r16, imm8], [r32, imm8], [mem16, r16], [mem32, r32]]), ("btr", [[mem16, imm8], [mem32, imm8], [r16, imm8], [r32, imm8], [mem16, r16], [mem32, r32]]), ("bts", [[mem16, imm8], [mem32, imm8], [r16, imm8], [r32, imm8], [mem16, r16], [mem32, r32]]), ("call", [[r32], [mem32], [["start"]]]), ("cbw", no_operands), ("cdq", no_operands), ("clc", no_operands), ("cld", no_operands), ("cli", no_operands), ("cmc", no_operands), ("cmp", typical_binary), ("cmpsb", no_operands), ("cmpsw", no_operands), ("cmpsd", no_operands), ("cmpxchg", [[r32, r32], [mem32, r32]]), ("cwd", no_operands), ("cwde", no_operands), ("daa", no_operands), ("das", no_operands), ("dec", rvalues), ("div", rvalues), ("enter", [[["2"], ["2"]]]), ("hlt", no_operands), ("idiv", rvalues), ("imul", imul), ("inc", rvalues), ("int", [[["3"]]]), ("ja", jcc_targets), ("jae", jcc_targets), ("jb", jcc_targets), ("jbe", jcc_targets), ("jc", jcc_targets), ("je", jcc_targets), ("jg", jcc_targets), ("jge", jcc_targets), ("jl", jcc_targets), ("jle", jcc_targets), ("jmp", jcc_targets), ("jna", jcc_targets), ("jnae", jcc_targets), ("jnb", jcc_targets), ("jnbe", jcc_targets), ("jnc", jcc_targets), ("jne", jcc_targets), ("jng", jcc_targets), ("jnge", jcc_targets), ("jnl", jcc_targets), ("jnle", jcc_targets), ("jno", jcc_targets), ("jnp", jcc_targets), ("jns", jcc_targets), ("jnz", jcc_targets), ("jo", jcc_targets), ("jp", jcc_targets), ("jpe", jcc_targets), ("jpo", jcc_targets), ("js", jcc_targets), ("jz", jcc_targets), ("lahf", no_operands), ("lds", [[r16, mem32]]), ("lea", [[r16, mem16]]), ("lea", [[r32, mem32]]), ("leave", no_operands), ("les", [[r16, mem32]]), ("lfs", [[r16, mem32]]), ("lgs", [[r16, mem32]]), ("lodsb", no_operands), ("lodsw", no_operands), ("lodsd", no_operands), ("lss", [[r16, mem32]]), ("mov", typical_binary), ("movsx", extend), ("movzx", extend), ("movsb", no_operands), ("movsw", no_operands), ("movsd", no_operands), ("mul", rvalues), ("neg", rvalues), ("nop", no_operands), ("not", rvalues), ("or", typical_binary), ("pop", [[segments_writable], [r16], [mem16], [r32], [mem32]]), ("popa", no_operands), ("popad", no_operands), ("push", [segments] : [[r16], [mem16], [imm16]] ++ [[r32], [mem32], [imm32]]), ("pusha", no_operands), ("pushad", no_operands), ("rcl", rotate), ("rcr", rotate), ("rep", [[["movsb"]], [["movsw"]], [["movsd"]], [["lodsb"]], [["lodsw"]], [["lodsd"]], [["stosb"]], [["stosw"]], [["stosd"]]]), ("repe", [[["cmpsb"]], [["cmpsw"]], [["cmpsd"]], [["scasb"]], [["scasw"]], [["scasd"]]]), ("repne", [[["cmpsb"]], [["cmpsw"]], [["cmpsd"]], [["scasb"]], [["scasw"]], [["scasd"]]]), ("retn", [[[""]], [["4"]]]), ("retf", [[[""]], [["4"]]]), ("rol", rotate), ("ror", rotate), ("sahf", no_operands), ("sal", rotate), ("sar", rotate), ("sbb", typical_binary), ("scasb", no_operands), ("scasw", no_operands), ("scasd", no_operands), ("seta", [[r8], [mem8]]), ("setae", [[r8], [mem8]]), ("setb", [[r8], [mem8]]), ("setbe", [[r8], [mem8]]), ("sete", [[r8], [mem8]]), ("setne", [[r8], [mem8]]), ("setl", [[r8], [mem8]]), ("setge", [[r8], [mem8]]), ("setle", [[r8], [mem8]]), ("setg", [[r8], [mem8]]), ("sets", [[r8], [mem8]]), ("setns", [[r8], [mem8]]), ("setc", [[r8], [mem8]]), ("setnc", [[r8], [mem8]]), ("seto", [[r8], [mem8]]), ("setno", [[r8], [mem8]]), ("setp", [[r8], [mem8]]), ("setnp", [[r8], [mem8]]), ("shl", rotate), ("shr", rotate), ("shld", shift_double), ("shrd", shift_double), ("stc", no_operands), ("std", no_operands), ("sti", no_operands), ("stosb", no_operands), ("stosw", no_operands), ("stosd", no_operands), ("sub", typical_binary), ("test", typical_binary), ("wait", no_operands), ("fwait", no_operands), ("xchg", [[r8, r8], [r16, r16], [r32, r32], [r8, mem8], [r16, mem16], [r32, mem32]]), ("xlatb", [[mem8]]), ("xlatb", no_operands), ("xor", typical_binary) ] -- Register definitions r8 = ["al", "bl", "cl", "dl", "ah", "bh", "ch", "dh"] r16 = ["ax", "bx", "cx", "dx", "si", "di", "sp", "bp"] r32 = ["eax", "ebx", "ecx", "edx", "esi", "edi", "esp", "ebp"] segments = "cs" : "ds" : segments_writable segments_writable = ["es", "fs", "gs", "ss"] -- Definitions of all possible memory access operand trees mem8 = ["byte ptr [someDword]"] ++ simple_ptr "byte" r32 ++ ptr_offset "byte" r32 ++ mult_reg "byte" r32 ++ two_regs "byte" r32 ++ mult_two_regs "byte" r32 mem16 = ["word ptr [someDword]"] ++ (simple_ptr "word" r32) ++ (ptr_offset "word" r32) ++ mult_reg "word" r32 ++ two_regs "word" r32 ++ mult_two_regs "word" r32 mem32 = ["dword ptr [someDword]"] ++ (simple_ptr "dword" r32) ++ (ptr_offset "dword" r32) ++ mult_reg "dword" r32 ++ two_regs "dword" r32 ++ mult_two_regs "dword" r32 mem64 = ["qword ptr [someDword]"] ++ (simple_ptr "qword" r32) ++ (ptr_offset "qword" r32) ++ mult_reg "qword" r32 ++ two_regs "qword" r32 ++ mult_two_regs "qword" r32 -- Definitions of a few sample immediates imm8 = ["12h"] imm16 = ["512h"] imm32 = ["6237512h"] -- Variant for instructions that use no operands no_operands = [[]] -- All variants of typical instructions with two operands -- like ADD, SUB, AND, OR, XOR, ... typical_binary = [ [r8, imm8], [r16, imm8], [r16, imm16], [r32, imm8], [r32, imm32], [mem8, imm8], [mem16, imm8], [mem16, imm16], [mem32, imm8], [mem32, imm32], [r8, r8], [r16, r16], [r32, r32], [mem8, r8], [mem16, r16], [mem32, r32], [r8, mem8], [r16, mem16], [r32, mem32] ] -- Operand variants for conditional jumps jcc_targets = [[["start"]]] -- Operand variants for single-operand instructions that write -- back to the operand rvalues = [[r8], [mem8], [r16], [mem16], [r32], [mem32]] -- Operand variants for the IMUL instruction imul = [ [r8], [r16], [r32], [mem8], [mem16], [mem32], [r16, r16], [r32, r32], [r16, mem16], [r32, mem32], [r16, imm16], [r32, imm32], [r16, r16, imm16], [r32, r32, imm32], [r16, mem16, imm16], [r32, mem32, imm32] ] -- Operand variants for movsx and movzx extend = [ [r16, r8], [r16, mem8], [r32, r8], [r32, mem8], [r32, r16], [r32, mem16] ] -- Operand variants for shifts and rotates rotate = [ [r8, imm8], [mem8, imm8], [r16, imm8], [mem16, imm8], [r32, imm8], [mem32, imm8], [r8, ["cl"]], [mem8, ["cl"]], [r16, ["cl"]], [mem16, ["cl"]], [r32, ["cl"]], [mem32, ["cl"]] ] -- Operand variants for double precision rotates shift_double = [ [r16, r16, "cl" : imm8], [mem16, r16, "cl" : imm8], [r32, r32, "cl" : imm8], [mem32, r32, "cl" : imm8] ] -- Flattens a nested list flatten = foldr (++) [] -- Only memory access operands with at most 1 use of ESP are valid fmbr = filter (\(x:y:[]) -> x /= "esp" || y /= "esp") -- Create operands of the form "byte/word/dword ptr [value]" simple_ptr size = map (\x -> size ++ " ptr [" ++ x ++ "]") -- Create operands of the form "byte/word/dword ptr [register + 123456h]" ptr_offset size = map (\x -> size ++ " ptr [" ++ x ++ " + 123456h]") -- Create operands of the form "byte/word/dword ptr [4 * register + 123456h]" mult_reg size regs = map (\x -> size ++ " ptr [4 * " ++ x ++ " + 123456h]") (regs \\ ["esp"]) -- Create operands of the form "byte/word/dword ptr [register + register]" two_regs size regs = map (\(x:y:[]) -> size ++ " ptr [" ++ x ++ " + " ++ y ++ "]") (fmbr $ zip_lists [regs, regs]) -- Create operands of the form "byte/word/dword ptr [4 * register + register]" mult_two_regs size regs = map (\(x:y:[]) -> size ++ " ptr [4 * " ++ x ++ " + " ++ y ++ "]") (fmbr $ zip_lists [regs \\ ["esp"], regs]) -- Takes a list of the form [["eax", "ebx", ...], ["esi", "edi", ...]] and turns it into -- [["eax", "esi"], ["eax, "edi"], ["eax", ...], ["ebx", "esi"], ["ebx", "edi"], ["ebx", "..."]] zip_lists :: [[a]] -> [[a]] zip_lists x | length x <= 1 = transpose x zip_lists (x:xs) = [a : b | a <- x, b <- zip_lists(xs)] -- Converts a list of operands an turns it into a comma-separated string to_operand_string :: [String] -> String to_operand_string = concat . intersperse ", " -- Creates the operand strings for a list of given variants create_operand_strings :: [[String]] -> [String] create_operand_strings = map to_operand_string . zip_lists -- Generates all instruction strings for one variant of an instruction generate_variant :: String -> [[String]] -> [String] generate_variant mnemonic = map (\x -> concat [mnemonic, " ", x]) . create_operand_strings -- Generates all instruction strings for one mnemonic gen_instruction_strings :: (String, [[[String]]]) -> [[String]] gen_instruction_strings (mnemonic, variants) = map (\x -> generate_variant mnemonic x) variants -- Main function; used to print the generated results main = putStrLn $ unlines $ flatten $ flatten $ map gen_instruction_strings mnemonics