📄 dasm_x86.lua
字号:
wputmodrm(t.xsc, t.xreg, 5) else -- Pure displacement. wputmodrm(0, s, 5) -- [disp] -> (0, s, ebp) end wputdarg(disp) return end local m if tdisp == "number" then -- Check displacement size at assembly time. if disp == 0 and t.reg ~= 5 then m = 0 -- [ebp] -> [ebp+0] (in SIB, too) elseif disp >= -128 and disp <= 127 then m = 1 else m = 2 end elseif tdisp == "table" then m = 2 end -- Index register present or esp as base register: need SIB encoding. if t.xreg or t.reg == 4 then wputmodrm(m or 2, s, 4) -- ModRM. if (m == nil or imark) and tdisp ~= "table" then waction("MARK") end wputmodrm(t.xsc or 0, t.xreg or 4, t.reg) -- SIB. else wputmodrm(m or 2, s, t.reg) -- ModRM. if imark and (m == 1 or m == 2) then waction("MARK") end end -- Put displacement. if m == 1 then wputsbarg(disp) elseif m == 2 then wputdarg(disp) elseif not m then waction("DISP", disp) endend-------------------------------------------------------------------------------- Return human-readable operand mode string.local function opmodestr(op, args) local m = {} for i=1,#args do local a = args[i] m[#m+1] = sub(a.mode, 1, 1)..(a.opsize or "?") end return op.." "..concat(m, ",")end-- Convert number to valid integer or nil.local function toint(expr) local n = tonumber(expr) if n then if n % 1 ~= 0 or n < -2147483648 or n > 4294967295 then werror("bad integer number `"..expr.."'") end return n endend-- Parse immediate expression.local function immexpr(expr) -- &expr (pointer) if sub(expr, 1, 1) == "&" then return "iPJ", format("(ptrdiff_t)(%s)", sub(expr,2)) end local prefix = sub(expr, 1, 2) -- =>expr (pc label reference) if prefix == "=>" then return "iJ", sub(expr, 3) end -- ->name (global label reference) if prefix == "->" then return "iJ", map_global[sub(expr, 3)] end -- [<>][1-9] (local label reference) local dir, lnum = match(expr, "^([<>])([1-9])$") if dir then -- Fwd: 247-255, Bkwd: 1-9. return "iJ", lnum + (dir == ">" and 246 or 0) end -- expr (interpreted as immediate) return "iI", exprend-- Parse displacement expression: +-num, +-expr, +-opsize*numlocal function dispexpr(expr) local disp = expr == "" and 0 or toint(expr) if disp then return disp end local c, dispt = match(expr, "^([+-])%s*(.+)$") if c == "+" then expr = dispt elseif not c then werror("bad displacement expression `"..expr.."'") end local opsize, tailops = match(dispt, "^(%w+)%s*%*%s*(.+)$") local ops, imm = map_opsize[opsize], toint(tailops) if ops and imm then if c == "-" then imm = -imm end return imm*map_opsizenum[ops] end local mode, iexpr = immexpr(dispt) if mode == "iJ" then if c == "-" then werror("cannot invert label reference") end return { iexpr } end return expr -- Need to return original signed expression.end-- Parse register or type expression.local function rtexpr(expr) if not expr then return end local tname, ovreg = match(expr, "^([%w_]+):(@[%w_]+)$") local tp = map_type[tname or expr] if tp then local reg = ovreg or tp.reg local rnum = map_reg_num[reg] if not rnum then werror("type `"..(tname or expr).."' needs a register override") end if not map_reg_valid_base[reg] then werror("bad base register override `"..(map_reg_rev[reg] or reg).."'") end return reg, rnum, tp end return expr, map_reg_num[expr]end-- Parse operand and return { mode, opsize, reg, xreg, xsc, disp, imm }.local function parseoperand(param) local t = {} local expr = param local opsize, tailops = match(param, "^(%w+)%s*(.+)$") if opsize then t.opsize = map_opsize[opsize] if t.opsize then expr = tailops end end local br = match(expr, "^%[%s*(.-)%s*%]$") repeat if br then t.mode = "xm" -- [disp] t.disp = toint(br) if t.disp then t.mode = "xmO" break end -- [reg...] local tp local reg, tailr = match(br, "^([@%w_:]+)%s*(.*)$") reg, t.reg, tp = rtexpr(reg) if not t.reg then -- [expr] t.mode = "xmO" t.disp = dispexpr("+"..br) break end -- [xreg*xsc] or [xreg*xsc+-disp] or [xreg*xsc+-expr] local xsc, tailsc = match(tailr, "^%*%s*([1248])%s*(.*)$") if xsc then if not map_reg_valid_index[reg] then werror("bad index register `"..map_reg_rev[reg].."'") end t.xsc = map_xsc[xsc] t.xreg = t.reg t.reg = nil t.disp = dispexpr(tailsc) break end if not map_reg_valid_base[reg] then werror("bad base register `"..map_reg_rev[reg].."'") end -- [reg] or [reg+-disp] t.disp = toint(tailr) or (tailr == "" and 0) if t.disp then break end -- [reg+xreg...] local xreg, tailx = match(tailr, "^+%s*([@%w_:]+)%s*(.*)$") xreg, t.xreg, tp = rtexpr(xreg) if not t.xreg then -- [reg+-expr] t.disp = dispexpr(tailr) break end if not map_reg_valid_index[xreg] then werror("bad index register `"..map_reg_rev[xreg].."'") end -- [reg+xreg*xsc...] local xsc, tailsc = match(tailx, "^%*%s*([1248])%s*(.*)$") if xsc then t.xsc = map_xsc[xsc] tailx = tailsc end -- [...] or [...+-disp] or [...+-expr] t.disp = dispexpr(tailx) else -- imm or opsize*imm local imm = toint(expr) if not imm and sub(expr, 1, 1) == "*" and t.opsize then imm = toint(sub(expr, 2)) if imm then imm = imm * map_opsizenum[t.opsize] t.opsize = nil end end if imm then if t.opsize then werror("bad operand size override") end local m = "i" if imm == 1 then m = m.."1" end if imm >= 4294967168 and imm <= 4294967295 then imm = imm-4294967296 end if imm >= -128 and imm <= 127 then m = m.."S" end t.imm = imm t.mode = m break end local tp local reg, tailr = match(expr, "^([@%w_:]+)%s*(.*)$") reg, t.reg, tp = rtexpr(reg) if t.reg then -- reg if tailr == "" then if t.opsize then werror("bad operand size override") end t.opsize = map_reg_opsize[reg] if t.opsize == "f" then t.mode = t.reg == 0 and "fF" or "f" else if reg == "@w4" then wwarn("bad idea, try again with `esp'") end t.mode = t.reg == 0 and "rmR" or (reg == "@b1" and "rmC" or "rm") end break end -- type[idx], type[idx].field, type->field -> [reg+offset_expr] if not tp then werror("bad operand `"..param.."'") end t.mode = "xm" t.disp = format(tp.ctypefmt, tailr) else t.mode, t.imm = immexpr(expr) if sub(t.mode, -1) == "J" then if t.opsize and t.opsize ~= addrsize then werror("bad operand size override") end t.opsize = addrsize end end end until true return tend-------------------------------------------------------------------------------- x86 Template String Description-- ===============================---- Each template string is a list of [match:]pattern pairs,-- separated by "|". The first match wins. No match means a-- bad or unsupported combination of operand modes or sizes.---- The match part and the ":" is omitted if the operation has-- no operands. Otherwise the first N characters are matched-- against the mode strings of each of the N operands.---- The mode string for each operand type is (see parseoperand()):-- Integer register: "rm", +"R" for eax, ax, al, +"C" for cl-- FP register: "f", +"F" for st0-- Index operand: "xm", +"O" for [disp] (pure offset)-- Immediate: "i", +"S" for signed 8 bit, +"1" for 1,-- +"I" for arg, +"P" for pointer-- Any: +"J" for valid jump targets---- So a match character "m" (mixed) matches both an integer register-- and an index operand (to be encoded with the ModRM/SIB scheme).-- But "r" matches only a register and "x" only an index operand-- (e.g. for FP memory access operations).---- The operand size match string starts right after the mode match-- characters and ends before the ":". "dwb" is assumed, if empty.-- The effective data size of the operation is matched against this list.---- If only the regular "b", "w", "d", "q", "t" operand sizes are-- present, then all operands must be the same size. Unspecified sizes-- are ignored, but at least one operand must have a size or the pattern-- won't match (use the "byte", "word", "dword", "qword", "tword"-- operand size overrides. E.g.: mov dword [eax], 1).---- If the list has a "1" or "2" prefix, the operand size is taken-- from the respective operand and any other operand sizes are ignored.-- If the list contains only ".", all operand sizes are ignored.-- If the list has a "/" prefix, the concatenated (mixed) operand sizes-- are compared to the match.---- E.g. "rrdw" matches for either two dword registers or two word-- registers. "Fx2dq" matches an st0 operand plus an index operand-- pointing to a dword (float) or qword (double).---- Every character after the ":" is part of the pattern string:-- Hex chars are accumulated to form the opcode (left to right).-- "n" disables the standard opcode mods-- (otherwise: -1 for "b", o16 prefix for "w")-- "r"/"R" adds the reg. number from the 1st/2nd operand to the opcode.-- "m"/"M" generates ModRM/SIB from the 1st/2nd operand.-- The spare 3 bits are either filled with the last hex digit or-- the result from a previous "r"/"R". The opcode is restored.---- All of the following characters force a flush of the opcode:-- "o"/"O" stores a pure 32 bit disp (offset) from the 1st/2nd operand.-- "S" stores a signed 8 bit immediate from the last operand.-- "U" stores an unsigned 8 bit immediate from the last operand.-- "W" stores an unsigned 16 bit immediate from the last operand.-- "i" stores an operand sized immediate from the last operand.-- "I" dito, but generates an action code to optionally modify-- the opcode (+2) for a signed 8 bit immediate.-- "J" generates one of the REL action codes from the last operand.---------------------------------------------------------------------------------- Template strings for x86 instructions. Ordered by first opcode byte.-- Unimplemented opcodes (deliberate omissions) are marked with *.local map_op = { -- 00-05: add... -- 06: *push es -- 07: *pop es -- 08-0D: or... -- 0E: *push cs -- 0F: two byte opcode prefix -- 10-15: adc... -- 16: *push ss -- 17: *pop ss -- 18-1D: sbb... -- 1E: *push ds -- 1F: *pop ds -- 20-25: and... es_0 = "26", -- 27: *daa -- 28-2D: sub... cs_0 = "2E", -- 2F: *das -- 30-35: xor... ss_0 = "36", -- 37: *aaa -- 38-3D: cmp... ds_0 = "3E", -- 3F: *aas inc_1 = "rdw:40r|m:FF0m", dec_1 = "rdw:48r|m:FF1m", push_1 = "rdw:50r|mdw:FF6m|S.:6AS|ib:n6Ai|i.:68i", pop_1 = "rdw:58r|mdw:8F0m", -- 60: *pusha, *pushad, *pushaw -- 61: *popa, *popad, *popaw -- 62: *bound rdw,x -- 63: *arpl mw,rw fs_0 = "64", gs_0 = "65", o16_0 = "66", a16_0 = "67", -- 68: push idw -- 69: imul rdw,mdw,idw -- 6A: push ib -- 6B: imul rdw,mdw,S -- 6C: *insb -- 6D: *insd, *insw -- 6E: *outsb -- 6F: *outsd, *outsw -- 70-7F: jcc lb -- 80: add... mb,i -- 81: add... mdw,i -- 82: *undefined -- 83: add... mdw,S test_2 = "mr:85Rm|rm:85rM|Ri:A9i|mi:F70mi", -- 86: xchg rb,mb -- 87: xchg rdw,mdw -- 88: mov mb,r -- 89: mov mdw,r -- 8A: mov r,mb -- 8B: mov r,mdw -- 8C: *mov mdw,seg lea_2 = "rxd:8DrM", -- 8E: *mov seg,mdw -- 8F: pop mdw nop_0 = "90", xchg_2 = "Rrdw:90R|rRdw:90r|rm:87rM|mr:87Rm", cbw_0 = "6698", cwde_0 = "98", cwd_0 = "6699", cdq_0 = "99", -- 9A: *call iw:idw wait_0 = "9B", fwait_0 = "9B",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -