Advertisement
Tatantyler

DCPU-16 Assembler

Mar 29th, 2013
534
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 16.78 KB | None | 0 0
  1. -- DCPU-16 Assembler in Lua, by KillaVanilla
  2.  
  3. -- If it's an assembler, why is it called DCPUCompiler?
  4.  
  5. -- Usage:
  6. -- DCPUCompiler <input> <output> <symbols> <arguments>
  7.  
  8. -- Arguments are denoted by "-" or "--", and MUST come after the input/output/symbolFile arguments.
  9.  
  10. local args = {...}
  11.  
  12. if #args < 3 then
  13.     print("Usage: ")
  14.     print(fs.getName(shell.getRunningProgram()).." <input> <output> <symbols> <arguments>")
  15.     print("Required parameters:")
  16.     print("<input> : Input assembly file.")
  17.     print("<output> : Output binary file. ")
  18.     print("<symbols> : Symbols file, useful for debugging. Pass as \"-\" to disable.")
  19.     print("Arguments:")
  20.     print("These must come after the aforementioned parameters.")
  21.     print("-p / --print : Save all output to \"assemblyLog\".")
  22.     print("-a / --ascii / --ascii-out / --text-out / --text : Output as a list of DAT instructions instead of as a binary.")
  23.     print("-d / --debug : Enable debugging output (values emitted, parser output, etc.).")
  24.     print("Do note that this compiler may still have a few bugs in it; if you find any, please report them ASAP, ok?")
  25.     return
  26. end
  27.  
  28. local flags = {}
  29. for i=4, #args do
  30.     if string.sub(args[i], 1, 2) == "--" then
  31.         flags[string.sub(args[i],3)] = true
  32.     elseif string.sub(args[i], 1, 1) == "-" then
  33.         flags[string.sub(args[i],2)] = true
  34.     end
  35. end
  36.  
  37. if flags["p"] or flags["print"] then
  38.     local file = fs.open("assemblyLog", "w")
  39.     file.close()
  40. end
  41.  
  42. -- ooooobbbbbaaaaaa (MSB-0 DCPU Instruction)
  43. -- aaaaaabbbbbooooo (LSB-0 DCPU Instruction)
  44.  
  45. -- aaaaaaooooo00000 (LSB-0 DCPU Special Instruction)
  46. -- 00000oooooaaaaaa (MSB-0 DCPU Special Instruction)
  47.  
  48. -- A few tables to help with parsing:
  49.  
  50. local operandValues = {
  51.     ["A"] = 0,
  52.     ["B"] = 0x01,
  53.     ["C"] = 0x02,
  54.     ["X"] = 0x03,
  55.     ["Y"] = 0x04,
  56.     ["Z"] = 0x05,
  57.     ["I"] = 0x06,
  58.     ["J"] = 0x07,
  59.     ["[A]"] = 0x08,
  60.     ["[B]"] = 0x09,
  61.     ["[C]"] = 0x0A,
  62.     ["[X]"] = 0x0B,
  63.     ["[Y]"] = 0x0C,
  64.     ["[Z]"] = 0x0D,
  65.     ["[I]"] = 0x0E,
  66.     ["[J]"] = 0x0F,
  67.     --[[["[A+]"] = 0x10,
  68.     ["[B+]"] = 0x11,
  69.     ["[C+]"] = 0x12,
  70.     ["[X+]"] = 0x13,
  71.     ["[Y+]"] = 0x14,
  72.     ["[Z+]"] = 0x15,
  73.     ["[I+]"] = 0x16,
  74.     ["[J+]"] = 0x17,]]
  75.     ["PUSH"] = 0x18,
  76.     ["POP"] = 0x18,
  77.     ["PEEK"] = 0x19,
  78.     ["[SP]"] = 0x19,
  79.     ["PICK"] = 0x1A,
  80.     --["[SP+]"] = 0x1A,
  81.     ["SP"] = 0x1B,
  82.     ["PC"] = 0x1C,
  83.     ["EX"] = 0x1D,
  84.     --["[]"] = 0x1E, -- next word (pointer)
  85.     --[""] = 0x1F, -- next word (literal)
  86.     ["-1"] = 0x20,
  87.     ["0"] = 0x21,
  88.     ["1"] = 0x22,
  89.     ["2"] = 0x23,
  90.     ["3"] = 0x24,
  91.     ["4"] = 0x25,
  92.     ["5"] = 0x26,
  93.     ["6"] = 0x27,
  94.     ["7"] = 0x28,
  95.     ["8"] = 0x29,
  96.     ["9"] = 0x2A,
  97.     ["10"] = 0x2B,
  98.     ["11"] = 0x2C,
  99.     ["12"] = 0x2D,
  100.     ["13"] = 0x2E,
  101.     ["14"] = 0x2F,
  102.     ["15"] = 0x30,
  103.     ["16"] = 0x31,
  104.     ["17"] = 0x32,
  105.     ["18"] = 0x33,
  106.     ["19"] = 0x34,
  107.     ["20"] = 0x35,
  108.     ["21"] = 0x36,
  109.     ["22"] = 0x37,
  110.     ["23"] = 0x38,
  111.     ["24"] = 0x39,
  112.     ["25"] = 0x3A,
  113.     ["26"] = 0x3B,
  114.     ["27"] = 0x3C,
  115.     ["28"] = 0x3D,
  116.     ["29"] = 0x3E,
  117.     ["30"] = 0x3F,
  118. }
  119.  
  120. local opcodes = {
  121.     ["SET"] = 0x01,
  122.     ["ADD"] = 0x02,
  123.     ["SUB"] = 0x03,
  124.     ["MUL"] = 0x04,
  125.     ["MLI"] = 0x05,
  126.     ["DIV"] = 0x06,
  127.     ["DVI"] = 0x07,
  128.     ["MOD"] = 0x08,
  129.     ["MDI"] = 0x09,
  130.     ["AND"] = 0x0A,
  131.     ["BOR"] = 0x0B,
  132.     ["XOR"] = 0x0C,
  133.     ["SHR"] = 0x0D,
  134.     ["ASR"] = 0x0E,
  135.     ["SHL"] = 0x0F,
  136.     ["IFB"] = 0x10,
  137.     ["IFC"] = 0x11,
  138.     ["IFE"] = 0x12,
  139.     ["IFN"] = 0x13,
  140.     ["IFG"] = 0x14,
  141.     ["IFA"] = 0x15,
  142.     ["IFL"] = 0x16,
  143.     ["IFU"] = 0x17,
  144.     ["ADX"] = 0x1A,
  145.     ["SBX"] = 0x1B,
  146.     ["STI"] = 0x1E,
  147.     ["STD"] = 0x1F,
  148. }
  149.  
  150. local spec_opcodes = {
  151.     ["JSR"] = 0x01,
  152.     ["INT"] = 0x08,
  153.     ["IAG"] = 0x09,
  154.     ["IAS"] = 0x0A,
  155.     ["RFI"] = 0x0B,
  156.     ["IAQ"] = 0x0C,
  157.     ["HWN"] = 0x10,
  158.     ["HWQ"] = 0x11,
  159.     ["HWI"] = 0x12,
  160. }
  161.  
  162. local literalOperandTransTable = { -- Translates the a-value only literal operands into the literals they represent and vice versa.
  163.     [0xFFFF] = 0x20,
  164.     [0] = 0x21,
  165.     [1] = 0x22,
  166.     [2] = 0x23,
  167.     [3] = 0x24,
  168.     [4] = 0x25,
  169.     [5] = 0x26,
  170.     [6] = 0x27,
  171.     [7] = 0x28,
  172.     [8] = 0x29,
  173.     [9] = 0x2A,
  174.     [10] = 0x2B,
  175.     [11] = 0x2C,
  176.     [12] = 0x2D,
  177.     [13] = 0x2E,
  178.     [14] = 0x2F,
  179.     [15] = 0x30,
  180.     [16] = 0x31,
  181.     [17] = 0x32,
  182.     [18] = 0x33,
  183.     [19] = 0x34,
  184.     [20] = 0x35,
  185.     [21] = 0x36,
  186.     [22] = 0x37,
  187.     [23] = 0x38,
  188.     [24] = 0x39,
  189.     [25] = 0x3A,
  190.     [26] = 0x3B,
  191.     [27] = 0x3C,
  192.     [28] = 0x3D,
  193.     [29] = 0x3E,
  194.     [30] = 0x3F,
  195.     [0x20] = 0xFFFF,
  196.     [0x21] = 0,
  197.     [0x22] = 1,
  198.     [0x23] = 2,
  199.     [0x24] = 3,
  200.     [0x25] = 4,
  201.     [0x26] = 5,
  202.     [0x27] = 6,
  203.     [0x28] = 7,
  204.     [0x29] = 8,
  205.     [0x2A] = 9,
  206.     [0x2B] = 10,
  207.     [0x2C] = 11,
  208.     [0x2D] = 12,
  209.     [0x2E] = 13,
  210.     [0x2F] = 14,
  211.     [0x30] = 15,
  212.     [0x31] = 16,
  213.     [0x32] = 17,
  214.     [0x33] = 18,
  215.     [0x34] = 19,
  216.     [0x35] = 20,
  217.     [0x36] = 21,
  218.     [0x37] = 22,
  219.     [0x38] = 23,
  220.     [0x39] = 24,
  221.     [0x3A] = 25,
  222.     [0x3B] = 26,
  223.     [0x3C] = 27,
  224.     [0x3D] = 28,
  225.     [0x3E] = 29,
  226.     [0x3F] = 30,
  227. }
  228.  
  229. local function compileMsg(line, severity, text)
  230.     -- Severity:
  231.     -- 0 -- Debug (light grey)
  232.     -- 1 -- Info (white)
  233.     -- 2 -- Warning (yellow; unused)
  234.     -- 3 -- Error (red; stops compile)
  235.     local file = {}
  236.     if flags["p"] or flags["print"] then
  237.         file = fs.open("assemblyLog", "a")
  238.     end
  239.     term.setBackgroundColor(colors.black)
  240.     if severity == 0 then
  241.         term.setTextColor(colors.lightGray)
  242.         if flags["d"] or flags["debug"] then
  243.             print("[DEBUG] "..text)
  244.             if flags["p"] or flags["print"] then
  245.                 file.writeLine("[DEBUG] "..text)
  246.             end
  247.         end
  248.     elseif severity == 1 then
  249.         term.setTextColor(colors.white)
  250.         print("[INFO] "..text)
  251.         if flags["p"] or flags["print"] then
  252.             file.writeLine("[INFO] "..text)
  253.         end
  254.     --[[elseif severity == 2 then
  255.         term.setTextColor(colors.yellow)
  256.         print("[WARN] "..text)
  257.         if flags["p"] or flags["print"] then
  258.             file.writeLine("[WARN] "..text)
  259.         end]]
  260.     elseif severity == 3 then
  261.         term.setTextColor(colors.red)
  262.         print("[ERR] "..text)
  263.         if flags["p"] or flags["print"] then
  264.             file.writeLine("[ERR] "..text)
  265.             file.close()
  266.         end
  267.         error("Compile failed at line "..line..".", 0)
  268.     end
  269.     if flags["p"] or flags["print"] then
  270.         file.close()
  271.     end
  272. end
  273.  
  274. local function parseLine(line, line_num, labels) -- Parse a single lime of DCPU-16 assembly, generating 3 values: the opcode w/ operands, and the two words referred to by the "next word" operands.
  275.     local ins, b, a = string.match(line, "(%a%a%a)%s+([%w_%-%[%]%+]+)%,?%s*([%w_%-%[%]%+]*)")
  276.     compileMsg(line_num, 0, "Line Parser Input: "..line)
  277.     if not ins then
  278.         return
  279.     end
  280.     local ptr_b_reg, ptr_b_lit = string.match(b, "%[(%a+)%+(%w+)%]")
  281.     local ptr_a_reg, ptr_a_lit = string.match(a, "%[(%a+)%+(%w+)%]")
  282.     if operandValues[b] then -- Does B match a recognized operand?
  283.         b = operandValues[b]
  284.         if b >= 0x20 then
  285.             ptr_b_lit = literalOperandTransTable[b]
  286.             b = 0x1F
  287.         end
  288.     elseif labels[b] then -- Is B a label?
  289.         compileMsg(line_num, 0, "B is a label: "..b)
  290.         b = 0x1F
  291.         ptr_b_lit = labels[b][1]
  292.     elseif ptr_b_reg then -- Did we find a [register+offset] combo?
  293.         ptr_b_reg = string.upper(ptr_b_reg)
  294.         if ptr_b_reg == "A" then
  295.             b = 0x10
  296.         elseif ptr_b_reg == "B" then
  297.             b = 0x11
  298.         elseif ptr_b_reg == "C" then
  299.             b = 0x12
  300.         elseif ptr_b_reg == "X" then
  301.             b = 0x13
  302.         elseif ptr_b_reg == "Y" then
  303.             b = 0x14
  304.         elseif ptr_b_reg == "Z" then
  305.             b = 0x15
  306.         elseif ptr_b_reg == "I" then
  307.             b = 0x16
  308.         elseif ptr_b_reg == "J" then
  309.             b = 0x17
  310.         else
  311.             compileMsg(line_num, 3, "Unrecognized register: "..ptr_b_reg)
  312.         end
  313.     elseif string.sub(b, 1, 1) == "[" and string.sub(b, #b, #b) == "]" then -- Is this a reference?
  314.         b = 0x1E
  315.         if tonumber(string.sub(b, 2, #b-1)) then
  316.             ptr_b_lit = tonumber(string.sub(b, 2, #b-1))
  317.         elseif labels[ string.sub(a, 2, #a-1) ] then
  318.             ptr_a_lit = labels[ string.sub(a, 2, #a-1) ][1]
  319.         end
  320.     elseif tonumber(b) then -- Is it a literal?
  321.         ptr_b_lit = tonumber(b)
  322.         b = 0x1F
  323.     else
  324.         compileMsg(line_num, 3, "Unrecognized expression: "..b)
  325.     end
  326.     if a and a ~= "" then
  327.         if operandValues[a] then
  328.             a = operandValues[a]
  329.         elseif labels[a] then
  330.             compileMsg(line_num, 0, "A is a label: "..a)
  331.             if labels[a][1] <= 30 then
  332.                 a = literalOperandTransTable[labels[a][1]]
  333.             else
  334.                 a = 0x1F
  335.                 ptr_a_lit = labels[a][1]
  336.             end
  337.         elseif ptr_a_reg then
  338.             ptr_a_reg = string.upper(ptr_a_reg)
  339.             if ptr_a_reg == "A" then
  340.                 a = 0x10
  341.             elseif ptr_a_reg == "B" then
  342.                 a = 0x11
  343.             elseif ptr_a_reg == "C" then
  344.                 a = 0x12
  345.             elseif ptr_a_reg == "X" then
  346.                 a = 0x13
  347.             elseif ptr_a_reg == "Y" then
  348.                 a = 0x14
  349.             elseif ptr_a_reg == "Z" then
  350.                 a = 0x15
  351.             elseif ptr_a_reg == "I" then
  352.                 a = 0x16
  353.             elseif ptr_a_reg == "J" then
  354.                 a = 0x17
  355.             elseif ptr_a_reg == "SP" then
  356.                 a = 0x1A
  357.             else
  358.                 compileMsg(line_num, 3, "Unrecognized register: "..ptr_a_reg)
  359.             end
  360.         elseif string.sub(a, 1, 1) == "[" and string.sub(a, #a, #a) == "]" then
  361.             if tonumber(string.sub(a, 2, #a-1)) then
  362.                 ptr_a_lit = tonumber(string.sub(a, 2, #a-1))
  363.             elseif labels[ string.sub(a, 2, #a-1) ] then
  364.                 ptr_a_lit = labels[ string.sub(a, 2, #a-1) ][1]
  365.             else
  366.                 compileMsg(line_num, 3, "Unrecognized label: "..string.sub(a, 2, #a-1))
  367.             end
  368.             a = 0x1E
  369.         elseif tonumber(a) then
  370.             ptr_a_lit = tonumber(a)
  371.             a = 0x1F
  372.         else
  373.             compileMsg(line_num, 3, "Unrecognized label: "..string.sub(a, 2, #a-1))
  374.         end
  375.     end
  376.     -- Opcode construction:
  377.     local ret = 0
  378.     if opcodes[ins] then -- Use the instruction value as a "base":
  379.         compileMsg(line_num, 0, "Instruction is normal: 0x"..string.format("%X", opcodes[ins]))
  380.         ret = opcodes[ins]
  381.     elseif spec_opcodes[ins] then
  382.         compileMsg(line_num, 0, "Instruction is special: 0x"..string.format("%X", spec_opcodes[ins]))
  383.         -- Shift the instruction value to the middle:
  384.         ret = bit.blshift(spec_opcodes[ins], 5)
  385.     end
  386.     compileMsg(line_num, 0, "B-value: 0x"..string.format("%X", b))
  387.     if a and a ~= "" then
  388.         compileMsg(line_num, 0, "A-value: 0x"..string.format("%X", a))
  389.     end
  390.     -- Add the b-value:
  391.     if opcodes[ins] then
  392.         ret = bit.bor(ret, bit.blshift(b, 5))
  393.     elseif spec_opcodes[ins] then
  394.         ret = bit.bor(ret, bit.blshift(b, 10))
  395.     end
  396.    
  397.     if opcodes[ins] and (a and a ~= "") then
  398.         -- Add the a-value:
  399.         ret = bit.bor(ret, bit.blshift(a, 10))
  400.     end
  401.    
  402.     local emit = "Emit: 0x"..string.format("%X", ret)
  403.     if ptr_a_lit then
  404.         emit = emit..", 0x"..string.format("%X", ptr_a_lit)
  405.     end
  406.     if ptr_b_lit then
  407.         emit = emit..", 0x"..string.format("%X", ptr_b_lit)
  408.     end
  409.     compileMsg(line_num, 0, emit)
  410.    
  411.     return ret, ptr_a_lit, ptr_b_lit
  412. end
  413.  
  414. local function determineInstructionSize(line)
  415.     local size = 1
  416.     if string.find(line, "DAT ") then
  417.         local dS, dE = string.find(line, "DAT ")
  418.         local data_str = string.sub(line, dE+1)
  419.         for dat in string.gmatch(data_str, "([^%,]+)%,?") do
  420.             dat = string.match(dat, "%s*(%S+)")
  421.             if tonumber(dat) then
  422.                 size = size+1
  423.             elseif string.sub(dat, 1,1) == "\"" then
  424.                 for i=2, #dat-1 do
  425.                     size = size+1
  426.                 end
  427.             end
  428.         end
  429.     else
  430.         local ins, b, a = string.match(line, "(%a%a%a)%s+([%w_%-%[%]%+]+)%,?%s*([%w_%-%[%]%+]*)")
  431.         if not operandValues[b] then
  432.             size = size+1
  433.         else
  434.             if operandValues[b] >= 0x20 then
  435.                 size = size+1
  436.             end
  437.         end
  438.         if a and a ~= "" then
  439.             if not operandValues[a] then
  440.                 size = size+1
  441.             end
  442.         end
  443.     end
  444.     return size
  445. end
  446.  
  447. local function generateMacroTable(lines)
  448.     local macros = {}
  449.     local currentMacro = {}
  450.     local inMacro = false
  451.     local cMacroName = ""
  452.     for i, line in ipairs(lines) do -- Label Accumulation
  453.         local no_whtspace = string.match(line, "%s*(.+)")
  454.         if string.sub(no_whtspace, 1, 7) == ".macro " then
  455.             if not inMacro then
  456.                 cMacroName = string.sub(no_whtspace, 8)
  457.                 inMacro = true
  458.             end
  459.         elseif string.sub(no_whtspace, 1, 9) == ".endmacro" then
  460.             if inMacro then
  461.                 macros[cMacroName] = currentMacro
  462.                 currentMacro = {}
  463.                 cMacroName = ""
  464.                 inMacro = false
  465.             end
  466.         elseif inMacro then
  467.             table.insert(currentMacro, line)
  468.         end
  469.     end
  470.     return macros
  471. end
  472.  
  473. local function readLines(file)
  474.     local lines = {}
  475.     local iHandle = io.open(file, "r")
  476.     for line in iHandle:lines() do
  477.         table.insert(lines, line)
  478.     end
  479.     iHandle:close()
  480.     return lines
  481. end
  482.  
  483. local function generateSymTable(lines)
  484.     local labels = {}
  485.     local addr = 0
  486.     local sTime = os.clock()
  487.     for i, line in ipairs(lines) do -- Label Accumulation
  488.         if string.match(line, "%:(.+)") then
  489.             local label = string.match(line, "%:(.+)")
  490.             labels[label] = {addr, i}
  491.             compileMsg(0, 0, "Label found: "..label.." at address 0x"..string.format("%X", addr)..".")
  492.         elseif string.match(line, "(.+)%:") then
  493.             local label = string.match(line, "(.+)%:")
  494.             labels[label] = {addr, i}
  495.             compileMsg(0, 0, "Label found: "..label.." at address 0x"..string.format("%X", addr)..".")
  496.         end
  497.         if string.match(line, "(%a%a%a)%s+([%w_%-%[%]%+]+)%,?%s*([%w_%-%[%]%+]*)") then
  498.             local sz = determineInstructionSize(line)
  499.             if sz then
  500.                 compileMsg(i, 0, "0x"..string.format("%X", addr)..": "..line.." (size: "..sz..")")
  501.                 addr = addr+sz
  502.             else
  503.                 compileMsg(i, 3, "Syntax error: "..line)
  504.             end
  505.         end
  506.     end
  507.     return labels, generateMacroTable(lines)
  508. end
  509.  
  510. local function doSymbolSub(lines, labels, macros)
  511.     local i = 1
  512.     while true do
  513.         if not lines[i] then
  514.             break
  515.         end
  516.         local no_whtspace = string.match(lines[i], "%s*(.+)")
  517.         if string.sub(no_whtspace, 1, 9) == ".insmacro" then
  518.             local macroName = string.sub(no_whtspace, 10)
  519.             if macros[macroName] then
  520.                 for i2=#macros[macroName], 1, -1 do
  521.                     table.insert(lines, i2, macros[macroName][i])
  522.                 end
  523.             else
  524.                 compileMsg(i, 3, "Undefined macro reference: "..macroName)
  525.             end
  526.         end
  527.         local ins, b, a = string.match(lines[i], "(%a%a%a)%s+([%w_%-%[%]%+]+)%,?%s*([%w_%-%[%]%+]*)")
  528.         if ins then
  529.             for index, label in pairs(labels) do
  530.                 if b == index then
  531.                     b = label[1]
  532.                 end
  533.                 if a == index then
  534.                     a = label[1]
  535.                 end
  536.                 --lines[i] = string.gsub(lines[i], index, label[1]) -- this is the old replacer code
  537.             end
  538.             local repLine = ins.." "..b
  539.             if a and a ~= "" then
  540.                 repLine = repLine..", "..a
  541.             end
  542.             if no_whtspace ~= repLine then
  543.                 compileMsg(i, 0, "Replacing line "..i.." (\""..no_whtspace.."\") with \""..repLine.."\".")
  544.                 lines[i] = repLine
  545.             end
  546.         end
  547.         i=i+1
  548.     end
  549.     return lines
  550. end
  551.  
  552. local function parseSingleFile(inFile, outFile, labelsFile)
  553.     local mem = {}
  554.     local lines = readLines(inFile)
  555.    
  556.     compileMsg(0, 1, "Step 1: Symbol Resolution")
  557.     local labels, macros = generateSymTable(lines)
  558.     compileMsg(0, 1, "Symbol resolution complete.")
  559.     compileMsg(0, 1, "Step 2a: Symbol substitution -- Pass 1...")
  560.     lines = doSymbolSub(lines, labels, macros)
  561.     compileMsg(0, 1, "Symbol substitution complete.")
  562.     compileMsg(0, 1, "Step 2b: Label Adjustment...")
  563.     labels, macros = generateSymTable(lines)
  564.     lines = readLines(inFile)
  565.     compileMsg(0, 1, "Label adjustment complete.")
  566.     compileMsg(0, 1, "Step 2c: Symbol substitution -- Pass 2...")
  567.     lines = doSymbolSub(lines, labels, macros)
  568.     compileMsg(0, 1, "Symbol substitution complete.")
  569.     if outFile and (flags["o"] or flags["optimize-only"]) then
  570.         local oHandle = fs.open(outFile, "w")
  571.         for i, line in ipairs(lines) do
  572.             oHandle.writeLine(line)
  573.         end
  574.         oHandle.close()
  575.         return
  576.     end
  577.     compileMsg(0, 1, "Step 3: Final Assembly / Output Generation...")
  578.     for i, line in ipairs(lines) do
  579.         if string.find(line, "DAT ") then
  580.             local dS, dE = string.find(line, "DAT ")
  581.             local data_str = string.sub(line, dE+1)
  582.             for dat in string.gmatch(data_str, "([^%,]+)%,?") do
  583.                 dat = string.match(dat, "%s*(%S+)")
  584.                 if tonumber(dat) then
  585.                     table.insert(mem, tonumber(dat))
  586.                 elseif string.sub(dat, 1,1) == "\"" then
  587.                     for i=2, #dat-1 do
  588.                         table.insert(mem, string.byte(string.sub(dat,i,i)))
  589.                     end
  590.                 end
  591.             end
  592.         else
  593.             local at_pc, at_pc_1, at_pc_2 = parseLine(line, i, labels)
  594.             if at_pc then
  595.                 table.insert(mem, at_pc)
  596.             end
  597.             if at_pc_1 then
  598.                 table.insert(mem, at_pc_1)
  599.             end
  600.             if at_pc_2 then
  601.                 table.insert(mem, at_pc_2)
  602.             end
  603.         end
  604.     end
  605.     compileMsg(0, 1, "Assembly complete; "..(#mem*2).." bytes generated.")
  606.     if outFile then
  607.         if flags["a"] or flags["ascii-out"] or flags["ascii"] or flags["text"] or flags["text-out"] then
  608.             local oHandle = fs.open(outFile, "w")
  609.             for index, byte in ipairs(mem) do
  610.                 oHandle.writeLine("DAT 0x"..string.format("%X", byte))
  611.             end
  612.             oHandle.close()
  613.         else
  614.             local oHandle = fs.open(outFile, "wb")
  615.             for index, byte in ipairs(mem) do
  616.                 oHandle.write(byte)
  617.             end
  618.             oHandle.close()
  619.         end
  620.     end
  621.     if labelsFile and labelsFile ~= "-" then
  622.         local lfHandle = fs.open(labelsFile, "w")
  623.         lfHandle.writeLine("-- BEGIN LABEL DEFINITIONS --")
  624.         lfHandle.writeLine("")
  625.         for i,v in pairs(labels) do
  626.             lfHandle.writeLine(i..": 0x"..string.format("%X", v[1]).." - "..v[2])
  627.         end
  628.         lfHandle.writeLine("-- END LABEL DEFINITIONS --")
  629.         lfHandle.writeLine("")
  630.         lfHandle.writeLine("-- BEGIN MACRO DEFINITIONS --")
  631.         lfHandle.writeLine("")
  632.         for i,v in pairs(macros) do
  633.             lfHandle.writeLine(i..":")
  634.             for i2, line in ipairs(v) do
  635.                 lfHandle.writeLine(line)
  636.             end
  637.             lfHandle.writeLine("")
  638.         end
  639.         lfHandle.writeLine("-- END MACRO DEFINITIONS --")
  640.         lfHandle.close()
  641.     end
  642.     return mem
  643. end
  644. parseSingleFile(args[1], args[2], args[3])
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement