-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathnasm_emitter.lua
More file actions
87 lines (72 loc) · 1.83 KB
/
nasm_emitter.lua
File metadata and controls
87 lines (72 loc) · 1.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
local dbg = require("debugger")
local IR = require("IR_translator")
local module = {}
local function setup_output(out)
local o = {}
o.file = io.open(out..".asm", "w")
return o
end
local function add_import(out, import)
out.file:write("extern "..import.."\n")
end
local function emit_data(o)
o.file:write("section .data\n")
o.file:write("msg db \"End of program %i\",0\n")
o.file:write("section .bss\n")
end
local function emit_ir(ir, output)
local o = function(s) output.file:write(s) end
local lookup = {
["MOV"] = "mov ",
["alloc"] = "sub rsp, ",
["ADD"] = "add ",
["SUB"] = "sub ",
["MUL"] = "mul ",
["DIV"] = "xor rdx, rdx\n\tidiv ",
["NEG"] = "neg "
}
for k,v in pairs(ir.code) do
local ins = lookup[v.type]
if v.type ~= "alloc" then
ins = "\t"..ins
if tonumber(v.reg1) ~= nil then
ins = ins.."qword "
end
ins = ins..v.reg1
if v.reg2 ~= nil then
if tonumber(v.reg2) ~= nil then
ins = ins..", qword "
else
ins = ins..", "
end
ins = ins..v.reg2
end
else
ins = "\t"..ins.."qword "..v.size
end
o(ins.."\t\t;"..(v.cmt or "").."\n")
end
end
module.emit = function(ir, out)
local output = setup_output(out)
add_import(output, "printf")
add_import(output, "ExitProcess")
-- write main header
output.file:write("\nsection .text\n")
output.file:write(" global main\n")
output.file:write("main:\n")
output.file:write(" sub rsp, 32\n") -- shadow space
output.file:write(" mov rdx, -1\n") -- init rdx to -1
emit_ir(ir, output)
--output.file:write(" sub rsp, 8\n") -- align
output.file:write(" mov rdx, rax\n")
-- emit printf
output.file:write(" mov rcx, msg\n")
output.file:write(" call printf\n")
-- emit ExitProcess call
output.file:write(" xor ecx,ecx\n")
output.file:write(" call ExitProcess\n")
emit_data(output)
output.file:close()
end
return module