Compare commits

...

13 Commits

21 changed files with 738 additions and 94 deletions

View File

@@ -6,8 +6,8 @@ dev-image = 5150-dev
crc16.s: crc16.c crc16.s: crc16.c
ia16-elf-gcc -S -Os -o crc16.s crc16.c ia16-elf-gcc -S -Os -o crc16.s crc16.c
crc16.bin: crc16.s crt0.c crc16.bin: crc16.s
ia16-elf-gcc -o crc16.bin -Os -nostdlib crc16.s crt0.c ia16-elf-gcc -o crc16.bin -Os -nostdlib crc16.s
CC = ia16-elf-gcc CC = ia16-elf-gcc
CXX = ia16-elf-gcc CXX = ia16-elf-gcc
@@ -31,11 +31,13 @@ fat12boot.elf: LDFLAGS += -T bootsect.ld
fat12boot.bin: fat12boot.elf fat12boot.bin: fat12boot.elf
stdlib.o: CFLAGS := $(filter-out -flto, $(CFLAGS))
polmon.elf: LDFLAGS += -T flat1000.ld polmon.elf: LDFLAGS += -T flat1000.ld
polmon.elf: polmon.o stdlib.o polmon.elf: polmon.o stdlib.o
polio.elf: LDFLAGS += -T flat0600.ld polio.elf: LDFLAGS += -T flat0600.ld
polio.elf: polio.s fat12.o polio.elf: polio-main.o polio.s fat12.o paracomm.o stdlib.o
wozmon.o: polmon.cc wozmon.o: polmon.cc
wozmon.o: CPPFLAGS = -DWOZMON=1 wozmon.o: CPPFLAGS = -DWOZMON=1
@@ -51,12 +53,19 @@ wozmon.bin: wozmon.elf
paracli.elf: LDFLAGS += -T doscom.ld paracli.elf: LDFLAGS += -T doscom.ld
paracli.elf: paracli.s paracomm.o paracli.elf: paracli.s paracomm.o
polos.img: fat12boot.bin polmon.com polio.com paracli.com dos-programs = mushroom.elf hello.elf
$(dos-programs): LDFLAGS += -T doscom.ld
mushroom.elf: mushroom.s
hello.elf: hello.o stdlib.o crt0.s
polos.img: fat12boot.bin polmon.com polio.com mushroom.com hello.com
dd if=/dev/zero of=$@ bs=512 count=720 dd if=/dev/zero of=$@ bs=512 count=720
mformat -i $@ -t 40 -h 2 -s 9 mformat -i $@ -t 40 -h 2 -s 9
mcopy -i $@ polio.com ::/ mcopy -i $@ polio.com ::/
mcopy -i $@ polmon.com ::/ mcopy -i $@ polmon.com ::/
mcopy -i $@ paracli.com ::/ mcopy -i $@ mushroom.com ::/
mcopy -i $@ hello.com ::/
dd if=fat12boot.bin of=$@ conv=notrunc dd if=fat12boot.bin of=$@ conv=notrunc
.PHONY: clean .PHONY: clean

View File

@@ -14,13 +14,9 @@ void setup() {
pc = ParaComms{ pc = ParaComms{
.mosi_cb = .mosi_cb =
[](uint8_t *data, uint8_t len) { [](uint8_t* data, uint8_t len) {
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
Serial.printf("%c", data[i]); Serial.printf("%c", data[i]);
pc.SendByte(data[i]); // echo
if (data[i] == '\r') {
pc.SendByte('\n');
}
} }
}, },
}; };
@@ -41,7 +37,7 @@ void loop() {
} }
led_counter += 1; led_counter += 1;
checkKbdReset(); // checkKbdReset();
uint8_t mosib; uint8_t mosib;
if (strobeOccurred(mosib)) { if (strobeOccurred(mosib)) {
@@ -52,6 +48,9 @@ void loop() {
if (Serial.available() > 0) { if (Serial.available() > 0) {
int c = Serial.read(); int c = Serial.read();
#if 1
pc.SendByte(c);
#else
if (c == 2) { if (c == 2) {
mode = 0; mode = 0;
} else if (c == 3) { } else if (c == 3) {
@@ -63,5 +62,6 @@ void loop() {
pc.SendByte(c); pc.SendByte(c);
} }
} }
#endif
} }
} }

View File

