From bf16ae5646bedcd3be8abf142a8c652052fb1884 Mon Sep 17 00:00:00 2001 From: Paul Mathieu Date: Wed, 24 Sep 2025 00:51:56 +0200 Subject: [PATCH] Add polmon executable --- Makefile | 12 ++ flat0600.ld | 20 +++ polmon.cc | 384 ++++++++++++++++++++++++++++++++++++++++++++++++++++ wozmon.cc | 152 --------------------- wozmon.s | 255 ---------------------------------- 5 files changed, 416 insertions(+), 407 deletions(-) create mode 100644 flat0600.ld create mode 100644 polmon.cc delete mode 100644 wozmon.cc delete mode 100644 wozmon.s diff --git a/Makefile b/Makefile index fdf8895..5cbadf4 100644 --- a/Makefile +++ b/Makefile @@ -31,6 +31,17 @@ fat12boot.elf: LDFLAGS += -T bootsect.ld fat12boot.bin: fat12boot.elf +polmon.elf: LDFLAGS += -T flat0600.ld +polmon.elf: polmon.o + +polmon.com: polmon.elf + ia16-elf-objcopy -O binary $? $@ + +wozmon.o: polmon.cc +wozmon.o: CPPFLAGS = -DWOZMON=1 +wozmon.o: + $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $< + wozmon.elf: wozmon.o bootsect.S wozmon.elf: LDFLAGS += -T bootsect.ld wozmon.elf: CPPFLAGS += -DNOBPB @@ -62,6 +73,7 @@ binaries: ## Build all binaries docker build --build-arg TARGET=debug.bin -o . --target=export . docker build --build-arg TARGET=dosdbt.bin -o . --target=export . docker build --build-arg TARGET=format.bin -o . --target=export . + docker build --build-arg TARGET=polmon.com -o . --target=export . docker build --build-arg TARGET=fat12boot.bin -o . --target=export . diff --git a/flat0600.ld b/flat0600.ld new file mode 100644 index 0000000..1deec9e --- /dev/null +++ b/flat0600.ld @@ -0,0 +1,20 @@ +SECTIONS { + . = 0x0600; + + .text : { + KEEP(*(.init)) + *(.text*) + } + + .rodata : { + *(.rodata*) + } + + .bss (NOLOAD) : { + * (.bss) + } + + .data : { + *(.data) + } +} diff --git a/polmon.cc b/polmon.cc new file mode 100644 index 0000000..29de476 --- /dev/null +++ b/polmon.cc @@ -0,0 +1,384 @@ +#include + +#ifndef WOZMON +#define WOZMON 0 +#endif + +#if WOZMON +#define BACKSPACE 0 +#define ASCIIDUMP 0 +#define CLEARSCREENCMD 0 +#define FARCALL 0 +#define SHOWTITLE 0 +#define BOOTSTRAP 0 +#endif // WOZMON + +#ifndef BACKSPACE +#define BACKSPACE 1 +#endif + +#ifndef ASCIIDUMP +#define ASCIIDUMP 1 +#endif + +#ifndef CLEARSCREENCMD +#define CLEARSCREENCMD 1 +#endif + +#ifndef FARCALL +#define FARCALL 1 +#endif + +#ifndef SHOWTITLE +#define SHOWTITLE 1 +#endif + +#ifndef BOOTSTRAP +#define BOOTSTRAP 1 +#endif + +namespace { + +constexpr int kDumpSize = 16; + +uint8_t getc() { + register uint8_t c asm ("al"); + asm volatile ( + "movb $0x00, %%ah\n\t" + "int $0x16" + : "=r" (c) + :: "ah", "cc" + ); + return c; +} + +void putc(uint8_t c) { + asm volatile ( + "movb %0, %%al \n\t" + "movb $0x0e, %%ah \n\t" + "movb $0, %%bh \n\t" + "int $0x10 \n\t" + :: "r" (c) + : "ax", "bh", "cc", "bp" + ); +} + +void puts(const char* s) { + while (*s) { + putc(*s++); + } +} + +// arguments on the stack in reverse order +extern "C" uint16_t Jump(uint16_t addr, int nargs); +asm ( + ".section .text \n" + "Jump: \n" + " push %bx \n" + " push %si \n" + " push %di \n" + " push %bp \n" + " push %es \n" + " push %ax \n" // addr + " movw %sp, %bp \n" + " movw %dx, %si \n" // nargs + " add %si, %si \n" + "j0: \n" + " test %si, %si \n" + " jz j1 \n" + " lea 12(%bp,%si), %di\n" + " push %di \n" + " sub $2, %si \n" + " jmp j0 \n" + "j1: \n" + " lcall *(%bp) \n" + " add $4, %sp \n" + " pop %bp \n" + " pop %di \n" + " pop %si \n" + " pop %bx \n" + " ret" + // return value in ax + ); + +constexpr uint8_t kBackspace = 0x7f; +constexpr uint8_t kOtherBackspace = 0x08; + +uint8_t ReadHexNibble(uint8_t c) { + // lowercase only + if (c <= '9') { + return c - '0'; + } + return 10 + (c - 'a'); +} + +uint16_t ReadUintN(int n, const char* buf) { + uint16_t out = 0; + for (int i = 0; i < n; i++) { + if (buf[i] == 0) { + break; + } + out <<= 4; + out += ReadHexNibble(buf[i]); + } + return out; +} + +uint8_t ReadUint8(const char* buf) { + return ReadUintN(2, buf); +} + +uint16_t ReadUint16(const char* buf) { + return ReadUintN(4, buf); +} + +void WriteHexNibble(uint8_t c) { + if (c > 9) { + putc('a' + c - 10); + } else { + putc('0' + c); + } +} + +void WriteUint8(uint8_t a) { + WriteHexNibble(a >> 4); + WriteHexNibble(a & 0xf); +} + +void WriteUint16(uint16_t a) { + WriteUint8(a >> 8); + WriteUint8(a & 0xff); +} + +void __set_es__(uint16_t es) { + asm volatile ( + "mov %0, %%es" + :: "r" (es) + : "es" + ); +} + +uint8_t __get_es_u8__(uint16_t addr) { + register uint16_t ad asm ("di") = addr; + uint8_t ret; + asm volatile ( + "movb %%es:(%1), %0" + : "=r" (ret) + : "r" (ad) + ); + return ret; +} + +void __set_es_u8__(uint16_t addr, uint8_t val) { + register uint16_t ad asm ("di") = addr; + asm volatile ( + "movb %0, %%es:(%1)" + :: "ri" (val), "rmi" (ad) + : "memory" + ); +} + +__attribute__((noreturn)) +inline static void __basic__() { + asm volatile ( + "movw $0x40, %ax \n\t" + "mov %ax, %ds \n\t" + "int $0x18" + ); + __builtin_unreachable(); +} + +void Dump(uint16_t addr, int count) { + for (int i = 0; i < count; i++) { + putc(' '); + uint8_t d = __get_es_u8__(addr + i); + WriteUint8(d); + } +#if ASCIIDUMP + putc(' '); + putc(' '); + for (int i = 0; i < count; i++) { + uint8_t d = __get_es_u8__(addr + i); + if (d > 31 && d < 127) { + putc(d); + } else { + putc('.'); + } + } +#endif +} + +void DumpHex(uint16_t addr, uint16_t seg) { + addr &= -kDumpSize; + + putc('['); + WriteUint16(seg); + putc(':'); + __set_es__(seg); + WriteUint16(addr); + putc(']'); + putc(':'); + Dump(addr, kDumpSize); + putc('\r'); + putc('\n'); +} + +void ClearScreen() { + asm volatile ( + "movw $0x0002, %%ax \n\t" + "int $0x10" + ::: "ax", "cc" + ); +} + +void Status(uint8_t status) { + asm volatile ( + "xorb %%bh, %%bh \n\t" + "movb $0x03, %%ah \n\t" + "int $0x10 \n\t" + "mov %%dx, %%di \n\t" + "movb $0x02, %%ah \n\t" + "movw $77, %%dx \n\t" + "int $0x10 \n\t" + "movb %0, %%al \n\t" + "call _ZN12_GLOBAL__N_110WriteUint8Eh \n\t" + "movb $0x02, %%ah \n\t" + "movw %%di, %%dx \n\t" + "int $0x10" + :: "rm" (status) + : "ax", "bh", "dx", "cx", "di", "cc" + ); +} + +bool ParseCommand(const char* buf, uint16_t& cur_addr, uint16_t& cur_seg) { + bool dump = true; + for (const char* ptr = buf; *ptr;) { + if (*ptr == 's') { + cur_addr = 0; + cur_seg = ReadUint16(ptr+1); + ptr += 5; + } else if (*ptr == '$') { + __basic__(); + } else if (*ptr == 'r') { + dump = false; +#if FARCALL + int nargs = 0; + ptr++; + for (; *ptr;) { + if (*ptr == ' ') { + ptr++; + continue; + } + uint16_t d = ReadUint16(ptr); + asm volatile ("push %0" :: "r" (d)); + nargs++; + ptr += 4; + } + __set_es__(cur_seg); + uint16_t ret = Jump(cur_addr, nargs); + asm volatile ( + "shl %0 \n\t" + "add %0, %%sp" + :: "r"(nargs) + ); + WriteUint16(ret); + putc('\r'); putc('\n'); +#else // FARCALL + auto jump = reinterpret_cast(cur_addr); + jump(); +#endif // FARCALL + ptr++; +#if CLEARSCREENCMD + } else if (*ptr == 'l') { + dump = false; + ClearScreen(); + ptr++; +#endif + } else if (*ptr == 'w') { + dump = false; + uint16_t addr = cur_addr; + ptr += 1; + for (; *ptr;) { + if (*ptr == ' ') { + ptr++; + continue; + } + uint8_t d = ReadUint8(ptr); + __set_es__(cur_seg); + __set_es_u8__(addr, d); + addr++; + ptr += 2; + } + } else { + cur_addr = ReadUint16(ptr); + ptr += 4; + } + } + return dump; +} + +const char* prompt = "> "; + +void polmon() { + uint16_t cur_addr = 0; + uint16_t cur_seg = 0; + char inbuf[64]; + bool first = true; + char* inptr = inbuf; + + ClearScreen(); +#if SHOWTITLE + puts("PolMon 0.2\r\n"); +#endif // SHOWTITLE + puts(prompt); + + while (1) { + uint8_t c = getc(); + putc(c); // echo + if (c == '\r') { + *inptr = 0; + if (inbuf[0] == 0) { + if (!first) { + cur_addr += kDumpSize; + } + } else { + putc('\n'); + } + + if (ParseCommand(inbuf, cur_addr, cur_seg)) { + DumpHex(cur_addr, cur_seg); + }; + first = false; + inptr = inbuf; + puts(prompt); +#if BACKSPACE + } else if (c == kBackspace || c == kOtherBackspace) { + inptr--; + if (inptr < inbuf) { + inptr = inbuf; + putc(' '); + continue; + } + putc(' '); + putc(kOtherBackspace); +#endif + } else { + *inptr = c; + inptr++; + } + } +} + +} // namespace + +int main() { + polmon(); +} + +#if BOOTSTRAP +__attribute__((section(".init"), noreturn, used)) +void _start() { + main(); + __builtin_unreachable(); +} +#endif // BOOTSTRAP diff --git a/wozmon.cc b/wozmon.cc deleted file mode 100644 index 7434aa5..0000000 --- a/wozmon.cc +++ /dev/null @@ -1,152 +0,0 @@ -#include - -namespace { - -uint8_t getc() { - register uint8_t c asm ("al"); - asm volatile ( - "mov $0x00, %%ah\n" - "int $0x16\n" - : "=r" (c) - ); - return c; -} - -void putc(uint8_t c) { - asm volatile ( - "mov %0, %%al\n" - "mov $0x0e, %%ah\n" - "int $0x10\n" - :: "r" (c) - ); -} - -void Jump(uint32_t addr) { - auto jump = reinterpret_cast(addr); - jump(); -} - -constexpr uint8_t kBackspace = 0x7f; -constexpr uint8_t kOtherBackspace = 0x08; - -uint8_t ReadHexNibble(uint8_t c) { - // lowercase only - if (c <= '9') { - return c - '0'; - } - return 10 + (c - 'a'); -} - -uint32_t ReadHex(const char* buf) { - uint32_t out = 0; - while (*buf == ' ') { - buf++; - } - for (int i = 0; i < 8; i++) { - uint8_t c = ReadHexNibble(*buf); - if (c > 0xf) { - break; - } - out = (out << 4) + c; - buf++; - } - - return out; -} - -void WriteHexNibble(uint8_t c) { - if (c > 9) { - putc('a' + c - 10); - } else { - putc('0' + c); - } -} - -void WriteUint32(uint32_t a) { - for (int i = 0; i < 8; i++) { - WriteHexNibble((a >> 28) & 0xf); - a <<= 4; - } -} - -void WriteUint8(uint8_t a) { - WriteHexNibble(a >> 4); - WriteHexNibble(a & 0xf); -} - -void Dump(uint32_t addr, int count) { - for (int i = 0; i < count; i++) { - putc(' '); - WriteUint8(*reinterpret_cast(addr + i)); - } -} - -void DumpHex(uint32_t addr) { - addr &= 0xfffffffc; - WriteUint32(addr); - putc(':'); - Dump(addr, 4); - putc('\r'); - putc('\n'); -} - -int FindChar(const char* buf, uint8_t c) { - int found = 0; - while (*buf) { - if (*buf == c) { - return found; - } - found++; - buf++; - } - return -1; -} - -void wozmon() { - uint32_t cur_addr = 0; - uint32_t cur_data = 0; - - char inbuf[64]; - inbuf[0] = 0; - char* inptr = inbuf; - - while (1) { - uint8_t c = getc(); - putc(c); // echo - if (c == '\r') { - *inptr = 0; - if (inptr == inbuf) { - cur_addr += 4; - } else if (FindChar(inbuf, 'r') >= 0) { - Jump(cur_addr); - } else { - cur_addr = ReadHex(inbuf); - putc('\n'); - } - DumpHex(cur_addr); - int assigned = FindChar(inbuf, ':'); - if (assigned >= 0) { - cur_data = ReadHex(inbuf + assigned + 1); - *(reinterpret_cast(cur_addr)) = cur_data; - } - inptr = inbuf; - } else if (c == kBackspace) { - inptr--; - if (inptr < inbuf) { - inptr = inbuf; - continue; - } - putc(kOtherBackspace); - putc(' '); - putc(kOtherBackspace); - } else { - *inptr++ = c; - } - } -} - -} // namespace - -int main() { - wozmon(); -} diff --git a/wozmon.s b/wozmon.s deleted file mode 100644 index db462f1..0000000 --- a/wozmon.s +++ /dev/null @@ -1,255 +0,0 @@ - .arch i8086,jumps - .code16 - .att_syntax prefix -#NO_APP - .text - .type _ZN12_GLOBAL__N_14putcEh, @function -_ZN12_GLOBAL__N_14putcEh: - movw %sp, %bx - movb 2(%bx), %al -#APP -;# 21 "wozmon.cc" 1 -mov $0x0e, %ah -int $0x10 - -;# 0 "" 2 -#NO_APP - ret - .size _ZN12_GLOBAL__N_14putcEh, .-_ZN12_GLOBAL__N_14putcEh - .type _ZN12_GLOBAL__N_17ReadHexEPKc, @function -_ZN12_GLOBAL__N_17ReadHexEPKc: - pushw %si - pushw %di - pushw %bp - movw %sp, %bp - pushw %ds - pushw %ds - movw 8(%bp), %ax - movw %ax, -2(%bp) -.L5: - movw -2(%bp), %bx - cmpb $32, (%bx) - jne .L4 - incw -2(%bp) - jmp .L5 -.L4: - xorw %di, %di - movw %di, %ax - movw %di, %dx - movb $4, %ch -.L9: - movw %di, %bx - movw -2(%bp), %si - movb (%bx,%si), %cl - cmpb $57, %cl - ja .L6 - addb $-48, %cl -.L12: - movb %cl, %bl - cmpb $15, %cl - ja .L3 - movw %ax, %si - movb $12, %cl - shrw %cl, %si - movb %ch, %cl - shlw %cl, %dx - orw %si, %dx - shlw %cl, %ax - movb %bl, -4(%bp) - movb -4(%bp), %bl - xorb %bh, %bh - addw %bx, %ax - movw $0, %bx - adcw %bx, %dx - incw %di - cmpw $8, %di - jne .L9 -.L3: - movw %bp, %sp - popw %bp - popw %di - popw %si - ret -.L6: - addb $-87, %cl - jmp .L12 - .size _ZN12_GLOBAL__N_17ReadHexEPKc, .-_ZN12_GLOBAL__N_17ReadHexEPKc - .type _ZN12_GLOBAL__N_114WriteHexNibbleEh, @function -_ZN12_GLOBAL__N_114WriteHexNibbleEh: - pushw %bp - movw %sp, %bp - movb 4(%bp), %al - movb %al, %dl - xorb %dh, %dh - cmpw $9, %dx - jle .L14 - addb $87, %al -.L16: - movb %al, 4(%bp) - popw %bp - jmp _ZN12_GLOBAL__N_14putcEh -.L14: - addb $48, %al - jmp .L16 - .size _ZN12_GLOBAL__N_114WriteHexNibbleEh, .-_ZN12_GLOBAL__N_114WriteHexNibbleEh - .section .text.startup,"ax",@progbits - .global main - .type main, @function -main: - movw $0x8000, %sp - movw %sp, %bp - subw $76, %sp - movb $0, -64(%bp) - leaw -64(%bp), %di - xorw %si, %si - movw %si, -70(%bp) -.L18: -#APP -;# 11 "wozmon.cc" 1 - mov $0x00, %ah -int $0x16 - -;# 0 "" 2 -#NO_APP - pushw %ax - movb %al, -71(%bp) - call _ZN12_GLOBAL__N_14putcEh - addw $2, %sp - movb -71(%bp), %al - cmpb $13, %al - jne .L19 - movb $0, (%di) - leaw -64(%bp), %bx - cmpw %bx, %di - jne .L21 - addw $4, %si - adcw $0, -70(%bp) -.L22: - movw %si, %ax - andw $-4, %ax - movw %ax, %es - movw -70(%bp), %di - movw $8, %bx -.L25: - movw %ax, -76(%bp) - movw %bx, -74(%bp) - movb $12, %cl - movb %cl, -71(%bp) - pushw -68(%bp) - call _ZN12_GLOBAL__N_114WriteHexNibbleEh - movw -76(%bp), %ax - movw %ax, %dx - movb -71(%bp), %cl - shrw %cl, %dx - movb $4, %cl - shlw %cl, %di - shlw %cl, %ax - orw %dx, %di - addw $2, %sp - movw -74(%bp), %bx - decw %bx - jne .L25 - movb $58, %al - pushw %ax - call _ZN12_GLOBAL__N_14putcEh - movw %es, %di - leaw 4(%di), %cx - addw $2, %sp -.L26: - movw %cx, -74(%bp) - movb $32, %al - pushw %ax - call _ZN12_GLOBAL__N_14putcEh - movb (%di), %dl - movb %dl, %al - movb %dl, -71(%bp) - xorb %ah, %ah - movb $4, %cl - sarw %cl, %ax - pushw %ax - call _ZN12_GLOBAL__N_114WriteHexNibbleEh - movb -71(%bp), %dl - andb $15, %dl - pushw %dx - call _ZN12_GLOBAL__N_114WriteHexNibbleEh - incw %di - addw $6, %sp - movw -74(%bp), %cx - cmpw %di, %cx - jne .L26 - movb $13, %al - pushw %ax - call _ZN12_GLOBAL__N_14putcEh - movb $10, %al - pushw %ax - call _ZN12_GLOBAL__N_14putcEh - addw $4, %sp - xorw %bx, %bx - leaw -64(%bp), %di -.L29: - movb (%bx,%di), %al - testb %al, %al - je .L18 - cmpb $58, %al - je .L28 - incw %bx - jmp .L29 -.L32: - xchgw %ax, %di - jmp .L18 -.L21: - movb (%bx), %al - testb %al, %al - je .L23 - cmpb $114, %al - je .L24 - incw %bx - jmp .L21 -.L19: - cmpb $127, %al - jne .L30 - decw %di - leaw -64(%bp), %ax - cmpw %ax, %di - jc .L32 - movb $8, %al - pushw %ax - movb %al, -71(%bp) - call _ZN12_GLOBAL__N_14putcEh - movb $32, %dl - pushw %dx - call _ZN12_GLOBAL__N_14putcEh - movb -71(%bp), %al - pushw %ax - call _ZN12_GLOBAL__N_14putcEh - addw $6, %sp - jmp .L18 -.L30: - movb %al, (%di) - incw %di - jmp .L18 -.L24: - call *%si - jmp .L22 -.L23: - leaw -64(%bp), %ax - pushw %ax - call _ZN12_GLOBAL__N_17ReadHexEPKc - addw $2, %sp - xchgw %ax, %si - movw %dx, -70(%bp) - movb $10, %al - pushw %ax - call _ZN12_GLOBAL__N_14putcEh - addw $2, %sp - jmp .L22 -.L28: - leaw 1(%bx,%di), %bx - pushw %bx - call _ZN12_GLOBAL__N_17ReadHexEPKc - addw $2, %sp - movw %ax, (%si) - movw %dx, 2(%si) - jmp .L18 - .size main, .-main - .ident "GCC: (GNU) 6.3.0"