commit a778d9116e59ca832d2d6d3b8bef32ee651e2513
parent f4a0d8c56a8575971c7ef12fa790c497f770495b
Author: erai <erai@omiltem.net>
Date: Mon, 25 Mar 2024 13:35:58 -0400
add multiboot header
Diffstat:
M | as.c | | | 97 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------- |
M | cc0.c | | | 78 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ |
M | cc1.c | | | 15 | ++++++++++++--- |
3 files changed, 170 insertions(+), 20 deletions(-)
diff --git a/as.c b/as.c
@@ -39,16 +39,24 @@ enum {
enum {
OP_NOP = 0x90,
+
OP_RET = 0xc3,
OP_CALL = 0xe8,
OP_JMP = 0xe9,
OP_JCC = 0x0f80,
OP_SETCC = 0x0f90,
- OP_ICALLM = 0x02ff,
+ OP_PUSHF = 0x9c,
+ OP_IRET = 0xcf,
+ OP_IRETQ = 0x48cf,
+ OP_WRMSR = 0x0f30,
+ OP_WRCRM = 0x0f20,
+ OP_LGDTM = 0x020f01,
+
+ OP_ICALLM = 0x0200ff,
- OP_NOTM = 0x02f7,
- OP_NEGM = 0x03f7,
+ OP_NOTM = 0x0200f7,
+ OP_NEGM = 0x0300f7,
OP_ANDRM = 0x23,
OP_ORRM = 0x0b,
@@ -60,10 +68,10 @@ enum {
OP_ADDI = 0x0081,
- OP_IMULM = 0x04f7,
- OP_IDIVM = 0x07f7,
- OP_SHLM = 0x04d3,
- OP_SHRM = 0x05d3,
+ OP_IMULM = 0x0400f7,
+ OP_IDIVM = 0x0700f7,
+ OP_SHLM = 0x0400d3,
+ OP_SHRM = 0x0500d3,
OP_PUSHR = 0x50,
@@ -536,12 +544,18 @@ emit_syscall(c: *assembler) {
as_opr(c, OP_PUSHR, R_RAX);
}
-writeout(c: *assembler, start: *label) {
+writeout(c: *assembler, start: *label, kstart: *label) {
var b: *chunk;
var i: int;
var text_size: int;
+ var text_end: int;
var load_addr: int;
var entry: int;
+ var kentry: int;
+ var mb_magic: int;
+ var mb_flags: int;
+ var mb_checksum: int;
+ var mb_addr: int;
if (!c.out) {
open_output(c, "a.out");
@@ -554,8 +568,21 @@ writeout(c: *assembler, start: *label) {
die("_start is not defined");
}
- entry = load_addr + start.at + 128;
- text_size = text_size + 128;
+ entry = load_addr + start.at + 128 + 32;
+ text_size = text_size + 128 + 32;
+ text_end = load_addr + text_size;
+
+ mb_magic = 0x1badb002;
+ mb_flags = 0x00010003;
+ mb_checksum = -(mb_magic + mb_flags);
+ mb_addr = load_addr + 120;
+
+ if (kstart && kstart.fixed) {
+ kentry = load_addr + kstart.at + 128 + 32;
+ } else {
+ mb_magic = 0;
+ kentry = 0;
+ }
// magic
putchar(c, 0x7f);
@@ -733,6 +760,54 @@ writeout(c: *assembler, start: *label) {
putchar(c, 0);
putchar(c, 0);
+ // multiboot magic
+ putchar(c, mb_magic);
+ putchar(c, mb_magic >> 8);
+ putchar(c, mb_magic >> 16);
+ putchar(c, mb_magic >> 24);
+
+ // multiboot flags
+ putchar(c, mb_flags);
+ putchar(c, mb_flags >> 8);
+ putchar(c, mb_flags >> 16);
+ putchar(c, mb_flags >> 24);
+
+ // multboot checksum
+ putchar(c, mb_checksum);
+ putchar(c, mb_checksum >> 8);
+ putchar(c, mb_checksum >> 16);
+ putchar(c, mb_checksum >> 24);
+
+ // multiboot header_addr
+ putchar(c, mb_addr);
+ putchar(c, mb_addr >> 8);
+ putchar(c, mb_addr >> 16);
+ putchar(c, mb_addr >> 24);
+
+ // multiboot load_addr
+ putchar(c, load_addr);
+ putchar(c, load_addr >> 8);
+ putchar(c, load_addr >> 16);
+ putchar(c, load_addr >> 24);
+
+ // multiboot load_end_addr
+ putchar(c, text_end);
+ putchar(c, text_end >> 8);
+ putchar(c, text_end >> 16);
+ putchar(c, text_end >> 24);
+
+ // multiboot bss_end_addr
+ putchar(c, 0);
+ putchar(c, 0);
+ putchar(c, 0);
+ putchar(c, 0);
+
+ // entry_addr
+ putchar(c, kentry);
+ putchar(c, kentry >> 8);
+ putchar(c, kentry >> 16);
+ putchar(c, kentry >> 24);
+
// nop sled
putchar(c, OP_NOP);
putchar(c, OP_NOP);
@@ -822,7 +897,7 @@ as_modrr(a: *assembler, op: int, r: int, b: int) {
// modrm /op
as_modr(a: *assembler, op: int, b: int) {
- as_modrr(a, op & 0xff, op >> 8, b);
+ as_modrr(a, op & 0xffff, op >> 16, b);
}
// modrm + sib + disp
diff --git a/cc0.c b/cc0.c
@@ -4137,14 +4137,36 @@ writeout(void)
int entry;
struct decl *d;
struct buf *b;
-
- load_addr = 0x100000;
+ int kentry;
+ int magic;
+ int flags;
+ int checksum;
+ int addr;
+ int end;
d = find((unsigned char *)"_start");
if (!d->defined || !d->label->fixed) {
die("no _start function");
}
+ load_addr = 0x100000;
+ entry = load_addr + d->label->at + 128 + 32;
+ at = at + 128 + 32;
+ end = load_addr + at;
+
+ magic = 0x1badb002;
+ flags = 0x00010003;
+ checksum = -(magic + flags);
+ addr = load_addr + 120;
+
+ d = find((unsigned char *)"_kstart");
+ if (d->defined && d->label->fixed) {
+ kentry = load_addr + d->label->at +128 + 32;
+ } else {
+ magic = 0;
+ kentry = 0;
+ }
+
// magic
fputc(0x7f, fout);
fputc('E', fout);
@@ -4189,8 +4211,6 @@ writeout(void)
fputc(0, fout);
fputc(0, fout);
- entry = load_addr + d->label->at + 128;
-
// entry point
fputc(entry, fout);
fputc(entry >> 8, fout);
@@ -4293,8 +4313,6 @@ writeout(void)
fputc(0, fout);
fputc(0, fout);
- at = at + 128;
-
// phdr[0].filesize
fputc(at, fout);
fputc(at >> 8, fout);
@@ -4325,6 +4343,54 @@ writeout(void)
fputc(0, fout);
fputc(0, fout);
+ // mb.magic
+ fputc(magic, fout);
+ fputc(magic >> 8, fout);
+ fputc(magic >> 16, fout);
+ fputc(magic >> 24, fout);
+
+ // mb.flags
+ fputc(flags, fout);
+ fputc(flags >> 8, fout);
+ fputc(flags >> 16, fout);
+ fputc(flags >> 24, fout);
+
+ // mb.checksum
+ fputc(checksum, fout);
+ fputc(checksum >> 8, fout);
+ fputc(checksum >> 16, fout);
+ fputc(checksum >> 24, fout);
+
+ // mb.header
+ fputc(addr, fout);
+ fputc(addr >> 8, fout);
+ fputc(addr >> 16, fout);
+ fputc(addr >> 24, fout);
+
+ // mb.load
+ fputc(load_addr, fout);
+ fputc(load_addr >> 8, fout);
+ fputc(load_addr >> 16, fout);
+ fputc(load_addr >> 24, fout);
+
+ // mb.load_end
+ fputc(end, fout);
+ fputc(end >> 8, fout);
+ fputc(end >> 16, fout);
+ fputc(end >> 24, fout);
+
+ // mb.bss_end
+ fputc(0, fout);
+ fputc(0, fout);
+ fputc(0, fout);
+ fputc(0, fout);
+
+ // mb.entry
+ fputc(kentry, fout);
+ fputc(kentry >> 8, fout);
+ fputc(kentry >> 16, fout);
+ fputc(kentry >> 24, fout);
+
// nop sled
fputc(0x90, fout);
fputc(0x90, fout);
diff --git a/cc1.c b/cc1.c
@@ -1274,6 +1274,8 @@ main(argc: int, argv: **byte, envp: **byte) {
var c: *compiler;
var p: *node;
var d: *decl;
+ var start: *label;
+ var kstart: *label;
var i: int;
setup_alloc(&a);
@@ -1327,10 +1329,17 @@ main(argc: int, argv: **byte, envp: **byte) {
emit_ret(c.as);
}
+ start = 0: *label;
d = find(c, "_start", 0:*byte, 0);
- if (!d || !d.func_defined) {
- die("no _start");
+ if (d && d.func_defined) {
+ start = d.func_label;
}
- writeout(c.as, d.func_label);
+ kstart = 0: *label;
+ d = find(c, "_kstart", 0:*byte, 0);
+ if (d && d.func_defined) {
+ kstart = d.func_label;
+ }
+
+ writeout(c.as, start, kstart);
}