# HG changeset patch # User Mike Pavone # Date 1377396198 25200 # Node ID 97f107b9e8d34fa73c2fb6f313e2e27e697256ce # Parent ab7c142090a034cbbf6003d331dab947904e53f1 Fix a few bugs in the x86 module and add jcc, push and pop instructions diff -r ab7c142090a0 -r 97f107b9e8d3 modules/x86.tp --- a/modules/x86.tp Sat Aug 24 19:02:59 2013 -0700 +++ b/modules/x86.tp Sat Aug 24 19:03:18 2013 -0700 @@ -90,6 +90,29 @@ dword <- size: 2 qword <- size: 3 + condition <- :num { + #{ + cc <- { num } + } + } + _o <- condition: 0u8 + _no <- condition: 1u8 + _c <- condition: 2u8 + _nc <- condition: 3u8 + _z <- condition: 4u8 + _nz <- condition: 5u8 + _be <- condition: 6u8 + _nbe <- condition: 7u8 + _s <- condition: 8u8 + _ns <- condition: 9u8 + _p <- condition: 10u8 + _np <- condition: 11u8 + _l <- condition: 12u8 + _nl <- condition: 13u8 + _le <- condition: 14u8 + _nle <- condition: 15u8 + + size_bit <- :opcode size { if: size = byte { opcode @@ -128,6 +151,7 @@ //used for mov instructions that support 64-bit immediate operands/offsets int_op64 <- :value size { tail <- [] + value <- uint64: value if: size = qword { tail <- (uint8: (rshift: value by: 32u64)) | (uint8: (rshift: value by: 40u64)) | (uint8: (rshift: value by: 48u64)) | (uint8: (rshift: value by: 56u64)) | tail } @@ -216,6 +240,9 @@ } } + _jmprel <- :op jmpDest { + } + #{ rax <- { _rax } rcx <- { _rcx } @@ -243,6 +270,31 @@ d <- { dword } q <- { qword } + o <- { _o } + no <- { _no } + c <- { _c } + nc <- { _nc } + ae <- { _nc } + z <- { _z } + e <- { _z } + nz <- { _nz } + ne <- { _nz } + be <- { _be } + nbe <- { _nbe } + a <- { _nbe } + s <- { _s } + ns <- { _ns } + p <- { _p } + pe <- { _p } + np <- { _np } + po <- { _np } + l <- { _l } + nl <- { _nl } + ge <- { _nl } + le <- { _le } + nle <- { _nle } + g <- { _nle } + add <- :src dst size { op: src dst size withCode: 0u8 withImmed: 0x80u8 withImmedRax: 0x04u8 withOpEx: 0u8 withByteExtend: 0x83u8 } @@ -252,11 +304,10 @@ } mov <- :src dst size { - reg <- src rm <- dst if: (src isInteger?) && (dst register?) { opval <- if: size = byte { 0xB0u8 } else: { 0xB8u8 } - base <- opval | (int_op64: src size) + base <- opval or (dst reg) | (int_op64: src size) inst: (prefix: fakesrc rm size withInstruction: base) } else: { op: src dst size withCode: 0x88u8 withImmed: 0xC6u8 withOpEx: 0u8 @@ -267,7 +318,6 @@ label <- { _offset <- -1 - _address <- 0u64 _forwardRefs <- #[] #{ length <- { 0 } @@ -278,7 +328,6 @@ flattenTo:at <- :dest :idx { if: (not: hasOffset?) { _offset <- idx - _address <- dest addressAt: idx foreach: _forwardRefs :idx fun { fun: _offset } @@ -346,6 +395,40 @@ } } + jcc <- :cond jmpDest { + _size <- -1 + #{ + length <- { if: _size < 0 { 5 } else: { _size } } + flattenTo:at <- :dest :idx { + jmpDest withOffset: :off { + if: _size < 0 { + rel <- off - (idx + 2) + if: rel < 128 && rel >= -128 { + _size <- 2 + } else: { + _size <- 6 + } + } + rel <- off - (idx + _size) + if: _size = 2 { + dest set: idx 0x70u8 or (cond cc) + dest set: (idx + 1) (uint8: rel) + } else: { + dest set: idx 0x0Fu8 + dest set: (idx + 1) 0x80u8 or (cond cc) + dest set: (idx + 2) (uint8: rel) + dest set: (idx + 3) (uint8: (rshift: rel by: 8)) + dest set: (idx + 4) (uint8: (rshift: rel by: 16)) + dest set: (idx + 5) (uint8: (rshift: rel by: 24)) + } + } else: { + _size <- 6 + } + idx + _size + } + } + } + call <- :callDest { if: (callDest label?) { #{ @@ -368,28 +451,56 @@ } } + push <- :src { + if: (src isInteger?) { + if: src < 128 && src > -128 { + inst: 0x6Au8 | (uint8: src) + } else: { + inst: 0x68u8 | (uint8: src) | (uint8: (rshift: src by: 8)) | (uint8: (rshift: src by: 16)) | (uint8: (rshift: src by: 24)) + } + } else: { + base <- if: (src register?) { + [0x50u8 or (src reg)] + } else: { + 0xFFu8 | (mod_rm: (opex: 6u8) src) + } + inst: (prefix: fakesrc src d withInstruction: base) + } + } + + pop <- :dst { + base <- if: (dst register?) { + [0x58u8 or (dst reg)] + } else: { + 0x8Fu8 | (mod_rm: (opex: 0u8) dst) + } + inst: (prefix: fakesrc dst d withInstruction: base) + } + main <- { - foo <- label: - bar <- label: - baz <- label: + fib <- label: + notbase <- label: prog <- #[ - mov: rdi rax q - sub: 1 rdi q + fib + sub: 2 rdi q + jcc: ge notbase + mov: 1 rax q + ret: + + notbase + push: rdi + call: fib + pop: rdi + push: rax + add: 1 rdi q + call: fib + pop: rdi add: rdi rax q - jmp: bar - foo - ret: - bar - sub: 13 rax q - call: baz - jmp: foo - baz - add: 1 rax q ret: ] ba <- bytearray executableFromBytes: prog - res <- ba runWithArg: 24u64 + res <- ba runWithArg: 30u64 print: (string: res) . "\n" 0 }