@@ -14,7 +14,7 @@ SECTIONS {
* (.bss) * (.bss)
} }
.data : { .data (NOLOAD) : {
*(.data) *(.data)
} }

View File

@@ -3,6 +3,11 @@
.att_syntax prefix .att_syntax prefix
#NO_APP #NO_APP
#APP #APP
.section .text.init
.global _start
_start:
.section .text.main
.global main .global main
main: main:
push %bp push %bp

25
crt0.c
View File

@@ -1,25 +0,0 @@
#include <stdint.h>
#include <string.h>
int main();
asm(".section .init \n"
".global _start \n"
"_start: \n\t"
"mov %cs, %ax \n\t"
"mov %ax, %ds \n\t"
"mov %ax, %es \n\t"
"cli \n\t"
"mov %ax, %ss \n\t"
"mov $0x1000, %ax \n\t"
"mov %ax, %sp \n\t"
"sti \n\t"
"jmp main");
void* memset(void* ptr, int val, size_t len) {
uint8_t* p = ptr;
while (len--) {
*p++ = val;
}
return ptr;
}

8
crt0.s Normal file
View File

@@ -0,0 +1,8 @@
.arch i8086,jumps
.code16
.intel_syntax noprefix
.section .init
.global _start
_start:
jmp main

View File

@@ -14,7 +14,7 @@ SECTIONS {
* (.bss) * (.bss)
} }
.data : { .data (NOLOAD) : {
*(.data) *(.data)
} }
} }

View File

@@ -14,7 +14,7 @@ SECTIONS {
* (.bss) * (.bss)
} }
.data : { .data (NOLOAD) : {
*(.data) *(.data)
} }
} }

View File

@@ -14,7 +14,7 @@ SECTIONS {
* (.bss) * (.bss)
} }
.data : { .data (NOLOAD) : {
*(.data) *(.data)
} }
} }

48
ftp.asm Normal file
View File

@@ -0,0 +1,48 @@
CPU 8086
chunksize equ 0x20
devicedelay equ 0x08
_start:
push bp
mov bp, sp
sub sp, 8
mov [bp-2], word chunksize ; recv size
mov [bp-4], word 0xf000 ; recv addr
mov [bp-6], word 0x0001 ; send size
mov [bp-8], word 0x7000 ; send addr
mov bx, [bp-8]
mov [bx], byte 0x42
l0:
cmp word [bp-4], 0xf600
jb l1
l2:
mov sp, bp
pop bp
ret
l1:
mov ah, 0x07
int 0x80
test al, al
jnz l1
push word [bp-2]
push word [bp-4]
mov ah, 0x05
int 0x80
test al, al
jz l2
mov ah, 0
add [bp-4], ax
push word [bp-6]
push word [bp-8]
mov ah, 0x06
int 0x80
add sp, 8
mov cx, devicedelay
l3:
mov ah, 0x07
push cx
int 0x80
pop cx
loop l3 ; give the device some time to answer
jmp l0

5
hello.c Normal file
View File

@@ -0,0 +1,5 @@
#include <stdio.h>
int main() {
puts("Hello, world!\r\n");
}

55
mrbridge.py Normal file
View File

@@ -0,0 +1,55 @@
import argparse
import serial
import threading
import time
import websocket
def parse_args():
parser = argparse.ArgumentParser(description="Bridge a serial port to a websocket")
parser.add_argument("port", help="path to the serial port")
parser.add_argument("--baudrate", default=115200)
parser.add_argument("--escape", action='store_true')
parser.add_argument("ws", help="URL of the websocket")
return parser.parse_args()
def device_thread(device, ws):
while True:
line = device.readline()
ws.send(line)
def slowwrite(device, data):
for b in data:
device.write([b])
time.sleep(0.01)
def ws_thread(device, ws):
while True:
data = ws.recv();
slowwrite(device, data.replace(b'\n', b'\r\n'))
def main():
args = parse_args()
device = serial.Serial(args.port, baudrate=args.baudrate)
ws = websocket.create_connection(args.ws)
wst = threading.Thread(target=ws_thread, args=(device, ws), daemon=True)
wst.start()
if args.escape:
device.write([0x03])
try:
device_thread(device, ws)
except KeyboardInterrupt:
pass
finally:
if args.escape:
device.write([0x02])
if __name__ == "__main__":
main()

261
mushroom.s Normal file
View File

