📄 dis_x86.lua
字号:
if #hex > 16 then hex = sub(hex, 1, 16).."." end if operands then text = text.." "..operands end if ctx.o16 then text = "o16 "..text; ctx.o16 = false end if ctx.rep then text = ctx.rep.." "..text; ctx.rep = false end if ctx.seg then local text2, n = gsub(text, "%[", "["..ctx.seg..":") if n == 0 then text = ctx.seg.." "..text else text = text2 end ctx.seg = false end if ctx.lock then text = "lock "..text; ctx.lock = false end local imm = ctx.imm if imm then local sym = ctx.symtab[imm] if sym then text = text.."\t->"..sym end end ctx.out(format("%08x %-18s%s\n", ctx.addr+ctx.start, hex, text)) ctx.mrm = false ctx.start = pos ctx.imm = nilend-- Fallback for incomplete opcodes at the end.local function incomplete(ctx) ctx.pos = ctx.stop+1 ctx.o16 = false; ctx.seg = false; ctx.lock = false; ctx.rep = false return putop(ctx, "(incomplete)")end-- Fallback for unknown opcodes.local function unknown(ctx) ctx.o16 = false; ctx.seg = false; ctx.lock = false; ctx.rep = false return putop(ctx, "(unknown)")end-- Return an immediate of the specified size.local function getimm(ctx, pos, n) if pos+n-1 > ctx.stop then return incomplete(ctx) end local code = ctx.code if n == 1 then local b1 = byte(code, pos, pos) return b1 elseif n == 2 then local b1, b2 = byte(code, pos, pos+1) return b1+b2*256 else local b1, b2, b3, b4 = byte(code, pos, pos+3) local imm = b1+b2*256+b3*65536+b4*16777216 ctx.imm = imm return imm endend-- Process pattern string and generate the operands.local function putpat(ctx, name, pat) local operands, regs, sz, mode, sp, rm, sc, rx, disp, sdisp local code, pos, stop = ctx.code, ctx.pos, ctx.stop -- Chars used: 1DFGMPQRVWXacdfgijmoprsuwxyz for p in gmatch(pat, ".") do local x = nil if p == "V" then sz = ctx.o16 and "W" or "D"; ctx.o16 = false regs = map_regs[sz] elseif match(p, "[BWDQFGMX]") then sz = p regs = map_regs[sz] elseif p == "P" then sz = ctx.o16 and "X" or "M"; ctx.o16 = false regs = map_regs[sz] elseif p == "s" then local imm = getimm(ctx, pos, 1); if not imm then return end x = imm <= 127 and format("byte +0x%02x", imm) or format("byte -0x%02x", 256-imm) pos = pos+1 elseif p == "u" then local imm = getimm(ctx, pos, 1); if not imm then return end x = format("0x%02x", imm) pos = pos+1 elseif p == "w" then local imm = getimm(ctx, pos, 2); if not imm then return end x = format("0x%x", imm) pos = pos+2 elseif p == "o" then -- [offset] local imm = getimm(ctx, pos, 4); if not imm then return end x = format("[0x%08x]", imm) pos = pos+4 elseif p == "i" then local n = map_sz2n[sz] local imm = getimm(ctx, pos, n); if not imm then return end x = format(imm > 65535 and "0x%08x" or "0x%x", imm) pos = pos+n elseif p == "j" then local n = map_sz2n[sz] local imm = getimm(ctx, pos, n); if not imm then return end if sz == "B" and imm > 127 then imm = imm-256 elseif imm > 2147483647 then imm = imm-4294967296 end pos = pos+n imm = imm + pos + ctx.addr ctx.imm = imm x = sz == "W" and format("word 0x%04x", imm%65536) or format("0x%08x", imm) elseif p == "R" then x = regs[byte(code, pos-1, pos-1)%8+1] elseif p == "a" then x = regs[1] elseif p == "c" then x = "cl" elseif p == "d" then x = "dx" elseif p == "1" then x = "1" else if not mode then mode = ctx.mrm if not mode then if pos > stop then return incomplete(ctx) end mode = byte(code, pos, pos) pos = pos+1 end rm = mode%8; mode = (mode-rm)/8 sp = mode%8; mode = (mode-sp)/8 sdisp = "" if mode < 3 then if rm == 4 then if pos > stop then return incomplete(ctx) end sc = byte(code, pos, pos) pos = pos+1 rm = sc%8; sc = (sc-rm)/8 rx = sc%8; sc = (sc-rx)/8 if rx == 4 then rx = nil end end if mode > 0 or rm == 5 then local dsz = mode if dsz ~= 1 then dsz = 4 end disp = getimm(ctx, pos, dsz); if not disp then return end sdisp = (dsz == 4 or disp <= 127) and format(disp > 65535 and "+0x%08x" or "+0x%x", disp) or format("-0x%x", 256-disp) pos = pos+dsz end end end if p == "m" then if mode == 3 then x = regs[rm+1] else local srm, srx = map_aregs[rm+1], "" if rx then srm = srm.."+" srx = map_aregs[rx+1] if sc > 0 then srx = srx.."*"..(2^sc) end end if mode == 0 and rm == 5 then srm = "" sdisp = format("%s0x%08x", rx and "+" or "", disp) end x = format("[%s%s%s]", srm, srx, sdisp) end if mode < 3 and (not match(pat, "[aRrgp]") or name == "movzx" or name == "movsx") then -- Yuck. x = map_sz2prefix[sz].." "..x end elseif p == "r" then x = regs[sp+1] elseif p == "g" then x = map_segregs[sp+1] elseif p == "p" then -- Suppress prefix. elseif p == "f" then x = "st"..rm elseif p == "x" then x = "CR"..sp elseif p == "y" then x = "DR"..sp elseif p == "z" then x = "TR"..sp else error("bad pattern `"..pat.."'") end end if x then operands = operands and operands..","..x or x end end ctx.pos = pos return putop(ctx, name, operands)end-- Forward declaration.local map_act-- Get a pattern from an opcode map and dispatch to handler.local function opcdispatch(ctx, opcmap) local pos = ctx.pos local opat = opcmap[byte(ctx.code, pos, pos)] if not opat then return unknown(ctx) end if match(opat, "%|") then -- MMX/SSE variants depending on prefix. local p if ctx.rep then p = ctx.rep=="rep" and "%|([^%|]*)" or "%|.-%|.-%|([^%|]*)" elseif ctx.o16 then p = "%|.-%|([^%|]*)" else p = "^[^%|]*" end opat = match(opat, p) if not opat or opat == "" then return unknown(ctx) end ctx.rep = false; ctx.o16 = false end local name, pat, act = match(opat, "^([a-z0-9 ]*)((.?).*)") ctx.pos = pos + 1 return map_act[act](ctx, name, pat)end-- Map for action codes. The key is the first char after the name.map_act = { -- Simple opcodes without operands. [""] = function(ctx, name, pat) return putop(ctx, name) end, -- Operand size chars fall right through. B = putpat, W = putpat, D = putpat, V = putpat, F = putpat, G = putpat, M = putpat, X = putpat, P = putpat, -- Collect prefixes. [":"] = function(ctx, name, pat) ctx[pat == ":" and name or sub(pat, 2)] = name end, -- Select alternate opcode name when prefixed with o16. ["/"] = function(ctx, name, pat) local wname, rpat = match(pat, "^/([a-z0-9 ]+)(.*)") if ctx.o16 then name = wname; ctx.o16 = false end return putpat(ctx, name, rpat) end, -- Chain to special handler specified by name. ["*"] = function(ctx, name, pat) return map_act[name](ctx, name, sub(pat, 2)) end, -- Use named subtable for opcode group. ["!"] = function(ctx, name, pat) local pos = ctx.pos if pos > ctx.stop then return incomplete(ctx) end local mrm = byte(ctx.code, pos, pos) ctx.pos = pos+1 ctx.mrm = mrm local opat = map_opcgroup[name][((mrm-(mrm%8))/8)%8+1] if not opat then return unknown(ctx) end local name, pat2 = match(opat, "^([a-z0-9 ]*)(.*)") return putpat(ctx, name, pat2 ~= "" and pat2 or sub(pat, 2)) end, -- Two-byte opcode dispatch. opc2 = function(ctx, name, pat) return opcdispatch(ctx, map_opc2) end, -- SSSE3 dispatch. ssse3 = function(ctx, name, pat) return opcdispatch(ctx, map_ssse3[pat]) end, -- Floating point opcode dispatch. fp = function(ctx, name, pat) local pos = ctx.pos if pos > ctx.stop then return incomplete(ctx) end local mrm = byte(ctx.code, pos, pos) ctx.pos = pos+1 ctx.mrm = mrm local rm = mrm%8 local idx = pat*8 + ((mrm-rm)/8)%8 if mrm >= 192 then idx = idx + 64 end local opat = map_opcfp[idx] if type(opat) == "table" then opat = opat[rm+1] end if not opat then return unknown(ctx) end local name, pat2 = match(opat, "^([a-z0-9 ]*)(.*)") return putpat(ctx, name, pat2) end,}-------------------------------------------------------------------------------- Disassemble a block of code.local function disass_block(ctx, ofs, len) if not ofs then ofs = 0 end local stop = len and ofs+len or #ctx.code ofs = ofs + 1 ctx.start = ofs ctx.pos = ofs ctx.stop = stop ctx.imm = nil ctx.mrm = false ctx.o16 = false; ctx.seg = false; ctx.lock = false; ctx.rep = false while ctx.pos <= stop do opcdispatch(ctx, map_opc1) end if ctx.pos ~= ctx.start then incomplete(ctx) endend-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len).local function create_(code, addr, out) local ctx = {} ctx.code = code ctx.addr = (addr or 0) - 1 ctx.out = out or io.write ctx.symtab = {} ctx.disass = disass_block return ctxend-- Simple API: disassemble code (a string) at address and output via out.local function disass_(code, addr, out) create_(code, addr, out):disass()end-- Public module functions.module(...)create = create_disass = disass_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -