⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dasm_x86.lua

📁 采用C语言写的Lua的解释器的代码!Lua不用介绍了吧
💻 LUA
📖 第 1 页 / 共 4 页
字号:
-------------------------------------------------------------------------------- DynASM x86 module.---- Copyright (C) 2005-2008 Mike Pall. All rights reserved.-- See dynasm.lua for full copyright notice.-------------------------------------------------------------------------------- Module information:local _info = {  arch =	"x86",  description =	"DynASM x86 (i386) module",  version =	"1.1.4",  vernum =	 10104,  release =	"2008-01-29",  author =	"Mike Pall",  license =	"MIT",}-- Exported glue functions for the arch-specific module.local _M = { _info = _info }-- Cache library functions.local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairslocal assert, unpack = assert, unpacklocal _s = stringlocal sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.charlocal find, match, gmatch, gsub = _s.find, _s.match, _s.gmatch, _s.gsublocal concat, sort = table.concat, table.sortlocal char, unpack = string.char, unpack-- Inherited tables and callbacks.local g_opt, g_archlocal wline, werror, wfatal, wwarn-- Action name list.-- CHECK: Keep this in sync with the C code!local action_names = {  -- int arg, 1 buffer pos:  "DISP",  "IMM_S", "IMM_B", "IMM_W", "IMM_D",  "IMM_WB", "IMM_DB",  -- action arg (1 byte), int arg, 1 buffer pos (num):  "SPACE",  -- ptrdiff_t arg, 1 buffer pos (address): !x64  "SETLABEL", "REL_A",  -- action arg (1 byte) or int arg, 2 buffer pos (link, offset):  "REL_LG", "REL_PC",  -- action arg (1 byte) or int arg, 1 buffer pos (link):  "IMM_LG", "IMM_PC",  -- action arg (1 byte) or int arg, 1 buffer pos (offset):  "LABEL_LG", "LABEL_PC",  -- action arg (1 byte), 1 buffer pos (offset):  "ALIGN",  -- action arg (1 byte), no buffer pos.  "ESC",  -- no action arg, no buffer pos.  "MARK",  -- action arg (1 byte), no buffer pos, terminal action:  "SECTION",  -- no args, no buffer pos, terminal action:  "STOP"}-- Maximum number of section buffer positions for dasm_put().-- CHECK: Keep this in sync with the C code!local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines.-- Action name -> action number (dynamically generated below).local map_action = {}-- First action number. Everything below does not need to be escaped.local actfirst = 256-#action_names-- Action list buffer and string (only used to remove dupes).local actlist = {}local actstr = ""-- Argument list for next dasm_put(). Start with offset 0 into action list.local actargs = { 0 }-- Current number of section buffer positions for dasm_put().local secpos = 1-------------------------------------------------------------------------------- Compute action numbers for action names.for n,name in ipairs(action_names) do  local num = actfirst + n - 1  map_action[name] = numend-- Dump action names and numbers.local function dumpactions(out)  out:write("DynASM encoding engine action codes:\n")  for n,name in ipairs(action_names) do    local num = map_action[name]    out:write(format("  %-10s %02X  %d\n", name, num, num))  end  out:write("\n")end-- Write action list buffer as a huge static C array.local function writeactions(out, name)  local nn = #actlist  local last = actlist[nn] or 255  actlist[nn] = nil -- Remove last byte.  if nn == 0 then nn = 1 end  out:write("static const unsigned char ", name, "[", nn, "] = {\n")  local s = "  "  for n,b in ipairs(actlist) do    s = s..b..","    if #s >= 75 then      assert(out:write(s, "\n"))      s = "  "    end  end  out:write(s, last, "\n};\n\n") -- Add last byte back.end-------------------------------------------------------------------------------- Add byte to action list.local function wputxb(n)  assert(n >= 0 and n <= 255 and n % 1 == 0, "byte out of range")  actlist[#actlist+1] = nend-- Add action to list with optional arg. Advance buffer pos, too.local function waction(action, a, num)  wputxb(assert(map_action[action], "bad action name `"..action.."'"))  if a then actargs[#actargs+1] = a end  if a or num then secpos = secpos + (num or 1) endend-- Add call to embedded DynASM C code.local function wcall(func, args)  wline(format("dasm_%s(Dst, %s);", func, concat(args, ", ")), true)end-- Delete duplicate action list chunks. A tad slow, but so what.local function dedupechunk(offset)  local al, as = actlist, actstr  local chunk = char(unpack(al, offset+1, #al))  local orig = find(as, chunk, 1, true)  if orig then    actargs[1] = orig-1 -- Replace with original offset.    for i=offset+1,#al do al[i] = nil end -- Kill dupe.  else    actstr = as..chunk  endend-- Flush action list (intervening C code or buffer pos overflow).local function wflush(term)  local offset = actargs[1]  if #actlist == offset then return end -- Nothing to flush.  if not term then waction("STOP") end -- Terminate action list.  dedupechunk(offset)  wcall("put", actargs) -- Add call to dasm_put().  actargs = { #actlist } -- Actionlist offset is 1st arg to next dasm_put().  secpos = 1 -- The actionlist offset occupies a buffer position, too.end-- Put escaped byte.local function wputb(n)  if n >= actfirst then waction("ESC") end -- Need to escape byte.  wputxb(n)end-------------------------------------------------------------------------------- Global label name -> global label number. With auto assignment on 1st use.local next_global = 10local map_global = setmetatable({}, { __index = function(t, name)  if not match(name, "^[%a_][%w_]*$") then werror("bad global label") end  local n = next_global  if n > 246 then werror("too many global labels") end  next_global = n + 1  t[name] = n  return nend})-- Dump global labels.local function dumpglobals(out, lvl)  local t = {}  for name, n in pairs(map_global) do t[n] = name end  out:write("Global labels:\n")  for i=10,next_global-1 do    out:write(format("  %s\n", t[i]))  end  out:write("\n")end-- Write global label enum.local function writeglobals(out, prefix)  local t = {}  for name, n in pairs(map_global) do t[n] = name end  out:write("enum {\n")  for i=10,next_global-1 do    out:write("  ", prefix, t[i], ",\n")  end  out:write("  ", prefix, "_MAX\n};\n")end-------------------------------------------------------------------------------- Arch-specific maps.local map_archdef = {}		-- Ext. register name -> int. name.local map_reg_rev = {}		-- Int. register name -> ext. name.local map_reg_num = {}		-- Int. register name -> register number.local map_reg_opsize = {}	-- Int. register name -> operand size.local map_reg_valid_base = {}	-- Int. register name -> valid base register?local map_reg_valid_index = {}	-- Int. register name -> valid index register?local reg_list = {}		-- Canonical list of int. register names.local map_type = {}		-- Type name -> { ctype, reg }local ctypenum = 0		-- Type number (for _PTx macros).local addrsize = "d"		-- Size for address operands. !x64-- Helper function to fill register maps.local function mkrmap(sz, names)  for n,name in ipairs(names) do    local iname = format("@%s%x", sz, n-1)    reg_list[#reg_list+1] = iname    map_archdef[name] = iname    map_reg_rev[iname] = name    map_reg_num[iname] = n-1    map_reg_opsize[iname] = sz    if sz == addrsize then      map_reg_valid_base[iname] = true      map_reg_valid_index[iname] = true    end  end  reg_list[#reg_list+1] = ""end-- Integer registers (dword, word and byte sized).mkrmap("d", {"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"})map_reg_valid_index[map_archdef.esp] = nilmkrmap("w", {"ax", "cx", "dx", "bx", "sp", "bp", "si", "di"})mkrmap("b", {"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"})-- FP registers (internally tword sized, but use "f" as operand size).mkrmap("f", {"st0", "st1", "st2", "st3", "st4", "st5", "st6", "st7"})-- SSE registers (oword sized, but qword and dword accessible).mkrmap("o", {"xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"})-- Operand size prefixes to codes.local map_opsize = {  byte = "b", word = "w", dword = "d", qword = "q", oword = "o", tword = "t",  aword = addrsize,}-- Operand size code to number.local map_opsizenum = {  b = 1, w = 2, d = 4, q = 8, o = 16, t = 10,}-- Operand size code to name.local map_opsizename = {  b = "byte", w = "word", d = "dword", q = "qword", o = "oword", t = "tword",  f = "fpword",}-- Valid index register scale factors.local map_xsc = {  ["1"] = 0, ["2"] = 1, ["4"] = 2, ["8"] = 3,}-- Condition codes.local map_cc = {  o = 0, no = 1, b = 2, nb = 3, e = 4, ne = 5, be = 6, nbe = 7,  s = 8, ns = 9, p = 10, np = 11, l = 12, nl = 13, le = 14, nle = 15,  c = 2, nae = 2, nc = 3, ae = 3, z = 4, nz = 5, na = 6, a = 7,  nge = 12, ge = 13, ng = 14, g = 15,}-- Reverse defines for registers.function _M.revdef(s)  return gsub(s, "@%w+", map_reg_rev)end-- Dump register names and numberslocal function dumpregs(out)  out:write("Register names, sizes and internal numbers:\n")  for _,reg in ipairs(reg_list) do    if reg == "" then      out:write("\n")    else      local name = map_reg_rev[reg]      local num = map_reg_num[reg]      local opsize = map_opsizename[map_reg_opsize[reg]]      out:write(format("  %-5s %-8s %d\n", name, opsize, num))    end  endend-------------------------------------------------------------------------------- Put action for label arg (IMM_LG, IMM_PC, REL_LG, REL_PC).local function wputlabel(aprefix, imm, num)  if type(imm) == "number" then    waction(aprefix.."LG", nil, num);    wputxb(imm)  else    waction(aprefix.."PC", imm, num)  endend-- Put signed byte or arg.local function wputsbarg(n)  if type(n) == "number" then    if n < -128 or n > 127 then      werror("signed immediate byte out of range")    end    if n < 0 then n = n + 256 end    wputb(n)  else waction("IMM_S", n) endend-- Put unsigned byte or arg.local function wputbarg(n)  if type(n) == "number" then    if n < 0 or n > 255 then      werror("unsigned immediate byte out of range")    end    wputb(n)  else waction("IMM_B", n) endend-- Put unsigned word or arg.local function wputwarg(n)  if type(n) == "number" then    if n < 0 or n > 65535 then      werror("unsigned immediate word out of range")    end    local r = n%256; n = (n-r)/256; wputb(r); wputb(n);  else waction("IMM_W", n) endend-- Put signed or unsigned dword or arg.local function wputdarg(n)  local tn = type(n)  if tn == "number" then    if n < 0 then n = n + 4294967296 end    local r = n%256; n = (n-r)/256; wputb(r);    r = n%256; n = (n-r)/256; wputb(r);    r = n%256; n = (n-r)/256; wputb(r); wputb(n);  elseif tn == "table" then    wputlabel("IMM_", n[1], 1)  else    waction("IMM_D", n)  endend-- Put operand-size dependent number or arg (defaults to dword).local function wputszarg(sz, n)  if not sz or sz == "d" then wputdarg(n)  elseif sz == "w" then wputwarg(n)  elseif sz == "b" then wputbarg(n)  elseif sz == "s" then wputsbarg(n)  else werror("bad operand size") endend-- Put multi-byte opcode with operand-size dependent modifications.local function wputop(sz, op)  local r  if sz == "w" then wputb(102) end  if op >= 16777216 then r = op % 16777216 wputb((op-r) / 16777216) op = r end  if op >= 65536 then r = op % 65536 wputb((op-r) / 65536) op = r end  if op >= 256 then r = op % 256 wputb((op-r) / 256) op = r end  if sz == "b" then op = op - 1 end  wputb(op)end-- Put ModRM or SIB formatted byte.local function wputmodrm(m, s, rm)  assert(m < 4 and s < 8 and rm < 8, "bad modrm operands")  wputb(64*m + 8*s + rm)end-- Put ModRM/SIB plus optional displacement.local function wputmrmsib(t, s, imark)  -- Register mode.  if sub(t.mode, 1, 1) == "r" then    wputmodrm(3, s, t.reg)    return  end  local disp = t.disp  local tdisp = type(disp)  -- No base register?  if not t.reg then    if t.xreg then      -- Indexed mode with index register only.      wputmodrm(0, s, 4) -- [xreg*xsc+disp] -> (0, s, esp) (xsc, xreg, ebp)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -