📄 dasm_x86.lua
字号:
map_op[fn.."p_1"] = format("ff:DE%02Xr", nr) map_op[fn.."p_2"] = format("fFf:DE%02Xr", nr) end map_op["fi"..name.."_1"] = format("xd:DA%Xm|xw:nDE%Xm", n, n)end-- FP conditional moves.for cc,n in pairs{ b=0, e=1, be=2, u=3, nb=4, ne=5, nbe=6, nu=7 } do local n4 = n % 4 local nc = 56000 + n4 * 8 + (n-n4) * 64 map_op["fcmov"..cc.."_1"] = format("ff:%04Xr", nc) -- P6+ map_op["fcmov"..cc.."_2"] = format("Fff:%04XR", nc) -- P6+end-- SSE FP arithmetic ops.for name,n in pairs{ sqrt = 1, add = 8, mul = 9, sub = 12, min = 13, div = 14, max = 15 } do map_op[name.."ps_2"] = format("rmo:0F5%XrM", n) map_op[name.."ss_2"] = format("rro:F30F5%XrM|rx/od:", n) map_op[name.."pd_2"] = format("rmo:660F5%XrM", n) map_op[name.."sd_2"] = format("rro:F20F5%XrM|rx/oq:", n)end-------------------------------------------------------------------------------- Process pattern string.local function dopattern(pat, args, sz, op) local digit, addin local opcode = 0 local szov = sz -- Limit number of section buffer positions used by a single dasm_put(). -- A single opcode needs a maximum of 2 positions. !x64 if secpos+2 > maxsecpos then wflush() end -- Process each character. for c in gmatch(pat, ".") do if match(c, "%x") then -- Hex digit. digit = byte(c) - 48 if digit > 48 then digit = digit - 39 elseif digit > 16 then digit = digit - 7 end opcode = opcode*16 + digit addin = nil elseif c == "n" then -- Disable operand size mods for opcode. szov = nil elseif c == "r" then -- Merge 1st operand regno. into opcode. addin = args[1].reg; opcode = opcode + addin elseif c == "R" then -- Merge 2nd operand regno. into opcode. addin = args[2].reg; opcode = opcode + addin elseif c == "m" or c == "M" then -- Encode ModRM/SIB. if addin then opcode = opcode - addin -- Undo regno opcode merge. else addin = opcode % 16 -- Undo last digit. opcode = (opcode - addin) / 16 end wputop(szov, opcode); opcode = nil local imark = (sub(pat, -1) == "I") -- Force a mark (ugly). -- Put ModRM/SIB with regno/last digit as spare. wputmrmsib(args[c == "m" and 1 or 2], addin, imark) else if opcode then wputop(szov, opcode); opcode = nil end -- Flush opcode. if c == "o" or c == "O" then -- Offset (pure 32 bit displacement). wputdarg(args[c == "o" and 1 or 2].disp) else -- Anything else is an immediate operand. local a = args[#args] local mode, imm = a.mode, a.imm if mode == "iJ" and not match("iIJ", c) then werror("bad operand size for label") end if c == "S" then wputsbarg(imm) elseif c == "U" then wputbarg(imm) elseif c == "W" then wputwarg(imm) elseif c == "i" or c == "I" then if mode == "iJ" then wputlabel("IMM_", imm, 1) elseif mode == "iI" and c == "I" then waction(sz == "w" and "IMM_WB" or "IMM_DB", imm) else wputszarg(sz, imm) end elseif c == "J" then if mode == "iPJ" then waction("REL_A", imm) -- !x64 (secpos) else wputlabel("REL_", imm, 2) end else werror("bad char `"..c.."' in pattern `"..pat.."' for `"..op.."'") end end end end if opcode then wputop(szov, opcode) endend-------------------------------------------------------------------------------- Mapping of operand modes to short names. Suppress output with '#'.local map_modename = { r = "reg", R = "eax", C = "cl", x = "mem", m = "mrm", i = "imm", f = "stx", F = "st0", J = "lbl", ["1"] = "1", I = "#", S = "#", O = "#",}-- Return a table/string showing all possible operand modes.local function templatehelp(template, nparams) if nparams == 0 then return "" end local t = {} for tm in gmatch(template, "[^%|]+") do local s = map_modename[sub(tm, 1, 1)] s = s..gsub(sub(tm, 2, nparams), ".", function(c) return ", "..map_modename[c] end) if not match(s, "#") then t[#t+1] = s end end return tend-- Match operand modes against mode match part of template.local function matchtm(tm, args) for i=1,#args do if not match(args[i].mode, sub(tm, i, i)) then return end end return trueend-- Handle opcodes defined with template strings.map_op[".template__"] = function(params, template, nparams) if not params then return templatehelp(template, nparams) end local args = {} -- Zero-operand opcodes have no match part. if #params == 0 then dopattern(template, args, "d", params.op) return end -- Determine common operand size (coerce undefined size) or flag as mixed. local sz, szmix for i,p in ipairs(params) do args[i] = parseoperand(p) local nsz = args[i].opsize if nsz then if sz and sz ~= nsz then szmix = true else sz = nsz end end end -- Try all match:pattern pairs (separated by '|'). local gotmatch, lastpat for tm in gmatch(template, "[^%|]+") do -- Split off size match (starts after mode match) and pattern string. local szm, pat = match(tm, "^(.-):(.*)$", #args+1) if pat == "" then pat = lastpat else lastpat = pat end if matchtm(tm, args) then local prefix = sub(szm, 1, 1) if prefix == "/" then -- Match both operand sizes. if args[1].opsize == sub(szm, 2, 2) and args[2].opsize == sub(szm, 3, 3) then dopattern(pat, args, sz, params.op) -- Process pattern string. return end else -- Match common operand size. local szp = sz if szm == "" then szm = "dwb" end -- Default size match. if prefix == "1" then szp = args[1].opsize; szmix = nil elseif prefix == "2" then szp = args[2].opsize; szmix = nil end if not szmix and (prefix == "." or match(szm, szp or "#")) then dopattern(pat, args, szp, params.op) -- Process pattern string. return end end gotmatch = true end end local msg = "bad operand mode" if gotmatch then if szmix then msg = "mixed operand size" else msg = sz and "bad operand size" or "missing operand size" end end werror(msg.." in `"..opmodestr(params.op, args).."'")end-------------------------------------------------------------------------------- Pseudo-opcodes for data storage.local function op_data(params) if not params then return "imm..." end local sz = sub(params.op, 2, 2) if sz == "a" then sz = addrsize end for _,p in ipairs(params) do local a = parseoperand(p) if sub(a.mode, 1, 1) ~= "i" or (a.opsize and a.opsize ~= sz) then werror("bad mode or size in `"..p.."'") end if a.mode == "iJ" then wputlabel("IMM_", a.imm, 1) else wputszarg(sz, a.imm) end endendmap_op[".byte_*"] = op_datamap_op[".sbyte_*"] = op_datamap_op[".word_*"] = op_datamap_op[".dword_*"] = op_datamap_op[".aword_*"] = op_data-------------------------------------------------------------------------------- Pseudo-opcode to mark the position where the action list is to be emitted.map_op[".actionlist_1"] = function(params) if not params then return "cvar" end local name = params[1] -- No syntax check. You get to keep the pieces. wline(function(out) writeactions(out, name) end)end-- Pseudo-opcode to mark the position where the global enum is to be emitted.map_op[".globals_1"] = function(params) if not params then return "prefix" end local prefix = params[1] -- No syntax check. You get to keep the pieces. wline(function(out) writeglobals(out, prefix) end)end-------------------------------------------------------------------------------- Label pseudo-opcode (converted from trailing colon form).map_op[".label_2"] = function(params) if not params then return "[1-9] | ->global | =>pcexpr [, addr]" end local a = parseoperand(params[1]) local mode, imm = a.mode, a.imm if type(imm) == "number" and (mode == "iJ" or (imm >= 1 and imm <= 9)) then -- Local label (1: ... 9:) or global label (->global:). waction("LABEL_LG", nil, 1) wputxb(imm) elseif mode == "iJ" then -- PC label (=>pcexpr:). waction("LABEL_PC", imm) else werror("bad label definition") end -- SETLABEL must immediately follow LABEL_LG/LABEL_PC. local addr = params[2] if addr then local a = parseoperand(params[2]) if a.mode == "iPJ" then waction("SETLABEL", a.imm) -- !x64 (secpos) else werror("bad label assignment") end endendmap_op[".label_1"] = map_op[".label_2"]-------------------------------------------------------------------------------- Alignment pseudo-opcode.map_op[".align_1"] = function(params) if not params then return "numpow2" end local align = tonumber(params[1]) or map_opsizenum[map_opsize[params[1]]] if align then local x = align -- Must be a power of 2 in the range (2 ... 256). for i=1,8 do x = x / 2 if x == 1 then waction("ALIGN", nil, 1) wputxb(align-1) -- Action byte is 2**n-1. return end end end werror("bad alignment")end-- Spacing pseudo-opcode.map_op[".space_2"] = function(params) if not params then return "num [, filler]" end waction("SPACE", params[1]) local fill = params[2] if fill then fill = tonumber(fill) if not fill or fill < 0 or fill > 255 then werror("bad filler") end end wputxb(fill or 0)endmap_op[".space_1"] = map_op[".space_2"]-------------------------------------------------------------------------------- Pseudo-opcode for (primitive) type definitions (map to C types).map_op[".type_3"] = function(params, nparams) if not params then return nparams == 2 and "name, ctype" or "name, ctype, reg" end local name, ctype, reg = params[1], params[2], params[3] if not match(name, "^[%a_][%w_]*$") then werror("bad type name `"..name.."'") end local tp = map_type[name] if tp then werror("duplicate type `"..name.."'") end if reg and not map_reg_valid_base[reg] then werror("bad base register `"..(map_reg_rev[reg] or reg).."'") end -- Add #type to defines. A bit unclean to put it in map_archdef. map_archdef["#"..name] = "sizeof("..ctype..")" -- Add new type and emit shortcut define. local num = ctypenum + 1 map_type[name] = { ctype = ctype, ctypefmt = format("Dt%X(%%s)", num), reg = reg, } wline(format("#define Dt%X(_V) (int)&(((%s *)0)_V)", num, ctype)) ctypenum = numendmap_op[".type_2"] = map_op[".type_3"]-- Dump type definitions.local function dumptypes(out, lvl) local t = {} for name in pairs(map_type) do t[#t+1] = name end sort(t) out:write("Type definitions:\n") for _,name in ipairs(t) do local tp = map_type[name] local reg = tp.reg and map_reg_rev[tp.reg] or "" out:write(format(" %-20s %-20s %s\n", name, tp.ctype, reg)) end out:write("\n")end-------------------------------------------------------------------------------- Set the current section.function _M.section(num) waction("SECTION") wputxb(num) wflush(true) -- SECTION is a terminal action.end-------------------------------------------------------------------------------- Dump architecture description.function _M.dumparch(out) out:write(format("DynASM %s version %s, released %s\n\n", _info.arch, _info.version, _info.release)) dumpregs(out) dumpactions(out)end-- Dump all user defined elements.function _M.dumpdef(out, lvl) dumptypes(out, lvl) dumpglobals(out, lvl)end-------------------------------------------------------------------------------- Pass callbacks from/to the DynASM core.function _M.passcb(wl, we, wf, ww) wline, werror, wfatal, wwarn = wl, we, wf, ww return wflushend-- Setup the arch-specific module.function _M.setup(arch, opt) g_arch, g_opt = arch, optend-- Merge the core maps and the arch-specific maps.function _M.mergemaps(map_coreop, map_def) setmetatable(map_op, { __index = map_coreop }) setmetatable(map_def, { __index = map_archdef }) return map_op, map_defendreturn _M------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -