polmon: al int80, run args, ret code
This commit is contained in:
167
src/polmon.cc
167
src/polmon.cc
@@ -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();
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user