commit 26477129cfe7ccef1bfb485f8ee107b557c9f9fa from: Onana Onana Xavier Manuel date: Sun Sep 27 20:08:41 2026 UTC Fixed endianness and added support for call rel16 commit - cc1b538ae080ea83a96421aa59d0fa35078f44a2 commit + 26477129cfe7ccef1bfb485f8ee107b557c9f9fa blob - c115f66915a6581fd4af49849b22d0dcb8fdc0ea blob + 382df3706cb70a0adeab9a245c2fadc3bfe38831 --- tools/6c +++ tools/6c @@ -3,7 +3,7 @@ ----------------------------------------------------------------------- -- TOKEN MATCHING ----------------------------------------------------------------------- -local mnemonics = { "mov", "cli", "hlt", "ret", "sti", "int" } +local mnemonics = { "mov", "cli", "hlt", "ret", "sti", "int", "call" } -- This is kinda a double definition but fix later :^) local arithmetics = { "+", "-", "*", "/", "^", "~", "|", "&" } @@ -50,6 +50,12 @@ local function cincadd() end ----------------------------------------------------------------------- +-- CONSTANTS +----------------------------------------------------------------------- +local MAX_S16 = 2^16-1 +local MIN_S16 = -2^16 + +----------------------------------------------------------------------- -- DEBUGING ----------------------------------------------------------------------- local function perror(msg) @@ -189,7 +195,7 @@ local function writeu16(dst, value) local b2 = band(brshift(value, 8), 0xff) local b1 = band(value, 0xff) - dst:write(string.char(b2, b1)) -- Little Endian x86 + dst:write(string.char(b1, b2)) -- Little Endian x86 end local function writeu32(dst, value) @@ -198,7 +204,7 @@ local function writeu32(dst, value) local b2 = band(brshift(value, 8), 0xff) local b1 = band(value, 0xff) - dst:write(string.char(b4, b3, b2, b1)) -- Little Endian x86 + dst:write(string.char(b1, b2, b3, b4)) -- Little Endian x86 end @@ -379,6 +385,7 @@ ast.genast = function(expr) i = i + 1 end end + return expr[1] end @@ -401,7 +408,11 @@ ast.eval = function(node) local con = 0 for _, term in ipairs(leftval) do - table.insert(result, term) + if type(term) == "table" then + table.insert(result, term) + else + con = con + term + end end for _, term in ipairs(rightval) do blob - 3ea7054e411f2f3630fcdc2c110483cf51399ce4 blob + 04a04989c870c5a0d8575f4f57bcc28f19e0bf48 --- tools/6l +++ tools/6l @@ -3,7 +3,7 @@ ----------------------------------------------------------------------- -- TOKEN MATCHING ----------------------------------------------------------------------- -local mnemonics = { "mov", "cli", "hlt", "ret", "sti", "int" } +local mnemonics = { "mov", "cli", "hlt", "ret", "sti", "int", "call" } -- This is kinda a double definition but fix later :^) local arithmetics = { "+", "-", "*", "/", "^", "~", "|", "&" } @@ -50,6 +50,12 @@ local function cincadd() end ----------------------------------------------------------------------- +-- CONSTANTS +----------------------------------------------------------------------- +local MAX_S16 = 2^16-1 +local MIN_S16 = -2^16 + +----------------------------------------------------------------------- -- DEBUGING ----------------------------------------------------------------------- local function perror(msg) @@ -189,7 +195,7 @@ local function writeu16(dst, value) local b2 = band(brshift(value, 8), 0xff) local b1 = band(value, 0xff) - dst:write(string.char(b2, b1)) -- Little Endian x86 + dst:write(string.char(b1, b2)) -- Little Endian x86 end local function writeu32(dst, value) @@ -198,7 +204,7 @@ local function writeu32(dst, value) local b2 = band(brshift(value, 8), 0xff) local b1 = band(value, 0xff) - dst:write(string.char(b4, b3, b2, b1)) -- Little Endian x86 + dst:write(string.char(b1, b2, b3, b4)) -- Little Endian x86 end @@ -379,6 +385,7 @@ ast.genast = function(expr) i = i + 1 end end + return expr[1] end @@ -401,7 +408,11 @@ ast.eval = function(node) local con = 0 for _, term in ipairs(leftval) do - table.insert(result, term) + if type(term) == "table" then + table.insert(result, term) + else + con = con + term + end end for _, term in ipairs(rightval) do @@ -485,10 +496,10 @@ local function readhdr() local b = { string.byte((hdr), 1, 12) } - local line = b[4] + blshift(b[3], 8) + blshift(b[2], 16) + blshift(b[1], 24) - local col = b[8] + blshift(b[7], 8) + blshift(b[6], 16) + blshift(b[5], 24) - local type = b[10] + blshift(b[9], 8) - local len = b[12] + blshift(b[11], 8) + local line = b[1] + blshift(b[2], 8) + blshift(b[3], 16) + blshift(b[4], 24) + local col = b[5] + blshift(b[6], 8) + blshift(b[7], 16) + blshift(b[8], 24) + local type = b[9] + blshift(b[10], 8) + local len = b[11] + blshift(b[12], 8) local raw = nil if len > 0 then raw = src:read(len) end @@ -650,27 +661,16 @@ local function operlyze(op, ret) local gen = ast.genast(expr) local exp = ast.eval(gen) - for _, v in ipairs(exp) do - if type(v) == "table" then - io.write("{") - io.write(v[1]) - io.write(", ") - io.write(v[2]) - io.write("} ") - else - io.write(tonumber(v)) - end - end - - io.write("\n") - io.write("\n") - - ret.memblock.expression = e + ret.memblock.expression = exp table.insert(ret.details, ASM_MEM8) ret.opcount = 1 elseif op.type == tk_type["\n"] then ret.opcount = 0 + elseif op.type == tk_type["id"] then + table.insert(ret.details, ASM_LABEL) + table.insert(ret.operands, op) + ret.opcount = 0 else perror("unknown operand `" .. gettokenkey(op) .. "` at line " .. op.line) end @@ -687,8 +687,8 @@ local function asmlyze(first) regs = { }, dispsize = 0, blevel = 0, - expression = nil - } + expression = { } + }, } local op1 = readhdr() @@ -782,15 +782,54 @@ local function instvaluate(inst) local reg2 = nil local dstmap = "000" local srcmap = "000" + local displacement = 0 for i = 1, #inst.memblock.regs do if reg1 == nil then reg1 = inst.memblock.regs[i] - elseif reg2 == nil then - reg2 = inst.memblock.regs[i] end end + if reg1 ~= nil then dstmap = regmap[reg1] end + srcmap = regmap[gettokenkey(inst.operands[1])] + + if reg2 ~= nil then + for i = 1,#inst.memblock.expression do + local entry = inst.memblock.expression[i] + + if type(entry) == "table" and entry[1] == reg2 then + local scale = tonumber(entry[2]) + if scale ~= 1 and scale ~= 2 and scale ~= 4 and scale ~= 8 then + perror("Scale for index register can be 1, 2, 4 or 8") + end + + ret.sib = scale + break + end + end + end + + for i = 1, #inst.memblock.expression do + local offset = tonumber(inst.memblock.expression[i]) + + if offset ~= nil then + displacement = offset + + if reg1 == nil and reg2 == nil then + dstmap = "110" + end + break + end + end + + if reg1 ~= nil or reg2 ~= nil then + if displacement > 127 or displacement < -128 then + perror("displacement is only allowed to between -128 and 127") + end + end + + ret.modrm = bitval("0b" .. mod .. srcmap .. dstmap) + return ret end end @@ -821,9 +860,69 @@ local function writemov(inst, eval) writeu8(dst, hexval("0hC6")) writeu8(dst, eval.modrm) writeu8(dst, ib) + + elseif inst.details[1] == ASM_MEM8 and inst.details[2] == ASM_R8 then + if #inst.memblock.regs > 0 then + perror("illegal, registers are not allowed in memory access for now. Line " .. inst.operands[2].line) + else + local addr = inst.memblock.expression[1] + writeu8(dst, hexval("0h88")) + writeu8(dst, eval.modrm) + + if addr <= 32767 then + writeu16(dst, addr) + else + writeu32(dst, addr) + end + end end end +local function writecall(inst, curr) + local opcount = #inst.details + if opcount ~= 1 then + perror("call takes 1 operand " .. inst.operands[1].line) + end + + -- ONCE AGAIN WE ASSUME THIS IS REAL MODE + if inst.details[1] == ASM_LABEL then + local addr = symbol_table[inst.operands[1].raw] + writeu8(dst, hexval("0hE8")) + writeu16(dst, addr - curr) + end +end + +local function get_instruction_size(hdr, inst) + if hdr.type == tk_type["mov"] then + local size = 2 + local eval = instvaluate(inst) + if eval.modrm ~= nil then size = size + 1 end + + -- Check expression for memory constants + if inst.memblock and inst.memblock.expression then + for _, v in ipairs(inst.memblock.expression) do + local num = tonumber(v) + if num ~= nil then + if num <= MAX_S16 and num >= MIN_S16 then + size = size + 2 + else + size = size + 4 + end + end + end + end + return size + 1 -- Plus your trailing byte modifier + + elseif hdr.type == tk_type["hlt"] or hdr.type == tk_type["ret"] or hdr.type == tk_type["cli"] then + return 1 + elseif hdr.type == tk_type["int"] then + return 2 + elseif hdr.type == tk_type["call"] or hdr.type == tk_type["jmp"] then + return 3 -- WE ASSUME ITS REAL MODE!!! + end + return 0 +end + ----------------------------------------------------------------------- -- 1st pass (syntax check and symbol table) ----------------------------------------------------------------------- @@ -844,22 +943,7 @@ while true do local inst = asmlyze(hdr) if inst.type == ASM_INSTRUCTION then - if hdr.type == tk_type["mov"] then - -- mov r8, r8 - if inst.details[1] == ASM_R8 and inst.details[2] == ASM_R8 then - offset = offset + 2 - - -- mov r8, imm8 - 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) - end - end + offset = offset + get_instruction_size(hdr, inst) -- Add symbol table elseif inst.type == ASM_LABEL then symbol_table[hdr.raw] = offset @@ -886,6 +970,8 @@ src:seek("set", begin) parser.inasm = false parser.insec = false +local coffset = 0 + while true do local hdr = readhdr() if hdr == nil then @@ -902,6 +988,7 @@ while true do local inst = asmlyze(hdr) if inst.type == ASM_INSTRUCTION then local eval = instvaluate(inst) + coffset = coffset + get_instruction_size(hdr, inst) if eval == nil then perror("unknown instruction at line " .. hdr.line) @@ -937,6 +1024,8 @@ while true do elseif inst.operands[1].type == tk_type["integer"] then writeu8(dst, intval(inst.operands[1].raw)) end + elseif hdr.type == tk_type["call"] then + writecall(inst, coffset) end end end blob - fb5ebec9b76df12de540c6dba0bef4bca2d5dc53 blob + b5e6dcbb21ab9e6ad6c2c3d81931e9250b2dd73d --- tools/boot.sc +++ tools/boot.sc @@ -3,6 +3,13 @@ _start: mov ah, 0h0e mov al, 0h61 int 0h10 - mov [ ((al)) + (bl * 100) * 4 + 0h100 ], bl + call me + mov [ 0h100 + 300], bl hlt + +me: + mov ah, 0h0e + mov al, 0h61 + int 0h10 + ret } blob - 8d86957439a3fd2605f9b14d39de96c8bc135663 blob + 0fdab57d6e3d4e1ff757a04a8e37754252a4ff66 --- tools/linker.lua +++ tools/linker.lua @@ -42,10 +42,10 @@ local function readhdr() local b = { string.byte((hdr), 1, 12) } - local line = b[4] + blshift(b[3], 8) + blshift(b[2], 16) + blshift(b[1], 24) - local col = b[8] + blshift(b[7], 8) + blshift(b[6], 16) + blshift(b[5], 24) - local type = b[10] + blshift(b[9], 8) - local len = b[12] + blshift(b[11], 8) + local line = b[1] + blshift(b[2], 8) + blshift(b[3], 16) + blshift(b[4], 24) + local col = b[5] + blshift(b[6], 8) + blshift(b[7], 16) + blshift(b[8], 24) + local type = b[9] + blshift(b[10], 8) + local len = b[11] + blshift(b[12], 8) local raw = nil if len > 0 then raw = src:read(len) end @@ -207,27 +207,16 @@ local function operlyze(op, ret) local gen = ast.genast(expr) local exp = ast.eval(gen) - for _, v in ipairs(exp) do - if type(v) == "table" then - io.write("{") - io.write(v[1]) - io.write(", ") - io.write(v[2]) - io.write("} ") - else - io.write(tonumber(v)) - end - end - - io.write("\n") - io.write("\n") - - ret.memblock.expression = e + ret.memblock.expression = exp table.insert(ret.details, ASM_MEM8) ret.opcount = 1 elseif op.type == tk_type["\n"] then ret.opcount = 0 + elseif op.type == tk_type["id"] then + table.insert(ret.details, ASM_LABEL) + table.insert(ret.operands, op) + ret.opcount = 0 else perror("unknown operand `" .. gettokenkey(op) .. "` at line " .. op.line) end @@ -244,8 +233,8 @@ local function asmlyze(first) regs = { }, dispsize = 0, blevel = 0, - expression = nil - } + expression = { } + }, } local op1 = readhdr() @@ -339,15 +328,54 @@ local function instvaluate(inst) local reg2 = nil local dstmap = "000" local srcmap = "000" + local displacement = 0 for i = 1, #inst.memblock.regs do if reg1 == nil then reg1 = inst.memblock.regs[i] - elseif reg2 == nil then - reg2 = inst.memblock.regs[i] end end + if reg1 ~= nil then dstmap = regmap[reg1] end + srcmap = regmap[gettokenkey(inst.operands[1])] + + if reg2 ~= nil then + for i = 1,#inst.memblock.expression do + local entry = inst.memblock.expression[i] + + if type(entry) == "table" and entry[1] == reg2 then + local scale = tonumber(entry[2]) + if scale ~= 1 and scale ~= 2 and scale ~= 4 and scale ~= 8 then + perror("Scale for index register can be 1, 2, 4 or 8") + end + + ret.sib = scale + break + end + end + end + + for i = 1, #inst.memblock.expression do + local offset = tonumber(inst.memblock.expression[i]) + + if offset ~= nil then + displacement = offset + + if reg1 == nil and reg2 == nil then + dstmap = "110" + end + break + end + end + + if reg1 ~= nil or reg2 ~= nil then + if displacement > 127 or displacement < -128 then + perror("displacement is only allowed to between -128 and 127") + end + end + + ret.modrm = bitval("0b" .. mod .. srcmap .. dstmap) + return ret end end @@ -378,9 +406,69 @@ local function writemov(inst, eval) writeu8(dst, hexval("0hC6")) writeu8(dst, eval.modrm) writeu8(dst, ib) + + elseif inst.details[1] == ASM_MEM8 and inst.details[2] == ASM_R8 then + if #inst.memblock.regs > 0 then + perror("illegal, registers are not allowed in memory access for now. Line " .. inst.operands[2].line) + else + local addr = inst.memblock.expression[1] + writeu8(dst, hexval("0h88")) + writeu8(dst, eval.modrm) + + if addr <= 32767 then + writeu16(dst, addr) + else + writeu32(dst, addr) + end + end end end +local function writecall(inst, curr) + local opcount = #inst.details + if opcount ~= 1 then + perror("call takes 1 operand " .. inst.operands[1].line) + end + + -- ONCE AGAIN WE ASSUME THIS IS REAL MODE + if inst.details[1] == ASM_LABEL then + local addr = symbol_table[inst.operands[1].raw] + writeu8(dst, hexval("0hE8")) + writeu16(dst, addr - curr) + end +end + +local function get_instruction_size(hdr, inst) + if hdr.type == tk_type["mov"] then + local size = 2 + local eval = instvaluate(inst) + if eval.modrm ~= nil then size = size + 1 end + + -- Check expression for memory constants + if inst.memblock and inst.memblock.expression then + for _, v in ipairs(inst.memblock.expression) do + local num = tonumber(v) + if num ~= nil then + if num <= MAX_S16 and num >= MIN_S16 then + size = size + 2 + else + size = size + 4 + end + end + end + end + return size + 1 -- Plus your trailing byte modifier + + elseif hdr.type == tk_type["hlt"] or hdr.type == tk_type["ret"] or hdr.type == tk_type["cli"] then + return 1 + elseif hdr.type == tk_type["int"] then + return 2 + elseif hdr.type == tk_type["call"] or hdr.type == tk_type["jmp"] then + return 3 -- WE ASSUME ITS REAL MODE!!! + end + return 0 +end + ----------------------------------------------------------------------- -- 1st pass (syntax check and symbol table) ----------------------------------------------------------------------- @@ -401,22 +489,7 @@ while true do local inst = asmlyze(hdr) if inst.type == ASM_INSTRUCTION then - if hdr.type == tk_type["mov"] then - -- mov r8, r8 - if inst.details[1] == ASM_R8 and inst.details[2] == ASM_R8 then - offset = offset + 2 - - -- mov r8, imm8 - 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) - end - end + offset = offset + get_instruction_size(hdr, inst) -- Add symbol table elseif inst.type == ASM_LABEL then symbol_table[hdr.raw] = offset @@ -443,6 +516,8 @@ src:seek("set", begin) parser.inasm = false parser.insec = false +local coffset = 0 + while true do local hdr = readhdr() if hdr == nil then @@ -459,6 +534,7 @@ while true do local inst = asmlyze(hdr) if inst.type == ASM_INSTRUCTION then local eval = instvaluate(inst) + coffset = coffset + get_instruction_size(hdr, inst) if eval == nil then perror("unknown instruction at line " .. hdr.line) @@ -494,6 +570,8 @@ while true do elseif inst.operands[1].type == tk_type["integer"] then writeu8(dst, intval(inst.operands[1].raw)) end + elseif hdr.type == tk_type["call"] then + writecall(inst, coffset) end end end blob - 118b7570602f441e01aed443d89312149213e293 blob + 8c0a97bff15a71cc55d2ef7d551a6fd5d1aa633a --- tools/util.lua +++ tools/util.lua @@ -1,7 +1,7 @@ ----------------------------------------------------------------------- -- TOKEN MATCHING ----------------------------------------------------------------------- -local mnemonics = { "mov", "cli", "hlt", "ret", "sti", "int" } +local mnemonics = { "mov", "cli", "hlt", "ret", "sti", "int", "call" } -- This is kinda a double definition but fix later :^) local arithmetics = { "+", "-", "*", "/", "^", "~", "|", "&" } @@ -48,6 +48,12 @@ local function cincadd() end ----------------------------------------------------------------------- +-- CONSTANTS +----------------------------------------------------------------------- +local MAX_S16 = 2^16-1 +local MIN_S16 = -2^16 + +----------------------------------------------------------------------- -- DEBUGING ----------------------------------------------------------------------- local function perror(msg) @@ -187,7 +193,7 @@ local function writeu16(dst, value) local b2 = band(brshift(value, 8), 0xff) local b1 = band(value, 0xff) - dst:write(string.char(b2, b1)) -- Little Endian x86 + dst:write(string.char(b1, b2)) -- Little Endian x86 end local function writeu32(dst, value) @@ -196,7 +202,7 @@ local function writeu32(dst, value) local b2 = band(brshift(value, 8), 0xff) local b1 = band(value, 0xff) - dst:write(string.char(b4, b3, b2, b1)) -- Little Endian x86 + dst:write(string.char(b1, b2, b3, b4)) -- Little Endian x86 end @@ -377,6 +383,7 @@ ast.genast = function(expr) i = i + 1 end end + return expr[1] end @@ -399,7 +406,11 @@ ast.eval = function(node) local con = 0 for _, term in ipairs(leftval) do - table.insert(result, term) + if type(term) == "table" then + table.insert(result, term) + else + con = con + term + end end for _, term in ipairs(rightval) do blob - /dev/null blob + 77dcb7dfc5944eca9f8a0559f1f72c0e8a9c0f4f (mode 755) --- /dev/null +++ tools/mkmbr @@ -0,0 +1,5 @@ +#!/bin/ksh + +set -e + +./6c boot.sc && ./6l boot.6 && ./mbrsign 6.boot