Compare commits
13 Commits
becc319419
...
2bab877a7d
| Author | SHA1 | Date | |
|---|---|---|---|
| 2bab877a7d | |||
| f46b13e044 | |||
| bf16ae5646 | |||
| 3c90dd8b3d | |||
| bdb2fce4db | |||
| 9bd84390d0 | |||
| e4473e14f6 | |||
| 7bf7e863eb | |||
| ee97876115 | |||
| 9daf8d7f97 | |||
| b5b679c4e2 | |||
| c818d185ba | |||
| c45a312dd0 |
@@ -3,7 +3,7 @@ FROM ubuntu:jammy AS deps
|
|||||||
RUN apt-get update && apt-get install -y software-properties-common
|
RUN apt-get update && apt-get install -y software-properties-common
|
||||||
RUN add-apt-repository ppa:tkchia/build-ia16
|
RUN add-apt-repository ppa:tkchia/build-ia16
|
||||||
RUN apt-get update && apt-get install -y gcc-ia16-elf
|
RUN apt-get update && apt-get install -y gcc-ia16-elf
|
||||||
RUN apt-get install nasm make
|
RUN apt-get install -y nasm make mtools
|
||||||
|
|
||||||
|
|
||||||
FROM deps AS dev
|
FROM deps AS dev
|
||||||
|
|||||||
70
Makefile
70
Makefile
@@ -1,10 +1,7 @@
|
|||||||
dev-image = 5150-dev
|
dev-image = 5150-dev
|
||||||
|
|
||||||
writefloppy.bin: writefloppy.asm
|
%.bin: %.asm
|
||||||
nasm writefloppy.asm -o writefloppy.bin
|
nasm $? -o $@
|
||||||
|
|
||||||
readfloppy.bin: readfloppy.asm
|
|
||||||
nasm readfloppy.asm -o readfloppy.bin
|
|
||||||
|
|
||||||
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
|
||||||
@@ -12,17 +9,54 @@ crc16.s: crc16.c
|
|||||||
crc16.bin: crc16.s crt0.c
|
crc16.bin: crc16.s crt0.c
|
||||||
ia16-elf-gcc -o crc16.bin -Os -nostdlib crc16.s crt0.c
|
ia16-elf-gcc -o crc16.bin -Os -nostdlib crc16.s crt0.c
|
||||||
|
|
||||||
wozmon.s: wozmon.cc
|
CC = ia16-elf-gcc
|
||||||
ia16-elf-gcc -S -Os -o wozmon.s wozmon.cc
|
CXX = ia16-elf-gcc
|
||||||
|
LD = ia16-elf-gcc
|
||||||
|
CXXFLAGS = -mregparmcall -ffunction-sections -Os -flto
|
||||||
|
CFLAGS = -mregparmcall -ffunction-sections -Os -flto
|
||||||
|
LDFLAGS = -mregparmcall -Wl,--gc-sections -Os -nostdlib -flto
|
||||||
|
|
||||||
wozmon.bin: wozmon.s crt0.c
|
%.elf:
|
||||||
ia16-elf-gcc -o wozmon.bin -Os -nostdlib wozmon.s crt0.c
|
$(LD) $(LDFLAGS) $(CPPFLAGS) -o $@ $^
|
||||||
truncate -s 510 wozmon.bin
|
|
||||||
printf "\125\252" >> wozmon.bin
|
bootsectors = fat12boot.bin wozmon.bin
|
||||||
|
|
||||||
|
$(bootsectors):
|
||||||
|
ia16-elf-objcopy -O binary $? $@
|
||||||
|
truncate -s 510 $@
|
||||||
|
printf "\125\252" >> $@
|
||||||
|
|
||||||
|
fat12boot.elf: fat12boot.o fat12.o bootsect.S
|
||||||
|
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
|
||||||
|
|
||||||
|
wozmon.bin: wozmon.elf
|
||||||
|
|
||||||
|
polos.img: fat12boot.bin polmon.com
|
||||||
|
dd if=/dev/zero of=$@ bs=512 count=720
|
||||||
|
mformat -i $@ -t 40 -h 2 -s 9
|
||||||
|
mcopy -i $@ polmon.com ::/polmon.com
|
||||||
|
dd if=fat12boot.bin of=$@ conv=notrunc
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean: ## Remove generated files
|
clean: ## Remove generated files
|
||||||
rm -rf wozmon.bin crc16.bin readfloppy.bin writefloppy.bin
|
rm -rf wozmon.bin crc16.bin readfloppy.bin writefloppy.bin fat12boot.bin
|
||||||
|
|
||||||
.PHONY: dev-image
|
.PHONY: dev-image
|
||||||
dev-image:
|
dev-image:
|
||||||
@@ -39,6 +73,18 @@ binaries: ## Build all binaries
|
|||||||
docker build --build-arg TARGET=writefloppy.bin -o . --target=export .
|
docker build --build-arg TARGET=writefloppy.bin -o . --target=export .
|
||||||
docker build --build-arg TARGET=crc16.bin -o . --target=export .
|
docker build --build-arg TARGET=crc16.bin -o . --target=export .
|
||||||
docker build --build-arg TARGET=wozmon.bin -o . --target=export .
|
docker build --build-arg TARGET=wozmon.bin -o . --target=export .
|
||||||
|
docker build --build-arg TARGET=hello.bin -o . --target=export .
|
||||||
|
docker build --build-arg TARGET=copy.bin -o . --target=export .
|
||||||
|
docker build --build-arg TARGET=call.bin -o . --target=export .
|
||||||
|
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 .
|
||||||
|
|
||||||
|
.PHONY: floppy
|
||||||
|
floppy: ## Make a bootable floppy image
|
||||||
|
docker build --build-arg TARGET=polos.img -o . --target=export .
|
||||||
|
|
||||||
|
|
||||||
.PHONY: help
|
.PHONY: help
|
||||||
|
|||||||
11
add.asm
Normal file
11
add.asm
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
BITS 16
|
||||||
|
CPU 8086
|
||||||
|
|
||||||
|
_start:
|
||||||
|
mov bp, sp
|
||||||
|
mov si, [bp+6]
|
||||||
|
mov ax, [si]
|
||||||
|
mov si, [bp+4]
|
||||||
|
mov dx, [si]
|
||||||
|
sub ax, dx
|
||||||
|
retf 4
|
||||||
@@ -119,6 +119,22 @@ void sendShiftCode(int code) {
|
|||||||
sendCode(42 | 0x80);
|
sendCode(42 | 0x80);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sendCtrlAltDel() {
|
||||||
|
sendCode(0x1d); // ctrl
|
||||||
|
sendCode(0x38); // alt
|
||||||
|
sendCode(0x53); // del
|
||||||
|
sendCode(0x53 | 0x80);
|
||||||
|
sendCode(0x38 | 0x80);
|
||||||
|
sendCode(0x1d | 0x80);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendCtrlBreak() {
|
||||||
|
sendCode(0x1d); // ctrl
|
||||||
|
sendCode(0x46); // break
|
||||||
|
sendCode(0x46 | 0x80);
|
||||||
|
sendCode(0x1d | 0x80);
|
||||||
|
}
|
||||||
|
|
||||||
void sendAsciiChar(int c) {
|
void sendAsciiChar(int c) {
|
||||||
if (c >= 'a' && c <= 'z') {
|
if (c >= 'a' && c <= 'z') {
|
||||||
return sendNormalCode(kLetterCodes[c - 'a']);
|
return sendNormalCode(kLetterCodes[c - 'a']);
|
||||||
@@ -160,6 +176,9 @@ void sendAsciiChar(int c) {
|
|||||||
case '<': return sendShiftCode(51);
|
case '<': return sendShiftCode(51);
|
||||||
case '>': return sendShiftCode(52);
|
case '>': return sendShiftCode(52);
|
||||||
case '?': return sendShiftCode(53);
|
case '?': return sendShiftCode(53);
|
||||||
|
|
||||||
|
case 0: return sendCtrlAltDel();
|
||||||
|
case 27: return sendCtrlBreak(); // escape
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
29
bootsect.S
Normal file
29
bootsect.S
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
.arch i8086,jumps
|
||||||
|
.code16
|
||||||
|
|
||||||
|
.section .init
|
||||||
|
.global _start
|
||||||
|
_start:
|
||||||
|
#ifndef NOBPB
|
||||||
|
jmp l0
|
||||||
|
nop
|
||||||
|
|
||||||
|
.ascii "IBM 3.1"
|
||||||
|
bpb_bytespersect: .word 512
|
||||||
|
bpb_sectspercluster: .byte 2
|
||||||
|
bpb_reservedsects: .word 1
|
||||||
|
bbp_fats: .byte 2
|
||||||
|
bpb_rootentries: .word 112
|
||||||
|
bpb_localsectors: .word 720
|
||||||
|
bpb_mediadescr: .byte 0xfd
|
||||||
|
bpb_sectsperfat: .word 2
|
||||||
|
|
||||||
|
l0:
|
||||||
|
#endif // NOBPB
|
||||||
|
cli
|
||||||
|
xor %ax, %ax
|
||||||
|
mov %ax, %ds
|
||||||
|
mov %ax, %ss
|
||||||
|
mov $0x7c00, %sp
|
||||||
|
sti
|
||||||
|
jmp main
|
||||||
20
bootsect.ld
Normal file
20
bootsect.ld
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
SECTIONS {
|
||||||
|
. = 0x7c00;
|
||||||
|
|
||||||
|
.text : {
|
||||||
|
KEEP(*(.init))
|
||||||
|
*(.text*)
|
||||||
|
}
|
||||||
|
|
||||||
|
.rodata : {
|
||||||
|
*(.rodata*)
|
||||||
|
}
|
||||||
|
|
||||||
|
.bss (NOLOAD) : {
|
||||||
|
* (.bss)
|
||||||
|
}
|
||||||
|
|
||||||
|
.data : {
|
||||||
|
*(.data)
|
||||||
|
}
|
||||||
|
}
|
||||||
35
call.asm
Normal file
35
call.asm
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
BITS 16
|
||||||
|
CPU 8086
|
||||||
|
|
||||||
|
org 0x7300
|
||||||
|
|
||||||
|
PARAMS equ 0x7380
|
||||||
|
; dw 0: target offset
|
||||||
|
; dw 2: target segment
|
||||||
|
; dw 4: number of params
|
||||||
|
; dw 6: param 0
|
||||||
|
; ...
|
||||||
|
|
||||||
|
_start:
|
||||||
|
push bx
|
||||||
|
push si
|
||||||
|
push di
|
||||||
|
push bp
|
||||||
|
mov si, PARAMS
|
||||||
|
mov bx, 0x6
|
||||||
|
xor cx, cx
|
||||||
|
a1:
|
||||||
|
cmp cx, [es:si+4]
|
||||||
|
jge a2
|
||||||
|
lea ax, [es:si+bx]
|
||||||
|
push ax
|
||||||
|
add bl, 2
|
||||||
|
inc cl
|
||||||
|
jmp a1
|
||||||
|
a2:
|
||||||
|
call far [es:si]
|
||||||
|
pop bp
|
||||||
|
pop di
|
||||||
|
pop si
|
||||||
|
pop bx
|
||||||
|
ret
|
||||||
19
copy.asm
Normal file
19
copy.asm
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
BITS 16
|
||||||
|
CPU 8086
|
||||||
|
|
||||||
|
main:
|
||||||
|
mov bp, sp
|
||||||
|
mov si, [bp+4]
|
||||||
|
mov cx, [si]
|
||||||
|
mov si, [bp+6]
|
||||||
|
mov di, [si]
|
||||||
|
mov si, [bp+8]
|
||||||
|
mov si, [si]
|
||||||
|
push ds
|
||||||
|
push es
|
||||||
|
pop ds
|
||||||
|
cld
|
||||||
|
rep movsw
|
||||||
|
pop ds
|
||||||
|
|
||||||
|
retf 6
|
||||||
5
crc16.c
5
crc16.c
@@ -24,10 +24,11 @@ asm (
|
|||||||
"main: \n"
|
"main: \n"
|
||||||
" push %bp \n"
|
" push %bp \n"
|
||||||
" mov %sp, %bp \n"
|
" mov %sp, %bp \n"
|
||||||
" mov 6(%bp), %si \n"
|
" mov 8(%bp), %si \n"
|
||||||
" push (%si) \n"
|
" push (%si) \n"
|
||||||
" call crc16 \n"
|
" call crc16 \n"
|
||||||
" mov 8(%bp), %di \n"
|
" add $0x2, %sp \n"
|
||||||
|
" mov 6(%bp), %di \n"
|
||||||
" mov %ax, (%di) \n"
|
" mov %ax, (%di) \n"
|
||||||
" pop %bp \n"
|
" pop %bp \n"
|
||||||
" lret $4 \n"
|
" lret $4 \n"
|
||||||
|
|||||||
52
crc16.s
Normal file
52
crc16.s
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
.arch i8086,jumps
|
||||||
|
.code16
|
||||||
|
.att_syntax prefix
|
||||||
|
#NO_APP
|
||||||
|
#APP
|
||||||
|
.global main
|
||||||
|
main:
|
||||||
|
push %bp
|
||||||
|
mov %sp, %bp
|
||||||
|
mov 8(%bp), %si
|
||||||
|
push (%si)
|
||||||
|
call crc16
|
||||||
|
add $0x2, %sp
|
||||||
|
mov 6(%bp), %di
|
||||||
|
mov %ax, (%di)
|
||||||
|
pop %bp
|
||||||
|
lret $4
|
||||||
|
|
||||||
|
#NO_APP
|
||||||
|
.text
|
||||||
|
.global crc16
|
||||||
|
.type crc16, @function
|
||||||
|
crc16:
|
||||||
|
pushw %bp
|
||||||
|
movw %sp, %bp
|
||||||
|
xorw %bx, %bx
|
||||||
|
movw $-1, %ax
|
||||||
|
.L2:
|
||||||
|
cmpw 4(%bp), %bx
|
||||||
|
jne .L5
|
||||||
|
popw %bp
|
||||||
|
ret
|
||||||
|
.L5:
|
||||||
|
movb %cs:(%bx), %dl
|
||||||
|
movb $8, %cl
|
||||||
|
shlw %cl, %dx
|
||||||
|
xorw %dx, %ax
|
||||||
|
movb %cl, %dl
|
||||||
|
.L4:
|
||||||
|
movw %ax, %cx
|
||||||
|
shlw $1, %cx
|
||||||
|
testw %ax, %ax
|
||||||
|
xchgw %ax, %cx
|
||||||
|
jge .L3
|
||||||
|
xorw $4129, %ax
|
||||||
|
.L3:
|
||||||
|
decb %dl
|
||||||
|
jne .L4
|
||||||
|
incw %bx
|
||||||
|
jmp .L2
|
||||||
|
.size crc16, .-crc16
|
||||||
|
.ident "GCC: (GNU) 6.3.0"
|
||||||
12
crt0.c
12
crt0.c
@@ -6,8 +6,16 @@ int main();
|
|||||||
asm (
|
asm (
|
||||||
".section .init \n"
|
".section .init \n"
|
||||||
".global _start \n"
|
".global _start \n"
|
||||||
"_start: \n"
|
"_start: \n\t"
|
||||||
" jmp main \n"
|
"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) {
|
void* memset(void* ptr, int val, size_t len) {
|
||||||
|
|||||||
66
debug.asm
Normal file
66
debug.asm
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
BITS 16
|
||||||
|
CPU 8086
|
||||||
|
|
||||||
|
org 0x7000
|
||||||
|
|
||||||
|
_start:
|
||||||
|
jmp main
|
||||||
|
|
||||||
|
hexdigits:
|
||||||
|
db "0123456789abcdef"
|
||||||
|
|
||||||
|
putc:
|
||||||
|
push bx
|
||||||
|
push bp
|
||||||
|
mov ah, 0x0e
|
||||||
|
xor bh, bh
|
||||||
|
int 0x10
|
||||||
|
pop bp
|
||||||
|
pop bx
|
||||||
|
ret
|
||||||
|
|
||||||
|
printnibble:
|
||||||
|
push si
|
||||||
|
push bx
|
||||||
|
mov si, hexdigits
|
||||||
|
xor bh, bh
|
||||||
|
mov bl, al
|
||||||
|
and bl, 0xf
|
||||||
|
mov al, cs:[si+bx]
|
||||||
|
call putc
|
||||||
|
pop bx
|
||||||
|
pop si
|
||||||
|
ret
|
||||||
|
|
||||||
|
printi8:
|
||||||
|
push bx
|
||||||
|
mov bl, al
|
||||||
|
mov cl, 4
|
||||||
|
shr al, cl
|
||||||
|
call printnibble
|
||||||
|
mov al, bl
|
||||||
|
call printnibble
|
||||||
|
pop bx
|
||||||
|
ret
|
||||||
|
|
||||||
|
printi16:
|
||||||
|
push bx
|
||||||
|
mov bx, ax
|
||||||
|
mov al, ah
|
||||||
|
call printi8
|
||||||
|
mov al, bl
|
||||||
|
call printi8
|
||||||
|
pop bx
|
||||||
|
ret
|
||||||
|
|
||||||
|
main:
|
||||||
|
mov bp, sp
|
||||||
|
mov si, [bp+4]
|
||||||
|
mov si, [si]
|
||||||
|
mov ax, [si]
|
||||||
|
call printi16
|
||||||
|
mov al, 0x0d
|
||||||
|
call putc
|
||||||
|
mov al, 0x0a
|
||||||
|
call putc
|
||||||
|
retf 2
|
||||||
25
dosdbt.asm
Normal file
25
dosdbt.asm
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
BITS 16
|
||||||
|
CPU 8086
|
||||||
|
|
||||||
|
diskpointer equ 0x1e*4
|
||||||
|
dbtbase equ 0x100
|
||||||
|
|
||||||
|
_start:
|
||||||
|
jmp main
|
||||||
|
|
||||||
|
main:
|
||||||
|
push ds
|
||||||
|
mov si, diskpointer
|
||||||
|
lds si, [si]
|
||||||
|
mov di, dbtbase
|
||||||
|
mov cx, 0x0a
|
||||||
|
cld
|
||||||
|
rep movsb
|
||||||
|
pop ds
|
||||||
|
mov al, 9 ; sectors per track
|
||||||
|
mov di, dbtbase
|
||||||
|
mov [di+4], al
|
||||||
|
mov di, diskpointer
|
||||||
|
mov [di], word dbtbase
|
||||||
|
mov [di+2], ds
|
||||||
|
retf
|
||||||
138
fat12.c
Normal file
138
fat12.c
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define kSectorsPerCluster 2
|
||||||
|
#define kSectorsPerTrack 9
|
||||||
|
#define kHeads 2
|
||||||
|
#define kFatSizeSectors 2
|
||||||
|
#define kRootDirSizeSectors 7
|
||||||
|
#define kDataRegionStartSector (1 + kFatSizeSectors*2 + kRootDirSizeSectors)
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char name[8];
|
||||||
|
char ext[3];
|
||||||
|
uint8_t attr;
|
||||||
|
|
||||||
|
uint8_t dontcare[14];
|
||||||
|
|
||||||
|
uint16_t cluster;
|
||||||
|
uint32_t size;
|
||||||
|
} direntry;
|
||||||
|
|
||||||
|
static uint8_t* gFat;
|
||||||
|
static direntry* gRootdir;
|
||||||
|
|
||||||
|
|
||||||
|
static int readsector(int c, int h, int s, uint8_t* addr) {
|
||||||
|
register uint8_t* dest asm ("bx") = addr;
|
||||||
|
register uint8_t nsects asm ("al") = 1;
|
||||||
|
register uint8_t func asm ("ah") = 0x02;
|
||||||
|
register uint8_t sect asm ("cl") = s;
|
||||||
|
register uint8_t cyl asm ("ch") = c;
|
||||||
|
register uint8_t head asm ("dh") = h;
|
||||||
|
register uint8_t drive asm ("dl") = 0;
|
||||||
|
register uint16_t seg asm ("es") = 0;
|
||||||
|
|
||||||
|
register uint8_t ret asm("ah");
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
asm volatile ("int $0x13"
|
||||||
|
: "=r" (ret)
|
||||||
|
: "r" (dest), "r" (nsects), "r" (func), "r" (sect),
|
||||||
|
"r" (cyl), "r" (head), "r" (drive), "r" (seg));
|
||||||
|
if (ret == 0x80) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int readcluster(int cluster) {
|
||||||
|
int offs = cluster * 3 / 2;
|
||||||
|
if (cluster % 2) {
|
||||||
|
// high nibble is lsb + whole byte
|
||||||
|
return ((gFat[offs] & 0xf0) >> 4) + (gFat[offs+1] << 4);
|
||||||
|
} else {
|
||||||
|
return gFat[offs] + ((gFat[offs+1] & 0x0f) << 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cluster2chs(int cluster, int* c, int* h, int* s) {
|
||||||
|
int logicalsector = kDataRegionStartSector + (cluster - 2) * kSectorsPerCluster;
|
||||||
|
*s = (logicalsector % kSectorsPerTrack) + 1;
|
||||||
|
*h = (logicalsector / kSectorsPerTrack) % kHeads;
|
||||||
|
*c = logicalsector / (kHeads * kSectorsPerTrack);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int strncmp(const char* s1, const char *s2, size_t len) {
|
||||||
|
for (int i = 0; i < len && s1[i]; i++) {
|
||||||
|
if (s1[i] != s2[i]) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// XXX: really we should return 0 only if *s1 == *s2 here too
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int loadfile(direntry* entry, void* addr) {
|
||||||
|
int cluster = entry->cluster;
|
||||||
|
for (int i = 0; i < entry->size; i+=1024) {
|
||||||
|
int c, h, s;
|
||||||
|
cluster2chs(cluster, &c, &h, &s);
|
||||||
|
if (readsector(c, h, s, addr + i)) {
|
||||||
|
return -5;
|
||||||
|
}
|
||||||
|
s++;
|
||||||
|
if (s > 9) {
|
||||||
|
s = 1;
|
||||||
|
h++;
|
||||||
|
}
|
||||||
|
if (h > 1) {
|
||||||
|
h = 0;
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
if (readsector(c, h, s, addr + i + 512)) {
|
||||||
|
return -5;
|
||||||
|
};
|
||||||
|
cluster = readcluster(cluster);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fat12_init(void* fat_addr, void* rootdir_addr) {
|
||||||
|
if (readsector(0, 0, 2, fat_addr)) {
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
if (readsector(0, 0, 6, rootdir_addr)) {
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
|
||||||
|
gFat = fat_addr;
|
||||||
|
gRootdir = rootdir_addr;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fat12_readfile(const char* name, void* addr) {
|
||||||
|
direntry* file = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
direntry* entry = &gRootdir[i];
|
||||||
|
if (entry->name[0] == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!strncmp(entry->name, name, 11)) {
|
||||||
|
file = entry;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!file) {
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
|
||||||
|
return loadfile(file, addr);
|
||||||
|
}
|
||||||
15
fat12.h
Normal file
15
fat12.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Arguments:
|
||||||
|
* - fat_addr: 1 KiB
|
||||||
|
* - rootdir_addr: 3.5 KiB
|
||||||
|
*/
|
||||||
|
int fat12_init(void* fat_addr, void* rootdir_addr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns:
|
||||||
|
* -4 if file is not found
|
||||||
|
* -5 if there is a disk error
|
||||||
|
*/
|
||||||
|
int fat12_readfile(const char* name, void* addr);
|
||||||
59
fat12boot.c
Normal file
59
fat12boot.c
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "fat12.h"
|
||||||
|
|
||||||
|
#define kPolmonAddress ((void*)0x0600)
|
||||||
|
#define kFatAddress ((void*)0x1000)
|
||||||
|
#define kRootDirAddress ((void*)0x1200)
|
||||||
|
|
||||||
|
|
||||||
|
static int putchar(int c) {
|
||||||
|
register uint8_t khar asm ("al") = c;
|
||||||
|
register uint8_t func asm ("ah") = 0x0e;
|
||||||
|
register uint8_t page asm ("bh") = 0;
|
||||||
|
|
||||||
|
asm volatile ("int $0x10"
|
||||||
|
:: "r" (khar), "r" (func), "r" (page)
|
||||||
|
: "bp");
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int puts(const char* msg) {
|
||||||
|
while (*msg) {
|
||||||
|
putchar(*msg++);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((noreturn))
|
||||||
|
static void die(const char* msg) {
|
||||||
|
puts(msg);
|
||||||
|
while (1) {
|
||||||
|
}
|
||||||
|
__builtin_unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((noreturn))
|
||||||
|
static void jump(void* addr) {
|
||||||
|
asm volatile ("ljmp $0,%0" :: "i"(addr));
|
||||||
|
__builtin_unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((noreturn))
|
||||||
|
static void loadpolmon() {
|
||||||
|
if (fat12_init(kFatAddress, kRootDirAddress)) {
|
||||||
|
die("fi");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fat12_readfile("POLMON COM", kPolmonAddress)) {
|
||||||
|
die("pnf");
|
||||||
|
}
|
||||||
|
|
||||||
|
jump(kPolmonAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
loadpolmon();
|
||||||
|
}
|
||||||
20
flat0600.ld
Normal file
20
flat0600.ld
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
SECTIONS {
|
||||||
|
. = 0x0600;
|
||||||
|
|
||||||
|
.text : {
|
||||||
|
KEEP(*(.init))
|
||||||
|
*(.text*)
|
||||||
|
}
|
||||||
|
|
||||||
|
.rodata : {
|
||||||
|
*(.rodata*)
|
||||||
|
}
|
||||||
|
|
||||||
|
.bss (NOLOAD) : {
|
||||||
|
* (.bss)
|
||||||
|
}
|
||||||
|
|
||||||
|
.data : {
|
||||||
|
*(.data)
|
||||||
|
}
|
||||||
|
}
|
||||||
63
format.asm
Normal file
63
format.asm
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
BITS 16
|
||||||
|
CPU 8086
|
||||||
|
|
||||||
|
buffer equ 0xe000
|
||||||
|
sectors equ 9
|
||||||
|
|
||||||
|
|
||||||
|
_start:
|
||||||
|
jmp main
|
||||||
|
|
||||||
|
formattrack:
|
||||||
|
push bp
|
||||||
|
push bx
|
||||||
|
push di
|
||||||
|
mov bp, sp
|
||||||
|
push ax ; track
|
||||||
|
push cx ; head
|
||||||
|
|
||||||
|
mov bx, buffer
|
||||||
|
xor cx, cx
|
||||||
|
l0:
|
||||||
|
cmp cl, sectors
|
||||||
|
jnl l1
|
||||||
|
mov di, cx
|
||||||
|
and di, 0x0f ; max 15 sectors
|
||||||
|
shl di, 1
|
||||||
|
shl di, 1 ; di = cl*4
|
||||||
|
lea di, [bx+di]
|
||||||
|
mov al, [bp-2] ; track number
|
||||||
|
mov [di+0], al
|
||||||
|
mov al, [bp-4] ; head number
|
||||||
|
mov [di+1], al
|
||||||
|
mov al, cl ; sector number
|
||||||
|
inc al
|
||||||
|
mov [di+2], al
|
||||||
|
mov [di+3], byte 0x02 ; 512 bytes per sector
|
||||||
|
inc cl
|
||||||
|
jmp l0
|
||||||
|
|
||||||
|
l1:
|
||||||
|
mov ah, 0x05 ; format track
|
||||||
|
mov al, sectors
|
||||||
|
mov dl, 0 ; first drive
|
||||||
|
mov dh, [bp-4] ; head number
|
||||||
|
mov ch, [bp-2] ; track number
|
||||||
|
mov cl, 1 ; sector number (first sector?)
|
||||||
|
int 0x13
|
||||||
|
add sp, 4
|
||||||
|
pop di
|
||||||
|
pop bx
|
||||||
|
pop bp
|
||||||
|
ret
|
||||||
|
|
||||||
|
main:
|
||||||
|
mov bp, sp
|
||||||
|
mov si, [bp+8]
|
||||||
|
mov ax, [si]
|
||||||
|
mov si, [bp+6]
|
||||||
|
mov cx, [si]
|
||||||
|
call formattrack
|
||||||
|
mov si, [bp+4]
|
||||||
|
mov [si], ax
|
||||||
|
retf 6
|
||||||
25
hello.asm
Normal file
25
hello.asm
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
BITS 16
|
||||||
|
CPU 8086
|
||||||
|
|
||||||
|
org 0x7200
|
||||||
|
|
||||||
|
_start:
|
||||||
|
jmp main
|
||||||
|
|
||||||
|
hw:
|
||||||
|
db "Hello, world!", 0x0d, 0x0a, 0
|
||||||
|
|
||||||
|
main:
|
||||||
|
xor bx, bx
|
||||||
|
mov si, hw
|
||||||
|
printloop:
|
||||||
|
mov al, cs:[si]
|
||||||
|
test al, al
|
||||||
|
jz done
|
||||||
|
mov ah, 0x0e
|
||||||
|
int 0x10
|
||||||
|
inc si
|
||||||
|
jmp printloop
|
||||||
|
|
||||||
|
done:
|
||||||
|
retf
|
||||||
384
polmon.cc
Normal file
384
polmon.cc
Normal 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
|
||||||
@@ -1,9 +1,6 @@
|
|||||||
BITS 16
|
BITS 16
|
||||||
|
CPU 8086
|
||||||
|
|
||||||
org 0xff00
|
|
||||||
|
|
||||||
|
|
||||||
; actual entry point of the program, must be present
|
|
||||||
start:
|
start:
|
||||||
|
|
||||||
; sp and all segment registers need to be saved
|
; sp and all segment registers need to be saved
|
||||||
@@ -32,4 +29,4 @@ mov [si], ax
|
|||||||
|
|
||||||
pop es
|
pop es
|
||||||
pop bp
|
pop bp
|
||||||
retf 8 ; 6 is 2x the number of parameters on the stack
|
retf 8 ; 2x the number of parameters on the stack
|
||||||
|
|||||||
151
wozmon.cc
151
wozmon.cc
@@ -1,151 +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] = {};
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
261
wozmon.s
261
wozmon.s
@@ -1,261 +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 %sp, %bp
|
|
||||||
subw $76, %sp
|
|
||||||
leaw -64(%bp), %di
|
|
||||||
movw $64, %ax
|
|
||||||
pushw %ax
|
|
||||||
xorw %ax, %ax
|
|
||||||
movw %ax, %es
|
|
||||||
pushw %ax
|
|
||||||
pushw %di
|
|
||||||
call memset
|
|
||||||
addw $6, %sp
|
|
||||||
movw %es, %si
|
|
||||||
movw %es, -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"
|
|
||||||
@@ -1,9 +1,6 @@
|
|||||||
BITS 16
|
BITS 16
|
||||||
|
CPU 8086
|
||||||
|
|
||||||
org 0xfc00
|
|
||||||
|
|
||||||
|
|
||||||
; actual entry point of the program, must be present
|
|
||||||
start:
|
start:
|
||||||
|
|
||||||
; sp and all segment registers need to be saved
|
; sp and all segment registers need to be saved
|
||||||
@@ -32,4 +29,4 @@ mov [si], ax
|
|||||||
|
|
||||||
pop es
|
pop es
|
||||||
pop bp
|
pop bp
|
||||||
retf 8 ; 6 is 2x the number of parameters on the stack
|
retf 8 ; 2x the number of parameters on the stack
|
||||||
|
|||||||
Reference in New Issue
Block a user