Commit Diff


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