@@ -0,0 +1,261 @@
.arch i8086,jumps
.code16
.intel_syntax noprefix
.section .init
.global _start
_start:
mov ax, cs
mov ds, ax
mov es, ax
cli
mov ss, ax
mov sp, 0x100
sti
jmp main
.section .bss
kBufSize = 77
kDividerRow = 23
kRecvBufSize = 128
curpos: .word 0
inputsize: .byte 0
escaped: .byte 0
inputbuf: .zero kBufSize
recvbuf: .zero kRecvBufSize
# XXX: funky call
# inputs:
# si: string offset
# cl: string length
# clobbers: ax, bh, dx
.section .text.printn
printn:
push bx
push bp
mov bh, 0
1:
test cl, cl
jz 0f
mov al, [si]
cmpb escaped, 0
je 3f
cmp al, 'm'
jne 5f
movb escaped, 0
jmp 5f
3:
cmp al, 0x1b # ESC
jne 4f
movb escaped, 1
jmp 5f
4:
mov ah, 0x0e # write tty
int 0x10
push cx
mov ah, 0x03 # get cursor
int 0x10
cmp dh, kDividerRow
jb 2f
push dx
mov ah, 0x08 # read color
int 0x10
mov bh, ah
xor cx, cx
mov dx, 0x164f
mov ax, 0x0601 # scroll up, 1 line
int 0x10
pop dx
dec dh
mov bh, 0
mov ah, 0x02 # set cursor
int 0x10
2:
pop cx
5:
inc si
dec cl
jmp 1b
0:
pop bp
pop bx
ret
# XXX: funky call
# inputs:
# si: string offset
# cl: string length
# clobbers: ax, bh, dx
.section .text.addtext
addtext:
push di
push cx
mov bh, 0
mov ah, 0x03 # get cursor pos
int 0x10
pop cx
push dx
mov di, offset curpos
mov dx, [di]
mov ah, 0x02 # set cursor
int 0x10
call printn
mov ah, 0x03 # get cursor pos
int 0x10
mov [di], dx
pop dx
mov ah, 0x02 # set cursor
int 0x10
pop di
ret
.section .text.sendbuffer
sendbuffer:
push bp
mov bp, sp
sub sp, 2
mov al, inputsize
mov [bp-2], al
movb inputsize, 0
mov si, offset .l0
mov cl, 2
call addtext
mov si, offset inputbuf
mov cl, [bp-2]
call addtext
mov si, offset .l1
mov cl, 2
call addtext
mov si, offset inputbuf
mov cl, [bp-2]
call parasend
# XXX: should check cx in case not everything was sent
mov al, ' '
mov dx, 0x1802 # [24; 2]
call drawchar
mov ah, 0x02
int 0x10 # mov cursor back to start of line
add sp, 2
pop bp
ret
# draw until end of line
# al: char
# dh: row
# dl: start col
.section .text.drawchar
drawchar:
push ax
mov bh, 0
mov ah, 0x02 # set cursor
int 0x10
mov cx, 80
sub cl, dl
pop ax
mov ah, 0x0a
int 0x10
ret
.section .text.parasend
parasend:
mov ah, 0x06 # send parallel
push cx
push si
int 0x80
mov cx, 1
push cx
mov cx, offset .l1 + 1
push cx
mov ah, 0x06 # send parallel
int 0x80
add sp, 8
ret
prompt:
mov bh, 0
mov dx, 0x1800
mov ah, 0x02
int 0x10
mov ah, 0x0e
mov al, '>'
int 0x10
mov ah, 0x0e
mov al, ' '
int 0x10
ret
.section .rodata
.l0: .ascii "> "
.l1: .byte 0x0d, 0x0a
.l2: .ascii "MUSHRoom 8086 client 0.1\r\n"
l2len = . - offset .l2
.section .text.main
.global main
main:
movb inputsize, 0 # inputsize = 0
movw curpos, 0 # mov buffer cursor to [0;0]
movb escaped, 0
mov ax, 0x0002
int 0x10
mov si, offset .l2
mov cl, l2len
call addtext
mov dx, 0x1700 # [23; 0]
mov al, 0xc4 # horizontal box line
call drawchar
call prompt
0:
mov ah, 0x01
int 0x16 # check buffer
jz 1f # if empty, do a round of comms
mov ah, 0x00
int 0x16 # read 1 key
cmp al, 0x08 # backspace
je 5f
cmp al, 0x0d # CR
je 4f
mov di, offset inputbuf
mov si, offset inputsize
mov bh, 0
mov bl, [si]
cmp bl, kBufSize # stop accepting input at end of screen
jge 1f # do a round of comms
mov [di+bx], al # store character in buffer
incb [si] # increment buffer size
mov ah, 0x0e
mov bh, 0
int 0x10 # local echo
jmp 0b
5:
mov bl, inputsize
test bl, bl
jz 0b
decb inputsize
mov bh, 0
mov ah, 0x0e
int 0x10 # backspace
mov ax, 0x0e20
int 0x10
mov ax, 0x0e08
int 0x10
jmp 0b
4:
call sendbuffer # send input buffer
1:
mov ah, 0x07 # do parallel comms
int 0x80
mov ax, kRecvBufSize
push ax
mov ax, offset recvbuf
push ax
mov ah, 0x05 # recv
int 0x80
test al, al
mov cl, al
pop si
pop bx
jz 0b
call addtext
jmp 0b

