commit 2be87f778a56964007d4c5ccf7171fa000149f79 from: Onana Onana Xavier Manuel date: Fri Sep 25 22:25:29 2026 UTC Commit 42 commit - 0d8d680e5d37cebe6ad59eb5ddb386ed9198507e commit + 2be87f778a56964007d4c5ccf7171fa000149f79 blob - c13e3c987375f4d827f999dae8a63de533fce3b5 blob + 771e0898b66bd3ce7b85cd60ab72614d746765e4 --- tools/6c +++ tools/6c @@ -5,6 +5,9 @@ ----------------------------------------------------------------------- local mnemonics = { "mov", "cli", "hlt", "ret", "sti" } +-- This is kinda a double definition but fix later :^) +local arithmetics = { "+", "-", "*", "/", "^", "~", "|", "&" } + local symbols = { ",", "[", "]", "(", ")", "{", "}", "*", "/", "-", "+", "!", "~", "#", "?", ";", ":" } @@ -12,6 +15,8 @@ local regs8 = { "al", "ah", "bl", "bh", "cl", "ch", "d local asmkwd = { "asm" } +local tk_misc = { "hexadecimal", "integer", "id", "\n" } + local tk_type = { } local count = 0 @@ -35,14 +40,14 @@ for i = 1, #asmkwd do tk_type[asmkwd[i]] = count end +for i = 1, #tk_misc do + count = count + 1 + tk_type[tk_misc[i]] = count +end local function cincadd() count = count + 1 return count end -tk_type.hexadecimal = cincadd() -tk_type.integer = cincadd() -tk_type.id = cincadd() -tk_type["\n"] = cincadd() ----------------------------------------------------------------------- -- DEBUGING @@ -110,6 +115,21 @@ local function isregs8(m) return false end +local function isarithmetic(a) + local key = gettokenkey(a) + + if key == nil then + return false + end + + for i,v in ipairs(arithmetics) do + if v == key then + return true + end + end + return false +end + ----------------------------------------------------------------------- -- BITWISE OPERATIONS ----------------------------------------------------------------------- @@ -365,9 +385,9 @@ while true do end if ishex == true then - emittoken(nline, ncol, tk_type.hexadecimal, #data, data) + emittoken(nline, ncol, tk_type["hexadecimal"], #data, data) else - emittoken(nline, ncol, tk_type.integer, #data, data) + emittoken(nline, ncol, tk_type["integer"], #data, data) end i = i + #data elseif char == " " or char == "\t" then blob - 7ec0dac0f81122dc109dd6e9660fda89a89e952c blob + c40eacaa915eea26d8db27517a070e966ab2c204 --- tools/6l +++ tools/6l @@ -5,6 +5,9 @@ ----------------------------------------------------------------------- local mnemonics = { "mov", "cli", "hlt", "ret", "sti" } +-- This is kinda a double definition but fix later :^) +local arithmetics = { "+", "-", "*", "/", "^", "~", "|", "&" } + local symbols = { ",", "[", "]", "(", ")", "{", "}", "*", "/", "-", "+", "!", "~", "#", "?", ";", ":" } @@ -12,6 +15,8 @@ local regs8 = { "al", "ah", "bl", "bh", "cl", "ch", "d local asmkwd = { "asm" } +local tk_misc = { "hexadecimal", "integer", "id", "\n" } + local tk_type = { } local count = 0 @@ -35,14 +40,14 @@ for i = 1, #asmkwd do tk_type[asmkwd[i]] = count end +for i = 1, #tk_misc do + count = count + 1 + tk_type[tk_misc[i]] = count +end local function cincadd() count = count + 1 return count end -tk_type.hexadecimal = cincadd() -tk_type.integer = cincadd() -tk_type.id = cincadd() -tk_type["\n"] = cincadd() ----------------------------------------------------------------------- -- DEBUGING @@ -110,6 +115,21 @@ local function isregs8(m) return false end +local function isarithmetic(a) + local key = gettokenkey(a) + + if key == nil then + return false + end + + for i,v in ipairs(arithmetics) do + if v == key then + return true + end + end + return false +end + ----------------------------------------------------------------------- -- BITWISE OPERATIONS ----------------------------------------------------------------------- @@ -289,6 +309,26 @@ local function readhdr() return { line = line, col = col, type = type, len = len, raw = raw } end +local function typematch(token, array) + local len = #array + + for i = 1, len do + if type(array[i]) == "table" then + local match = typematch(token, array[i]) + if match == true then + return match + end + elseif type(array[i]) == "string" then + if token.type == tk_type[array[i]] then + return true + end + else + perror("illegal typematch must be array or string") + end + end + return false +end + -- This functions reads an asm line and tells if its a label or instructions -- If the return type is instructions, it will tell if its imm8, r8, etc -- @@ -306,7 +346,7 @@ local function operlyze(op, ret) ret.opcount = 1 table.insert(ret.details, ASM_R8) table.insert(ret.operands, op) - elseif op.type == tk_type.integer then + elseif op.type == tk_type["integer"] then ret.opcount = 1 local val = intval(op.raw) table.insert(ret.operands, op) @@ -316,7 +356,7 @@ local function operlyze(op, ret) else perror("operand 1 of instruction on line " .. op.line .. " is too big!") end - elseif op.type == tk_type.hexadecimal then + elseif op.type == tk_type["hexadecimal"] then ret.opcount = 1 local val = hexval(op.raw) table.insert(ret.operands, op) @@ -327,6 +367,68 @@ local function operlyze(op, ret) else perror("operand 1 of instruction on line " .. op.line .. " is too big!") end + + -- You can have max 1 segment registers and 2 GPR. For clarity + -- fs:rbx + rcx counts as 1 segment and 2 GPR + -- the displacement is capped to 32-bit signed + -- No paranthesis allowed for now + -- You cannot multiply the base reg (not allowed according to manual) + -- You can only multiply index reg by a factor of 2 up to max value 8 (1, 2, 4, 8) + elseif op.type == tk_type["["] then + local brackets = { opened = 0, closed = 0 } + + while true do + local pre = op + op = readhdr() + + if op.type == tk_type["\n"] or op.type == tk_type["]"] then + break + end + + if op.type == tk_type["["] then + perror("illegal nested operand at line " .. op.line) + end + + if isregs8(op) == true then + if typematch(pre, { "[", arithmetics }) == false then + perror("missing arithmetic prefix for register " .. gettokenkey(op) .. + " line " .. op.line) + end + + if #ret.memblock.regs == 0 and typematch(pre, { "+", "-" }) == false then + perror("Base register `" .. gettokenkey(op) .. + "` can only be applied + or - on it line " .. op.line) + elseif #ret.memblock.regs == 1 and typematch(pre, { "+", "-", "*" }) == false then + perror("Index register `" .. gettokenkey(op) .. + "` can only be applied +, - or * on it line " .. op.line) + end + table.insert(ret.memblock.regs, gettokenkey(op)) + + elseif typematch(op, { "hexadecimal", "integer" }) then + if typematch(pre, { "[", arithmetics }) == false then + perror("missing arithmetic/paranthesis prefix for whole number " .. op.raw .. + " line " .. op.line) + end + -- Other arithmetic symbols + elseif isarithmetic(op) == true then + if typematch(pre, { regs8, "hexadecimal", "integer" }) == false then + perror("illegal token before " .. gettokenkey(op) .. " at line " .. op.line) + end + else + perror("illegal token " .. gettokenkey(op) .. " at line " .. op.line) + end + + if #ret.memblock.regs > 2 then + perror("a maximum of 2 GPRs are allowed in memory block. Line " .. op.line) + end + end + + if op.type ~= tk_type["]"] then + perror("Missing closing `]` at line " .. op.line) + end + + table.insert(ret.details, ASM_MEM8) + ret.opcount = 1 elseif op.type == tk_type["\n"] then ret.opcount = 0 else @@ -340,7 +442,12 @@ local function asmlyze(first) type = ASM_INSTRUCTION, opcount = 0, details = { }, - operands = { } + operands = { }, + memblock = { + regs = { }, + dispsize = 0, + blevel = 0, + } } local op1 = readhdr() @@ -391,6 +498,7 @@ local function asmlyze(first) end end +-- formats instruction to be ready for opcode generation local function instvaluate(inst) local regmap = { ["al"] = "000", ["ah"] = "100", ["bl"] = "011", ["bh"] = "111", @@ -420,6 +528,13 @@ local function instvaluate(inst) ret.modrm = bitval("0b11" .. "000" .. dstmap) return ret + -- mod byte is ... + -- 00 memory no displacement + -- 01 memory 8 bit displacement + -- 10 memory 32 bit displacement + -- 11 register to register + elseif inst.details[1] == ASM_MEM8 and inst.details[2] == ASM_R8 then + return ret end end @@ -438,9 +553,9 @@ local function writemov(inst, eval) writeu8(dst, eval.modrm) elseif inst.details[1] == ASM_R8 and inst.details[2] == ASM_IMM8 then local ib = 0 - if inst.operands[2].type == tk_type.hexadecimal then + if inst.operands[2].type == tk_type["hexadecimal"] then ib = hexval(inst.operands[2].raw) - elseif inst.operands[2].type == tk_type.integer then + elseif inst.operands[2].type == tk_type["integer"] then ib = intval(inst.operands[2].raw) else perror("attempt to mov a non integer at line " .. inst.operands[2].line) @@ -481,6 +596,8 @@ while true do elseif inst.details[1] == ASM_R8 and inst.details[2] == ASM_IMM8 then offset = offset + 2 + elseif inst.details[1] == ASM_MEM8 and inst.details[2] == ASM_R8 then + offset = offset -- To change later -- huh? else perror("invalid instruction at line " .. hdr.line) blob - 520f91818c130587e79bd18473207a8f1a9b13b7 blob + 6d39970a0aa2f1314e3971c97ecf869d5bff94ec --- tools/boot.sc +++ tools/boot.sc @@ -1,9 +1,4 @@ asm { _start: - mov al, ah - mov ah, 0hff - ret -main: hlt - cli } blob - 71f6edaaccf35a7ecad23def99747b4524d30cd9 blob + 73c6a396f089b292270ae57e9209b940ccaa8b91 --- tools/compiler.lua +++ tools/compiler.lua @@ -128,9 +128,9 @@ while true do end if ishex == true then - emittoken(nline, ncol, tk_type.hexadecimal, #data, data) + emittoken(nline, ncol, tk_type["hexadecimal"], #data, data) else - emittoken(nline, ncol, tk_type.integer, #data, data) + emittoken(nline, ncol, tk_type["integer"], #data, data) end i = i + #data elseif char == " " or char == "\t" then blob - fad84b294e1de4a24ef667ced168e53218a52de1 blob + 88127113ea6e94d8819871d58c5f49c92ed74cda --- tools/linker.lua +++ tools/linker.lua @@ -52,6 +52,26 @@ local function readhdr() return { line = line, col = col, type = type, len = len, raw = raw } end +local function typematch(token, array) + local len = #array + + for i = 1, len do + if type(array[i]) == "table" then + local match = typematch(token, array[i]) + if match == true then + return match + end + elseif type(array[i]) == "string" then + if token.type == tk_type[array[i]] then + return true + end + else + perror("illegal typematch must be array or string") + end + end + return false +end + -- This functions reads an asm line and tells if its a label or instructions -- If the return type is instructions, it will tell if its imm8, r8, etc -- @@ -69,7 +89,7 @@ local function operlyze(op, ret) ret.opcount = 1 table.insert(ret.details, ASM_R8) table.insert(ret.operands, op) - elseif op.type == tk_type.integer then + elseif op.type == tk_type["integer"] then ret.opcount = 1 local val = intval(op.raw) table.insert(ret.operands, op) @@ -79,7 +99,7 @@ local function operlyze(op, ret) else perror("operand 1 of instruction on line " .. op.line .. " is too big!") end - elseif op.type == tk_type.hexadecimal then + elseif op.type == tk_type["hexadecimal"] then ret.opcount = 1 local val = hexval(op.raw) table.insert(ret.operands, op) @@ -90,6 +110,68 @@ local function operlyze(op, ret) else perror("operand 1 of instruction on line " .. op.line .. " is too big!") end + + -- You can have max 1 segment registers and 2 GPR. For clarity + -- fs:rbx + rcx counts as 1 segment and 2 GPR + -- the displacement is capped to 32-bit signed + -- No paranthesis allowed for now + -- You cannot multiply the base reg (not allowed according to manual) + -- You can only multiply index reg by a factor of 2 up to max value 8 (1, 2, 4, 8) + elseif op.type == tk_type["["] then + local brackets = { opened = 0, closed = 0 } + + while true do + local pre = op + op = readhdr() + + if op.type == tk_type["\n"] or op.type == tk_type["]"] then + break + end + + if op.type == tk_type["["] then + perror("illegal nested operand at line " .. op.line) + end + + if isregs8(op) == true then + if typematch(pre, { "[", arithmetics }) == false then + perror("missing arithmetic prefix for register " .. gettokenkey(op) .. + " line " .. op.line) + end + + if #ret.memblock.regs == 0 and typematch(pre, { "+", "-" }) == false then + perror("Base register `" .. gettokenkey(op) .. + "` can only be applied + or - on it line " .. op.line) + elseif #ret.memblock.regs == 1 and typematch(pre, { "+", "-", "*" }) == false then + perror("Index register `" .. gettokenkey(op) .. + "` can only be applied +, - or * on it line " .. op.line) + end + table.insert(ret.memblock.regs, gettokenkey(op)) + + elseif typematch(op, { "hexadecimal", "integer" }) then + if typematch(pre, { "[", arithmetics }) == false then + perror("missing arithmetic/paranthesis prefix for whole number " .. op.raw .. + " line " .. op.line) + end + -- Other arithmetic symbols + elseif isarithmetic(op) == true then + if typematch(pre, { regs8, "hexadecimal", "integer" }) == false then + perror("illegal token before " .. gettokenkey(op) .. " at line " .. op.line) + end + else + perror("illegal token " .. gettokenkey(op) .. " at line " .. op.line) + end + + if #ret.memblock.regs > 2 then + perror("a maximum of 2 GPRs are allowed in memory block. Line " .. op.line) + end + end + + if op.type ~= tk_type["]"] then + perror("Missing closing `]` at line " .. op.line) + end + + table.insert(ret.details, ASM_MEM8) + ret.opcount = 1 elseif op.type == tk_type["\n"] then ret.opcount = 0 else @@ -103,7 +185,12 @@ local function asmlyze(first) type = ASM_INSTRUCTION, opcount = 0, details = { }, - operands = { } + operands = { }, + memblock = { + regs = { }, + dispsize = 0, + blevel = 0, + } } local op1 = readhdr() @@ -184,6 +271,13 @@ local function instvaluate(inst) ret.modrm = bitval("0b11" .. "000" .. dstmap) return ret + -- mod byte is ... + -- 00 memory no displacement + -- 01 memory 8 bit displacement + -- 10 memory 32 bit displacement + -- 11 register to register + elseif inst.details[1] == ASM_MEM8 and inst.details[2] == ASM_R8 then + return ret end end @@ -202,9 +296,9 @@ local function writemov(inst, eval) writeu8(dst, eval.modrm) elseif inst.details[1] == ASM_R8 and inst.details[2] == ASM_IMM8 then local ib = 0 - if inst.operands[2].type == tk_type.hexadecimal then + if inst.operands[2].type == tk_type["hexadecimal"] then ib = hexval(inst.operands[2].raw) - elseif inst.operands[2].type == tk_type.integer then + elseif inst.operands[2].type == tk_type["integer"] then ib = intval(inst.operands[2].raw) else perror("attempt to mov a non integer at line " .. inst.operands[2].line) @@ -245,6 +339,8 @@ while true do elseif inst.details[1] == ASM_R8 and inst.details[2] == ASM_IMM8 then offset = offset + 2 + elseif inst.details[1] == ASM_MEM8 and inst.details[2] == ASM_R8 then + offset = offset -- To change later -- huh? else perror("invalid instruction at line " .. hdr.line) blob - bc25e9dd9309e97d87e1e27f7aad8fb16c655a3b blob + ae98f98922a5a8d6611cabb8da4d82c4cefa68c7 --- tools/util.lua +++ tools/util.lua @@ -3,6 +3,9 @@ ----------------------------------------------------------------------- local mnemonics = { "mov", "cli", "hlt", "ret", "sti" } +-- This is kinda a double definition but fix later :^) +local arithmetics = { "+", "-", "*", "/", "^", "~", "|", "&" } + local symbols = { ",", "[", "]", "(", ")", "{", "}", "*", "/", "-", "+", "!", "~", "#", "?", ";", ":" } @@ -10,6 +13,8 @@ local regs8 = { "al", "ah", "bl", "bh", "cl", "ch", "d local asmkwd = { "asm" } +local tk_misc = { "hexadecimal", "integer", "id", "\n" } + local tk_type = { } local count = 0 @@ -33,14 +38,14 @@ for i = 1, #asmkwd do tk_type[asmkwd[i]] = count end +for i = 1, #tk_misc do + count = count + 1 + tk_type[tk_misc[i]] = count +end local function cincadd() count = count + 1 return count end -tk_type.hexadecimal = cincadd() -tk_type.integer = cincadd() -tk_type.id = cincadd() -tk_type["\n"] = cincadd() ----------------------------------------------------------------------- -- DEBUGING @@ -108,6 +113,21 @@ local function isregs8(m) return false end +local function isarithmetic(a) + local key = gettokenkey(a) + + if key == nil then + return false + end + + for i,v in ipairs(arithmetics) do + if v == key then + return true + end + end + return false +end + ----------------------------------------------------------------------- -- BITWISE OPERATIONS ----------------------------------------------------------------------- blob - /dev/null blob + 11a8f0777e691090b3163b0fc7ca37721f2d413b (mode 755) --- /dev/null +++ tools/mbrsign @@ -0,0 +1,57 @@ +#!/usr/local/bin/lua51 + +----------------------------------------------------------------------- +-- Checking arguments +----------------------------------------------------------------------- + +progname = "mbrsign" + +if arg[1] == nil then + print("usage: " .. progname .. " file") + os.exit(1) +end + +local function perror(msg) + print(progname .. ": " .. msg) + os.exit(1) +end + +local file = io.open(arg[1], "rb") + +if file == nil then + perror("failed to open file " .. arg[1]) +end + + +----------------------------------------------------------------------- +-- Check file size +----------------------------------------------------------------------- +local size = file:seek("end") + +if size > 512 then + perror("boot file " .. arg[1] .. " size is more than 512 bytes : " .. size .. " bytes") +end + +file:close() + +----------------------------------------------------------------------- +-- Filling 0s +----------------------------------------------------------------------- +file = io.open(arg[1], "r+") + +if file == nil then + perror("faile to open file " .. arg[1] .. " for writting") +end + +if size < 512 then + file:seek("set", size) + for i = size, 509 do + file:write(string.char(0)) + end +end + +file:seek("set", 510) +file:write(string.char("0x55")) +file:write(string.char("0xaa")) + +file:close()