From da77e08b8069d36b141e52cf351ddea2cdde8bbf Mon Sep 17 00:00:00 2001 From: Paul Mathieu Date: Fri, 3 Oct 2025 23:34:27 +0200 Subject: [PATCH] polmon: al int80, run args, ret code --- src/polmon.cc | 167 +++++++++++++++++++++++++++++--------------------- 1 file changed, 98 insertions(+), 69 deletions(-) diff --git a/src/polmon.cc b/src/polmon.cc index 1809a0d..1e6f55d 100644 --- a/src/polmon.cc +++ b/src/polmon.cc @@ -6,21 +6,20 @@ namespace { constexpr int kDumpSize = 16; -// arguments on the stack in reverse order -extern "C" uint16_t Int80h(uint8_t fun, int nargs); +extern "C" uint16_t Int80h(uint16_t fun, uint16_t nargs, uint16_t args[]); asm(".section .text.Int80h \n" "Int80h: \n" " push %si \n" " push %bp \n" - " mov %al, %ah \n" " mov %sp, %bp \n" - " lea 6(%bp), %si \n" // 4 for pushed stuff, 2 for return addr + " mov %cx, %si \n" + " shl $1, %dx \n" + " add %dx, %si \n" "0: \n" - " test %dx, %dx \n" - " jz 1f \n" - " push (%si) \n" - " dec %dx \n" - " add $2, %si \n" + " cmp %cx, %si \n" + " je 1f \n" + " push -2(%si) \n" + " sub $2, %si \n" " jmp 0b \n" "1: \n" " int $0x80 \n" @@ -42,21 +41,22 @@ uint8_t ReadHexNibble(uint8_t c) { return 10 + (c - 'a'); } -uint16_t ReadUintN(int n, const char* buf) { +uint16_t ReadUintN(int n, const char*& buf) { uint16_t out = 0; for (int i = 0; i < n; i++) { - if (buf[i] == 0) { + if (*buf < '0') { break; } out <<= 4; - out += ReadHexNibble(buf[i]); + out += ReadHexNibble(*buf); + buf += 1; } return out; } -uint8_t ReadUint8(const char* buf) { return ReadUintN(2, buf); } +uint8_t ReadUint8(const char*& buf) { return ReadUintN(2, buf); } -uint16_t ReadUint16(const char* buf) { return ReadUintN(4, buf); } +uint16_t ReadUint16(const char*& buf) { return ReadUintN(4, buf); } void WriteHexNibble(uint8_t c) { if (c > 9) { @@ -76,6 +76,11 @@ void WriteUint16(uint16_t a) { WriteUint8(a & 0xff); } +void WriteUint16ln(uint16_t a) { + WriteUint16(a); + puts("\r\n"); +} + uint8_t __get_far_u8__(uint16_t addr, uint16_t seg) { register uint16_t ad asm("si") = addr; register uint16_t sg asm("ds") = seg; @@ -126,8 +131,7 @@ void DumpHex(uint16_t addr, uint16_t seg) { putchar(']'); putchar(':'); Dump(addr, seg, kDumpSize); - putchar('\r'); - putchar('\n'); + puts("\r\n"); } void ClearScreen() { @@ -173,46 +177,72 @@ void tofatname(const char* name, char* fatname) { } } -void LaunchFile(const char* name) { +uint16_t __readfile__(const char* name, uint16_t addr) { + register uint16_t ret asm("ax"); + asm volatile( + "push %2 \n\t" + "push %1 \n\t" + "mov $04, %%ah \n\t" + "int $0x80 \n\t" + "pop %%cx \n\t" + "pop %%cx \n\t" + : "=r"(ret) + : "r"(name), "r"(addr) + : "bx", "cx", "dx", "memory", "cc"); + + return ret; +} + +uint16_t LaunchFile(const char* name, uint8_t argc, uint16_t* argv) { constexpr uint16_t kSegment = 0x200; constexpr uint16_t kAddress = 0x100; constexpr uint16_t kHeaderAddress = (kSegment << 4); constexpr uint16_t kFlatAddress = (kSegment << 4) + kAddress; + constexpr uint16_t kArgvAddress = 0x0004; + // trampoline: + // call 0x100 + // retf + // XXX: if you change kAddress, the trampoline needs to be updated constexpr uint8_t kTrampoline[] = { 0xe8, 0xfd, 0x00, 0xcb }; char fatname[11]; tofatname(name, fatname); + uint16_t r = __readfile__(fatname, kFlatAddress); + if (r) { + return r; + } + auto* ptr = reinterpret_cast(kHeaderAddress); memcpy(ptr, kTrampoline, sizeof(kTrampoline)); + auto* argp = reinterpret_cast(kHeaderAddress + kArgvAddress); + memcpy(argp, argv, argc * 2); - asm volatile("mov %1, %%ax \n\t" - "push %%ax \n\t" - "mov %0, %%ax \n\t" - "push %%ax \n\t" - "mov $04, %%ah \n\t" - "int $0x80 \n\t" - "add $4, %%sp \n\t" - "mov %2, %%ax \n\t" - "mov %%ax, %%ds \n\t" - "mov %%ax, %%es \n\t" + register uint16_t ac asm("ax") = argc; + register uint16_t av asm("dx") = kArgvAddress; + asm volatile( + "mov %2, %%cx \n\t" + "mov %%cx, %%ds \n\t" + "mov %%cx, %%es \n\t" "cli \n\t" - "mov %%ax, %%ss \n\t" - "mov %3, %%ax \n\t" - "xchg %%ax, %%sp \n\t" + "mov %%cx, %%ss \n\t" + "mov %3, %%cx \n\t" + "xchg %%cx, %%sp \n\t" "sti \n\t" - "push %%ax \n\t" + "push %%cx \n\t" "lcall %2,$0 \n\t" - "xor %%ax, %%ax \n\t" - "mov %%ax, %%ds \n\t" - "mov %%ax, %%es \n\t" + "xor %%cx, %%cx \n\t" + "mov %%cx, %%ds \n\t" + "mov %%cx, %%es \n\t" "cli \n\t" "pop %%sp \n\t" - "mov %%ax, %%ss \n\t" + "mov %%cx, %%ss \n\t" "sti" - :: "rmi"(fatname), - "rmi"(kFlatAddress), "i"(kSegment), "i"(kHeaderAddress) - : "ax", "bx", "cx", "dx", "memory"); + : "+r" (ac), "+r" (av) + : "i"(kSegment), "i"(kAddress) + : "bx", "cx", "memory", "cc"); + + return ac; } constexpr uint16_t kCtrlBreakVector = (0x1b * 4); @@ -221,9 +251,9 @@ extern "C" void cbreak(); asm(" .section .text.cbreak \n" "cbreak: \n" " xor %ax, %ax \n" - " mov %ds, %ax \n" + " mov %ax, %ds \n" " cli \n" - " mov %ss, %ax \n" + " mov %ax, %ds \n" " mov $0x2000, %sp \n" " sti \n" " pushf \n" @@ -245,8 +275,8 @@ bool ParseCommand(const char* buf, uint16_t& cur_addr, uint16_t& cur_seg) { for (const char* ptr = buf; *ptr;) { if (*ptr == 's') { cur_addr = 0; - cur_seg = ReadUint16(ptr + 1); - ptr += 5; + ptr += 1; + cur_seg = ReadUint16(ptr); } else if (*ptr == '$') { __basic__(); } else if (*ptr == 'j') { @@ -254,46 +284,46 @@ bool ParseCommand(const char* buf, uint16_t& cur_addr, uint16_t& cur_seg) { ptr++; auto jump = reinterpret_cast(cur_addr); uint16_t ret = jump(); - WriteUint16(ret); - putchar('\r'); - putchar('\n'); + WriteUint16ln(ret); } else if (*ptr == 'i') { dump = false; - int nargs = 0; + uint16_t args[8]; // ought to be enough for everybody + uint8_t nargs = 0; ptr++; - int fun = ReadUint8(ptr); - ptr += 2; - for (; *ptr;) { + int fun = ReadUint16(ptr); + for (; *ptr && nargs < 8;) { if (*ptr == ' ') { ptr++; continue; } - uint16_t d = ReadUint16(ptr); - asm volatile("push %0" ::"r"(d)); - nargs++; - ptr += 4; + args[nargs++] = ReadUint16(ptr); } - uint16_t ret = Int80h(fun, nargs); - asm volatile("shl %0 \n\t" - "add %0, %%sp" ::"r"(nargs)); - WriteUint16(ret); - putchar('\r'); - putchar('\n'); + uint16_t ret = Int80h(fun, nargs, args); + WriteUint16ln(ret); } else if (*ptr == 'l') { dump = false; ClearScreen(); ptr++; } else if (*ptr == 'r') { dump = false; + uint16_t args[8]; // ought to be enough for everybody + uint8_t nargs = 0; ptr++; while (*ptr == ' ') { ptr++; } - int l = 0; - for (; ptr[l]; l++) { + const char* fname = ptr; + for (; *ptr && *ptr != ' '; ptr++) { } - LaunchFile(ptr); - ptr += l; + for (; *ptr && nargs < 8;) { + if (*ptr == ' ') { + ptr++; + continue; + } + args[nargs++] = ReadUint16(ptr); + } + uint16_t ret = LaunchFile(fname, nargs, args); + WriteUint16ln(ret); } else if (*ptr == 'w') { dump = false; uint16_t addr = cur_addr; @@ -306,21 +336,19 @@ bool ParseCommand(const char* buf, uint16_t& cur_addr, uint16_t& cur_seg) { uint8_t d = ReadUint8(ptr); __set_far_u8__(addr, cur_seg, d); addr++; - ptr += 2; } } else { cur_addr = ReadUint16(ptr); - ptr += 4; } } return dump; } void DisplayPrompt() { - putchar('>'); - putchar(' '); + puts("> "); } +[[noreturn]] void polmon() { uint16_t cur_addr = 0; uint16_t cur_seg = 0; @@ -365,6 +393,7 @@ void polmon() { inptr++; } } + __builtin_unreachable(); } } // namespace @@ -374,7 +403,7 @@ int main() { polmon(); } -__attribute__((section(".init"), noreturn, used)) void _start() { +__attribute__((section(".init"), used)) +void _start() { main(); - __builtin_unreachable(); }