Initial commit: try make binaries
This commit is contained in:
commit
789fa1306c
29
Dockerfile
Normal file
29
Dockerfile
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
FROM ubuntu:jammy AS deps
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y software-properties-common
|
||||||
|
RUN add-apt-repository ppa:tkchia/build-ia16
|
||||||
|
RUN apt-get update && apt-get install -y gcc-ia16-elf
|
||||||
|
RUN apt-get install nasm make
|
||||||
|
|
||||||
|
|
||||||
|
FROM deps AS dev
|
||||||
|
|
||||||
|
WORKDIR /workspace
|
||||||
|
RUN adduser --home /workspace paul
|
||||||
|
USER 1000:1000
|
||||||
|
|
||||||
|
|
||||||
|
FROM deps AS build
|
||||||
|
|
||||||
|
ARG TARGET
|
||||||
|
|
||||||
|
ADD . /workspace
|
||||||
|
WORKDIR /workspace
|
||||||
|
RUN make ${TARGET}
|
||||||
|
|
||||||
|
|
||||||
|
FROM scratch AS export
|
||||||
|
|
||||||
|
ARG TARGET
|
||||||
|
|
||||||
|
COPY --from=build /workspace/${TARGET} /
|
48
Makefile
Normal file
48
Makefile
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
dev-image = 5150-dev
|
||||||
|
|
||||||
|
writefloppy.bin: writefloppy.asm
|
||||||
|
nasm writefloppy.asm -o writefloppy.bin
|
||||||
|
|
||||||
|
readfloppy.bin: readfloppy.asm
|
||||||
|
nasm readfloppy.asm -o readfloppy.bin
|
||||||
|
|
||||||
|
crc16.s: crc16.c
|
||||||
|
ia16-elf-gcc -S -Os -o crc16.s crc16.c
|
||||||
|
|
||||||
|
crc16.bin: crc16.s crt0.c 5150.ld
|
||||||
|
ia16-elf-gcc -o crc16.bin -Os -nostdlib crc16.s crt0.c
|
||||||
|
|
||||||
|
wozmon.s: wozmon.cc
|
||||||
|
ia16-elf-gcc -S -Os -o wozmon.s wozmon.cc
|
||||||
|
|
||||||
|
wozmon.bin: wozmon.s crt0.c 5150.ld
|
||||||
|
ia16-elf-gcc -o wozmon.bin -Os -nostdlib wozmon.s crt0.c
|
||||||
|
truncate -s 510 wozmon.bin
|
||||||
|
printf "\125\252" >> wozmon.bin
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean: ## Remove generated files
|
||||||
|
rm -rf wozmon.bin crc16.bin readfloppy.bin writefloppy.bin
|
||||||
|
|
||||||
|
.PHONY: dev-image
|
||||||
|
dev-image:
|
||||||
|
docker build -t $(dev-image) --target dev .
|
||||||
|
|
||||||
|
.PHONY: dev
|
||||||
|
dev: dev-image ## Launch a dev container
|
||||||
|
docker run -it --rm -v $(CURDIR):/workspace $(dev-image)
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: binaries
|
||||||
|
binaries: ## Build all binaries
|
||||||
|
docker build --build-arg TARGET=readfloppy.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=wozmon.bin -o . --target=export .
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: help
|
||||||
|
help: ## Show this help
|
||||||
|
@echo Noteworthy targets:
|
||||||
|
@egrep '^[a-zA-Z_-]+:.*?## .*$$' $(firstword $(MAKEFILE_LIST)) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
|
||||||
|
.DEFAULT_GOAL := help
|
13
README.md
Normal file
13
README.md
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
5150 stuff
|
||||||
|
==========
|
||||||
|
|
||||||
|
The binary programs here use multiple conventions (more Fun!):
|
||||||
|
- .asm files use NASM syntax and are built with `nasm xx.asm`
|
||||||
|
- .s files use GAS syntax, they are built with `ia14-elf-gcc`
|
||||||
|
|
||||||
|
The reason is uh, because you see, I did things.
|
||||||
|
|
||||||
|
The .asm came first and was copy pasta from the internet.
|
||||||
|
The .s files came from the output of `ia16-elf-gcc -S` when I couldn't be bothered to write programs in assembly but still needed to make them compatible with BASIC's *CALL* instruction.
|
||||||
|
|
||||||
|
Also the wozmon binary contains special care to make it into a boot sector (0xaa55 magic).
|
34
crc16.c
Normal file
34
crc16.c
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define kDataAddr ((uint8_t*) 0x0000)
|
||||||
|
|
||||||
|
uint16_t crc16(int data_len) {
|
||||||
|
const uint8_t* data = kDataAddr;
|
||||||
|
|
||||||
|
uint16_t crc = 0xFFFF;
|
||||||
|
for (unsigned int i = 0; i < data_len; ++i) {
|
||||||
|
uint16_t dbyte = data[i];
|
||||||
|
crc ^= dbyte << 8;
|
||||||
|
for (unsigned char j = 0; j < 8; ++j) {
|
||||||
|
uint16_t mix = crc & 0x8000;
|
||||||
|
crc = (crc << 1);
|
||||||
|
if (mix)
|
||||||
|
crc = crc ^ 0x1021;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
asm (
|
||||||
|
".global main \n"
|
||||||
|
"main: \n"
|
||||||
|
" push %bp \n"
|
||||||
|
" mov %sp, %bp \n"
|
||||||
|
" mov 6(%bp), %si \n"
|
||||||
|
" push (%si) \n"
|
||||||
|
" call crc16 \n"
|
||||||
|
" mov 8(%bp), %di \n"
|
||||||
|
" mov %ax, (%di) \n"
|
||||||
|
" pop %bp \n"
|
||||||
|
" lret $4 \n"
|
||||||
|
);
|
19
crt0.c
Normal file
19
crt0.c
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int main();
|
||||||
|
|
||||||
|
asm (
|
||||||
|
".section .init \n"
|
||||||
|
".global _start \n"
|
||||||
|
"_start: \n"
|
||||||
|
" jmp main \n"
|
||||||
|
);
|
||||||
|
|
||||||
|
void* memset(void* ptr, int val, size_t len) {
|
||||||
|
uint8_t* p = ptr;
|
||||||
|
while(len--) {
|
||||||
|
*p++ = val;
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
|
}
|
35
readfloppy.asm
Normal file
35
readfloppy.asm
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
BITS 16
|
||||||
|
|
||||||
|
org 0xff00
|
||||||
|
|
||||||
|
|
||||||
|
; actual entry point of the program, must be present
|
||||||
|
start:
|
||||||
|
|
||||||
|
; sp and all segment registers need to be saved
|
||||||
|
push bp ; and we also save bp (??)
|
||||||
|
push es
|
||||||
|
mov bp, sp ; we'll need that to access parameters
|
||||||
|
|
||||||
|
xor dx, dx ; drive 0, head 0
|
||||||
|
mov es, dx ; es = 0
|
||||||
|
|
||||||
|
mov bx, 0xf000 ; store the read sector there
|
||||||
|
mov ax, 0x0201 ; read, 1 sector
|
||||||
|
|
||||||
|
; params: head, cylinder, sector, out
|
||||||
|
mov si, [bp+14]
|
||||||
|
mov dh, [si]
|
||||||
|
mov si, [bp+12]
|
||||||
|
mov ch, [si]
|
||||||
|
mov si, [bp+10]
|
||||||
|
mov cl, [si]
|
||||||
|
|
||||||
|
int 0x13
|
||||||
|
|
||||||
|
mov si, [bp+8]
|
||||||
|
mov [si], ax
|
||||||
|
|
||||||
|
pop es
|
||||||
|
pop bp
|
||||||
|
retf 8 ; 6 is 2x the number of parameters on the stack
|
151
wozmon.cc
Normal file
151
wozmon.cc
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
#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();
|
||||||
|
}
|
35
writefloppy.asm
Normal file
35
writefloppy.asm
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
BITS 16
|
||||||
|
|
||||||
|
org 0xfc00
|
||||||
|
|
||||||
|
|
||||||
|
; actual entry point of the program, must be present
|
||||||
|
start:
|
||||||
|
|
||||||
|
; sp and all segment registers need to be saved
|
||||||
|
push bp ; and we also save bp (??)
|
||||||
|
push es
|
||||||
|
mov bp, sp ; we'll need that to access parameters
|
||||||
|
|
||||||
|
xor dx, dx ; drive 0, head 0
|
||||||
|
mov es, dx ; es = 0
|
||||||
|
|
||||||
|
mov bx, 0xf000 ; store the read sector there
|
||||||
|
mov ax, 0x0301 ; write, 1 sector
|
||||||
|
|
||||||
|
; params: head, cylinder, sector, out
|
||||||
|
mov si, [bp+14]
|
||||||
|
mov dh, [si]
|
||||||
|
mov si, [bp+12]
|
||||||
|
mov ch, [si]
|
||||||
|
mov si, [bp+10]
|
||||||
|
mov cl, [si]
|
||||||
|
|
||||||
|
int 0x13
|
||||||
|
|
||||||
|
mov si, [bp+8]
|
||||||
|
mov [si], ax
|
||||||
|
|
||||||
|
pop es
|
||||||
|
pop bp
|
||||||
|
retf 8 ; 6 is 2x the number of parameters on the stack
|
Loading…
Reference in New Issue
Block a user