polmon: al int80, run args, ret code

This commit is contained in:
2025-10-03 23:34:27 +02:00
parent cad4f5081a
commit da77e08b80

View File

@@ -6,21 +6,20 @@ namespace {
constexpr int kDumpSize = 16; constexpr int kDumpSize = 16;
// arguments on the stack in reverse order extern "C" uint16_t Int80h(uint16_t fun, uint16_t nargs, uint16_t args[]);
extern "C" uint16_t Int80h(uint8_t fun, int nargs);
asm(".section .text.Int80h \n" asm(".section .text.Int80h \n"
"Int80h: \n" "Int80h: \n"
" push %si \n" " push %si \n"
" push %bp \n" " push %bp \n"
" mov %al, %ah \n"
" mov %sp, %bp \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" "0: \n"
" test %dx, %dx \n" " cmp %cx, %si \n"
" jz 1f \n" " je 1f \n"
" push (%si) \n" " push -2(%si) \n"
" dec %dx \n" " sub $2, %si \n"
" add $2, %si \n"
" jmp 0b \n" " jmp 0b \n"
"1: \n" "1: \n"
" int $0x80 \n" " int $0x80 \n"
@@ -42,21 +41,22 @@ uint8_t ReadHexNibble(uint8_t c) {
return 10 + (c - 'a'); return 10 + (c - 'a');
} }
uint16_t ReadUintN(int n, const char* buf) { uint16_t ReadUintN(int n, const char*& buf) {
uint16_t out = 0; uint16_t out = 0;
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
if (buf[i] == 0) { if (*buf < '0') {
break; break;
} }
out <<= 4; out <<= 4;
out += ReadHexNibble(buf[i]); out += ReadHexNibble(*buf);
buf += 1;
} }
return out; 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) { void WriteHexNibble(uint8_t c) {
if (c > 9) { if (c > 9) {
@@ -76,6 +76,11 @@ void WriteUint16(uint16_t a) {
WriteUint8(a & 0xff); WriteUint8(a & 0xff);
} }
void WriteUint16ln(uint16_t a) {
WriteUint16(a);
puts("\r\n");
}
uint8_t __get_far_u8__(uint16_t addr, uint16_t seg) { uint8_t __get_far_u8__(uint16_t addr, uint16_t seg) {
register uint16_t ad asm("si") = addr; register uint16_t ad asm("si") = addr;
register uint16_t sg asm("ds") = seg; register uint16_t sg asm("ds") = seg;
@@ -126,8 +131,7 @@ void DumpHex(uint16_t addr, uint16_t seg) {
putchar(']'); putchar(']');
putchar(':'); putchar(':');
Dump(addr, seg, kDumpSize); Dump(addr, seg, kDumpSize);
putchar('\r'); puts("\r\n");
putchar('\n');
} }
void ClearScreen() { 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 kSegment = 0x200;
constexpr uint16_t kAddress = 0x100; constexpr uint16_t kAddress = 0x100;
constexpr uint16_t kHeaderAddress = (kSegment << 4); constexpr uint16_t kHeaderAddress = (kSegment << 4);
constexpr uint16_t kFlatAddress = (kSegment << 4) + kAddress; 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 }; constexpr uint8_t kTrampoline[] = { 0xe8, 0xfd, 0x00, 0xcb };
char fatname[11]; char fatname[11];
tofatname(name, fatname); tofatname(name, fatname);
uint16_t r = __readfile__(fatname, kFlatAddress);
if (r) {
return r;
}
auto* ptr = reinterpret_cast<uint8_t*>(kHeaderAddress); auto* ptr = reinterpret_cast<uint8_t*>(kHeaderAddress);
memcpy(ptr, kTrampoline, sizeof(kTrampoline)); memcpy(ptr, kTrampoline, sizeof(kTrampoline));
auto* argp = reinterpret_cast<uint16_t*>(kHeaderAddress + kArgvAddress);
memcpy(argp, argv, argc * 2);
asm volatile("mov %1, %%ax \n\t" register uint16_t ac asm("ax") = argc;
"push %%ax \n\t" register uint16_t av asm("dx") = kArgvAddress;
"mov %0, %%ax \n\t" asm volatile(
"push %%ax \n\t" "mov %2, %%cx \n\t"
"mov $04, %%ah \n\t" "mov %%cx, %%ds \n\t"
"int $0x80 \n\t" "mov %%cx, %%es \n\t"
"add $4, %%sp \n\t"
"mov %2, %%ax \n\t"
"mov %%ax, %%ds \n\t"
"mov %%ax, %%es \n\t"
"cli \n\t" "cli \n\t"
"mov %%ax, %%ss \n\t" "mov %%cx, %%ss \n\t"
"mov %3, %%ax \n\t" "mov %3, %%cx \n\t"
"xchg %%ax, %%sp \n\t" "xchg %%cx, %%sp \n\t"
"sti \n\t" "sti \n\t"
"push %%ax \n\t" "push %%cx \n\t"
"lcall %2,$0 \n\t" "lcall %2,$0 \n\t"
"xor %%ax, %%ax \n\t" "xor %%cx, %%cx \n\t"
"mov %%ax, %%ds \n\t" "mov %%cx, %%ds \n\t"
"mov %%ax, %%es \n\t" "mov %%cx, %%es \n\t"
"cli \n\t" "cli \n\t"
"pop %%sp \n\t" "pop %%sp \n\t"
"mov %%ax, %%ss \n\t" "mov %%cx, %%ss \n\t"
"sti" "sti"
:: "rmi"(fatname), : "+r" (ac), "+r" (av)
"rmi"(kFlatAddress), "i"(kSegment), "i"(kHeaderAddress) : "i"(kSegment), "i"(kAddress)
: "ax", "bx", "cx", "dx", "memory"); : "bx", "cx", "memory", "cc");
return ac;
} }
constexpr uint16_t kCtrlBreakVector = (0x1b * 4); constexpr uint16_t kCtrlBreakVector = (0x1b * 4);
@@ -221,9 +251,9 @@ extern "C" void cbreak();
asm(" .section .text.cbreak \n" asm(" .section .text.cbreak \n"
"cbreak: \n" "cbreak: \n"
" xor %ax, %ax \n" " xor %ax, %ax \n"
" mov %ds, %ax \n" " mov %ax, %ds \n"
" cli \n" " cli \n"
" mov %ss, %ax \n" " mov %ax, %ds \n"
" mov $0x2000, %sp \n" " mov $0x2000, %sp \n"
" sti \n" " sti \n"
" pushf \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;) { for (const char* ptr = buf; *ptr;) {
if (*ptr == 's') { if (*ptr == 's') {
cur_addr = 0; cur_addr = 0;
cur_seg = ReadUint16(ptr + 1); ptr += 1;
ptr += 5; cur_seg = ReadUint16(ptr);
} else if (*ptr == '$') { } else if (*ptr == '$') {
__basic__(); __basic__();
} else if (*ptr == 'j') { } else if (*ptr == 'j') {
@@ -254,46 +284,46 @@ bool ParseCommand(const char* buf, uint16_t& cur_addr, uint16_t& cur_seg) {
ptr++; ptr++;
auto jump = reinterpret_cast<uint16_t (*)()>(cur_addr); auto jump = reinterpret_cast<uint16_t (*)()>(cur_addr);
uint16_t ret = jump(); uint16_t ret = jump();
WriteUint16(ret); WriteUint16ln(ret);
putchar('\r');
putchar('\n');
} else if (*ptr == 'i') { } else if (*ptr == 'i') {
dump = false; dump = false;
int nargs = 0; uint16_t args[8]; // ought to be enough for everybody
uint8_t nargs = 0;
ptr++; ptr++;
int fun = ReadUint8(ptr); int fun = ReadUint16(ptr);
ptr += 2; for (; *ptr && nargs < 8;) {
for (; *ptr;) {
if (*ptr == ' ') { if (*ptr == ' ') {
ptr++; ptr++;
continue; continue;
} }
uint16_t d = ReadUint16(ptr); args[nargs++] = ReadUint16(ptr);
asm volatile("push %0" ::"r"(d));
nargs++;
ptr += 4;
} }
uint16_t ret = Int80h(fun, nargs); uint16_t ret = Int80h(fun, nargs, args);
asm volatile("shl %0 \n\t" WriteUint16ln(ret);
"add %0, %%sp" ::"r"(nargs));
WriteUint16(ret);
putchar('\r');
putchar('\n');
} else if (*ptr == 'l') { } else if (*ptr == 'l') {
dump = false; dump = false;
ClearScreen(); ClearScreen();
ptr++; ptr++;
} else if (*ptr == 'r') { } else if (*ptr == 'r') {
dump = false; dump = false;
uint16_t args[8]; // ought to be enough for everybody
uint8_t nargs = 0;
ptr++; ptr++;
while (*ptr == ' ') { while (*ptr == ' ') {
ptr++; ptr++;
} }
int l = 0; const char* fname = ptr;
for (; ptr[l]; l++) { for (; *ptr && *ptr != ' '; ptr++) {
} }
LaunchFile(ptr); for (; *ptr && nargs < 8;) {
ptr += l; if (*ptr == ' ') {
ptr++;
continue;
}
args[nargs++] = ReadUint16(ptr);
}
uint16_t ret = LaunchFile(fname, nargs, args);
WriteUint16ln(ret);
} else if (*ptr == 'w') { } else if (*ptr == 'w') {
dump = false; dump = false;
uint16_t addr = cur_addr; 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); uint8_t d = ReadUint8(ptr);
__set_far_u8__(addr, cur_seg, d); __set_far_u8__(addr, cur_seg, d);
addr++; addr++;
ptr += 2;
} }
} else { } else {
cur_addr = ReadUint16(ptr); cur_addr = ReadUint16(ptr);
ptr += 4;
} }
} }
return dump; return dump;
} }
void DisplayPrompt() { void DisplayPrompt() {
putchar('>'); puts("> ");
putchar(' ');
} }
[[noreturn]]
void polmon() { void polmon() {
uint16_t cur_addr = 0; uint16_t cur_addr = 0;
uint16_t cur_seg = 0; uint16_t cur_seg = 0;
@@ -365,6 +393,7 @@ void polmon() {
inptr++; inptr++;
} }
} }
__builtin_unreachable();
} }
} // namespace } // namespace
@@ -374,7 +403,7 @@ int main() {
polmon(); polmon();
} }
__attribute__((section(".init"), noreturn, used)) void _start() { __attribute__((section(".init"), used))
void _start() {
main(); main();
__builtin_unreachable();
} }