Add polmon executable

This commit is contained in:
2025-09-24 00:51:56 +02:00
parent 3c90dd8b3d
commit bf16ae5646
5 changed files with 416 additions and 407 deletions

View File

@@ -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 .

20
flat0600.ld Normal file
View File

@@ -0,0 +1,20 @@
SECTIONS {
. = 0x0600;
.text : {
KEEP(*(.init))
*(.text*)
}
.rodata : {
*(.rodata*)
}
.bss (NOLOAD) : {
* (.bss)
}
.data : {
*(.data)
}
}

384
polmon.cc Normal file
View File

@@ -0,0 +1,384 @@
#include <cstdint>
#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<void(*)()>(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

152
wozmon.cc
View File

@@ -1,152 +0,0 @@
#include <cstdint>
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<void (*)()>(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<uint8_t*>(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<uint32_t*>(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();
}

255
wozmon.s
View File

@@ -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"