View File

@@ -1,6 +1,7 @@
#include "paracomm.h" #include "paracomm.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#define kMosiIdleByte 0x00 #define kMosiIdleByte 0x00
#define kMosiStartByte 0x42 #define kMosiStartByte 0x42
@@ -21,7 +22,6 @@ static uint8_t miso_recvbuf[256];
static uint8_t miso_size; static uint8_t miso_size;
static uint8_t miso_received_nibbles; static uint8_t miso_received_nibbles;
static uint8_t miso_state; static uint8_t miso_state;
static void (*miso_cb)(const uint8_t*, uint8_t);
static void swapbuffers() { static void swapbuffers() {
mosi_sendbuf = mosi_workbuf[mosi_workbuf_idx]; mosi_sendbuf = mosi_workbuf[mosi_workbuf_idx];
@@ -92,23 +92,19 @@ void paracomm_feed(uint8_t n) {
miso_received_nibbles += 1; miso_received_nibbles += 1;
if (miso_received_nibbles == 2 * miso_size) { if (miso_received_nibbles == 2 * miso_size) {
if (miso_cb != 0) {
miso_cb(miso_recvbuf, miso_size);
}
miso_state = 0; miso_state = 0;
} }
} break; } break;
} }
} }
void paracomm_init(miso_cb_t cb) { void paracomm_init() {
mosi_size = 0; mosi_size = 0;
mosi_workbuf_idx = 0; mosi_workbuf_idx = 0;
mosi_workbuf_size = 0; mosi_workbuf_size = 0;
mosi_state = 0; mosi_state = 0;
miso_state = 0; miso_state = 0;
miso_cb = cb;
} }
int paracomm_send(uint8_t b) { int paracomm_send(uint8_t b) {
@@ -122,3 +118,21 @@ int paracomm_send(uint8_t b) {
return 0; return 0;
} }
uint8_t paracomm_recv(uint8_t* buf, uint8_t size) {
if (miso_state != 0) {
return 0;
}
if (size > miso_size) {
size = miso_size;
}
memcpy(buf, miso_recvbuf, size);
memcpy(miso_recvbuf, miso_recvbuf+size, miso_size - size);
miso_size -= size;
return size;
}
uint8_t paracomm_busy() {
return mosi_state != 0 || miso_state != 0;
}

View File

@@ -2,18 +2,24 @@
#include <stdint.h> #include <stdint.h>
typedef void (*miso_cb_t)(const uint8_t* buff, uint8_t size);
/** Must call first **/ /** Must call first **/
void paracomm_init(miso_cb_t miso_cb); void paracomm_init();
/** Sends a single byte. /** Sends a single byte.
* Returns: 0 if no error, non-0 otherwise. * Returns: 0 if no error, non-0 otherwise.
*/ */
int paracomm_send(uint8_t b); int paracomm_send(uint8_t b);
/** Receive some bytes.
* Returns: number of bytes copied
*/
uint8_t paracomm_recv(uint8_t* buf, uint8_t size);
/** Call after reading a nibble from the port */ /** Call after reading a nibble from the port */
void paracomm_feed(uint8_t n); void paracomm_feed(uint8_t n);
/** Yields the next byte to send out the port */ /** Yields the next byte to send out the port */
uint8_t paracomm_nextbyte(); uint8_t paracomm_nextbyte();
/** Returns non-zero if busy */
uint8_t paracomm_busy();

93
polio-main.c Normal file
View File

@@ -0,0 +1,93 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "fat12.h"
#include "paracomm.h"
#define kFatAddr ((void*)0x1a00)
#define kRootDirAddr ((void*)0x1c00)
#define kPolmonAddr ((void*)0x1000)
#define kInt80Vector ((uint16_t*)(0x80 * 4))
#define kParallelDataPort 0x3bc
#define kParallelStatusPort 0x3bd
#define kParallelControlPort 0x3be
#define kParaDelay 400
#define kRecvBufferSize 256
void dosdbt();
void int80h();
uint8_t parabuf[kRecvBufferSize];
uint8_t parasize;
static void paracb(const uint8_t* buf, uint8_t size) {
// we'll mercilessly erase old data with new data
memcpy(parabuf, buf, size);
parasize = size;
}
static void die() {
while (1) {
}
}
static void __outb__(uint16_t port, uint8_t data) {
register uint16_t p asm("dx") = port;
register uint8_t d asm("al") = data;
asm volatile("outb %0, %1" ::"r"(d), "r"(p));
}
static uint8_t __inb__(uint16_t port) {
register uint16_t p asm("dx") = port;
register uint8_t d asm("al");
asm volatile("inb %1, %0" : "=r"(d) : "r"(p));
return d;
}
static void __delay__(int n) {
for (int i = 0; i < n; i++) {
asm volatile("");
}
}
uint8_t xferpara() {
uint8_t mosib = paracomm_nextbyte();
__outb__(kParallelDataPort, mosib);
__outb__(kParallelControlPort, 1);
__delay__(kParaDelay);
__outb__(kParallelControlPort, 0);
__delay__(kParaDelay);
uint8_t mison = __inb__(kParallelStatusPort) >> 4;
paracomm_feed(mison);
return paracomm_busy();
}
uint8_t parasend(uint8_t* addr, uint8_t size) {
uint8_t i;
for (i = 0; i < size; i++) {
if (paracomm_send(addr[i])) {
break;
}
}
return i;
}
int main() {
dosdbt();
parasize = 0;
paracomm_init(paracb);
fat12_init(kFatAddr, kRootDirAddr);
uint16_t* int80v = kInt80Vector;
int80v[0] = (uint16_t)int80h;
int80v[1] = 0;
if (fat12_readfile("POLMON COM", kPolmonAddr)) {
die();
}
asm volatile("jmp *%0" ::"r"(kPolmonAddr));
}

84
polio.s
View File

@@ -5,6 +5,10 @@
.section .init .section .init
.global _start .global _start
_start: _start:
cli
mov ax, 0x2000 # stack address
mov sp, ax # ss should already be 0
sti
jmp main jmp main
@@ -12,7 +16,7 @@ diskpointer = 0x1e*4
dbtbase = 0x0500 dbtbase = 0x0500
.section .text.dosdbt .section .text.dosdbt
.local dosdbt .global dosdbt
dosdbt: # assumes es=0 dosdbt: # assumes es=0
push si push si
push di push di
@@ -36,8 +40,13 @@ dosdbt: # assumes es=0
.section .text.int80stuff .section .text.int80stuff
# near copy [param 2] bytes, es:[param 0] -> es:[param 1] # near copy [param 2] bytes, ds:[param 0] -> ds:[param 1]
copy: copy:
mov ax, [bp-14] # ds
mov es, ax
mov ds, ax
mov cl, 4
shl si, cl
mov si, [bp+0] # source mov si, [bp+0] # source
mov di, [bp+2] # destination mov di, [bp+2] # destination
mov cx, [bp+4] # length mov cx, [bp+4] # length
@@ -103,51 +112,43 @@ formattrack:
int 0x13 int 0x13
ret ret
# params: ds:fname, ds:dest
readfile: readfile:
mov si, [bp-14] # ds
mov cl, 4
shl si, cl
mov ax, [bp+0] mov ax, [bp+0]
add ax, si
mov dx, [bp+2] mov dx, [bp+2]
add dx, si
call fat12_readfile call fat12_readfile
ret ret
# params: ds:addr, size
sendpara:
mov si, [bp-14] # ds
mov cl, 4
shl si, cl
mov ax, [bp+0]
add ax, si
mov dx, [bp+2]
call parasend
ret
.section .rodata.polmon_str # params: ds:addr, size
polmon_str: .ascii "POLMON COM" recvpara:
polmon_addr = 0x1000 mov si, [bp-14] # ds
mov cl, 4
.section .text.main shl si, cl
.global main mov ax, [bp+0]
main: add ax, si
cli mov dx, [bp+2]
mov ax, 0x2000 # stack address call paracomm_recv
mov sp, ax # ss should already be 0 ret
sti
call dosdbt
mov ax, 0x1a00 # first sector of first fat
mov dx, 0x1c00 # first sector of root dir
call fat12_init
mov si, 0x80*4
movw [si], offset int80h
movw [si+2], 0
mov ax, offset polmon_str
mov dx, polmon_addr
call fat12_readfile
test ax, ax
jnz 0f
jmp polmon_addr
0:
mov ax, 0x0e42
mov bh, 0
int 0x10
cli
hlt
.section .text.int80h .section .text.int80h
.global int80h
int80h: int80h:
push bx
push si push si
push di push di
push bp push bp
@@ -163,8 +164,8 @@ int80h:
xor ah, ah xor ah, ah
mov si, ax mov si, ax
mov bp, sp mov bp, sp
lea bp, [bp + 18] # 12 for us, 6 for the interrupt lea bp, [bp + 16] # 10 for us, 6 for the interrupt
call [int80h_table+si] call cs:[int80h_table+si]
jmp 1f jmp 1f
0: 0:
mov ax, -1 mov ax, -1
@@ -174,10 +175,8 @@ int80h:
pop bp pop bp
pop di pop di
pop si pop si
pop bx
iret iret
.section .rodata.int80h .section .rodata.int80h
int80h_table: int80h_table:
.word offset copy # 0x00 .word offset copy # 0x00
@@ -185,5 +184,8 @@ int80h_table:
.word offset writesector # 0x02 .word offset writesector # 0x02
.word offset formattrack # 0x03 .word offset formattrack # 0x03
.word offset readfile # 0x04 .word offset readfile # 0x04
.word offset recvpara # 0x05
.word offset sendpara # 0x06
.word offset xferpara # 0x07
int80h_entries = . - int80h_table int80h_entries = . - int80h_table

126
polmon.cc
View File

@@ -1,5 +1,6 @@
#include <cstdint> #include <cstdint>
#include <cstdio> #include <cstdio>
#include <cstring>
#ifndef WOZMON #ifndef WOZMON
#define WOZMON 0 #define WOZMON 0
@@ -12,6 +13,8 @@
#define INT80H 0 #define INT80H 0
#define SHOWTITLE 0 #define SHOWTITLE 0
#define BOOTSTRAP 0 #define BOOTSTRAP 0
#define LAUNCH 0
#define CTRLBREAK 0
#endif // WOZMON #endif // WOZMON
#ifndef BACKSPACE #ifndef BACKSPACE
@@ -38,6 +41,14 @@
#define BOOTSTRAP 1 #define BOOTSTRAP 1
#endif #endif
#ifndef LAUNCH
#define LAUNCH 1
#endif
#ifndef CTRLBREAK
#define CTRLBREAK 1
#endif
namespace { namespace {
#if WOZMON #if WOZMON
@@ -213,6 +224,97 @@ void Status(uint8_t status) {
: "ax", "bh", "dx", "cx", "di", "cc"); : "ax", "bh", "dx", "cx", "di", "cc");
} }
char toupper(char c) {
if (c >= 'a' && c <= 'z') {
return c - ('a' - 'A');
}
return c;
}
void tofatname(const char* name, char* fatname) {
for (int i = 0; i < 11; i++) {
if (*name == 0 || *name == '.') {
fatname[i] = ' ';
} else {
fatname[i] = toupper(*name++);
}
if (i == 7 && *name == '.') {
name++;
}
}
}
void LaunchFile(const char* name) {
constexpr uint16_t kSegment = 0x200;
constexpr uint16_t kAddress = 0x100;
constexpr uint16_t kHeaderAddress = (kSegment << 4);
constexpr uint16_t kFlatAddress = (kSegment << 4) + kAddress;
constexpr uint8_t kTrampoline[] = { 0xe8, 0xfd, 0x00, 0xcb };
char fatname[11];
tofatname(name, fatname);
auto* ptr = reinterpret_cast<uint8_t*>(kHeaderAddress);
memcpy(ptr, kTrampoline, sizeof(kTrampoline));
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"
"cli \n\t"
"mov %%ax, %%ss \n\t"
"mov %3, %%ax \n\t"
"xchg %%ax, %%sp \n\t"
"sti \n\t"
"push %%ax \n\t"
"lcall %2,$0 \n\t"
"xor %%ax, %%ax \n\t"
"mov %%ax, %%ds \n\t"
"mov %%ax, %%es \n\t"
"cli \n\t"
"pop %%sp \n\t"
"mov %%ax, %%ss \n\t"
"sti"
:: "rmi"(fatname),
"rmi"(kFlatAddress), "i"(kSegment), "i"(kHeaderAddress)
: "ax", "bx", "cx", "dx", "memory");
}
#if CTRLBREAK
constexpr uint16_t kCtrlBreakVector = (0x1b * 4);
extern "C" void cbreak();
asm(" .section .text.cbreak \n"
"cbreak: \n"
" xor %ax, %ax \n"
" mov %ds, %ax \n"
" cli \n"
" mov %ss, %ax \n"
" mov $0x2000, %sp \n"
" sti \n"
" pushf \n"
" push %ax \n"
" mov $0x1000, %ax \n"
" push %ax \n"
" mov $0x20, %al \n"
" out %al, $0x20 \n"
" iret \n");
void InstallCtrlBreak() {
auto vec = reinterpret_cast<void (**)()>(kCtrlBreakVector);
vec[0] = cbreak;
vec[1] = 0;
}
#endif // CTRLBREAK
bool ParseCommand(const char* buf, uint16_t& cur_addr, uint16_t& cur_seg) { bool ParseCommand(const char* buf, uint16_t& cur_addr, uint16_t& cur_seg) {
bool dump = true; bool dump = true;
for (const char* ptr = buf; *ptr;) { for (const char* ptr = buf; *ptr;) {
@@ -259,7 +361,20 @@ bool ParseCommand(const char* buf, uint16_t& cur_addr, uint16_t& cur_seg) {
dump = false; dump = false;
ClearScreen(); ClearScreen();
ptr++; ptr++;
#endif #endif // CLEARSCREENCMD
#if LAUNCH
} else if (*ptr == 'r') {
dump = false;
ptr++;
while (*ptr == ' ') {
ptr++;
}
int l = 0;
for (; ptr[l]; l++) {
}
LaunchFile(ptr);
ptr += l;
#endif // LAUNCH
} else if (*ptr == 'w') { } else if (*ptr == 'w') {
dump = false; dump = false;
uint16_t addr = cur_addr; uint16_t addr = cur_addr;
@@ -296,7 +411,7 @@ void polmon() {
ClearScreen(); ClearScreen();
#if SHOWTITLE #if SHOWTITLE
puts("PolMon 0.2\r\n"); puts("PolMon for Workgroups 3.1\r\n");
#endif // SHOWTITLE #endif // SHOWTITLE
DisplayPrompt(); DisplayPrompt();
@@ -339,7 +454,12 @@ void polmon() {
} // namespace } // namespace
int main() { polmon(); } int main() {
#if CTRLBREAK
InstallCtrlBreak();
#endif // CTRLBREAK
polmon();
}
#if BOOTSTRAP #if BOOTSTRAP
__attribute__((section(".init"), noreturn, used)) void _start() { __attribute__((section(".init"), noreturn, used)) void _start() {

10
runcomm.asm Normal file
View File

@@ -0,0 +1,10 @@
CPU 8086
mov cx, 0x100
a:
mov ah, 0x07
int 0x80
test al, al
loopnz a
b:
ret

View File

@@ -1,3 +1,6 @@
#include <stdint.h>
#include <stdlib.h>
int getchar() { int getchar() {
register char c asm("al"); register char c asm("al");
asm volatile("movb $0x00, %%ah\n\t" asm volatile("movb $0x00, %%ah\n\t"
@@ -23,3 +26,20 @@ int puts(const char* s) {
} }
return 0; return 0;
} }
void* memcpy(void* dest, const void* src, size_t n) {
uint8_t* d = dest;
const uint8_t* s = src;
for (int i = 0; i < n; i++) {
d[i] = s[i];
}
return dest;
}
void* memset(void* ptr, int val, size_t len) {
uint8_t* p = ptr;
while (len--) {
*p++ = val;
}
return ptr;
}

13
trampoline.asm Normal file
View File

@@ -0,0 +1,13 @@
CPU 8086
src equ 0xf000
dest equ 0x0600
size equ 0x0600
_start:
mov cx, size
mov si, src
mov di, dest
rep movsb
mov ax, dest
jmp ax