Created
January 31, 2017 18:12
-
-
Save jdryg/9ee78251bbc5f9be9adee0492b779fb3 to your computer and use it in GitHub Desktop.
Tiny BIOS for an i8080 system
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.ORG 0x0000 | |
LF EQU 0x0A | |
CR EQU 0x0D | |
EOS EQU 0x24; '$' | |
STACK EQU 0x80FF | |
TERMINAL EQU 0xF000 | |
CARET_ADDR EQU 0xEFFE | |
JMP boot ; | |
NOP ; | |
NOP ; | |
JMP syscall ; | |
BOOT: | |
EI ; Enable interrupts | |
XRA A ; clear A and reset flags | |
LXI SP,STACK ; set stack pointer | |
CALL cls | |
CALL setup_caret | |
MVI C, 0x02 | |
MVI E, LF | |
CALL syscall | |
MVI C, 0x09 | |
LXI D, BIOS_VERSION_STR | |
CALL syscall | |
MVI C, 0x09 | |
LXI D, CPUDIAG_STR | |
CALL syscall | |
CALL 0x0100 | |
HLT | |
CLS: | |
PUSH PSW | |
PUSH B | |
LXI H,TERMINAL ; Start of video memory | |
MVI A,0xA0 ; # characters on screen / 16 (== chars per iteration) | |
MVI B,0x20 ; ' ' character | |
CLS_NEXT_BATCH16: | |
MOV M,B | |
INX H | |
MOV M,B | |
INX H | |
MOV M,B | |
INX H | |
MOV M,B | |
INX H | |
MOV M,B | |
INX H | |
MOV M,B | |
INX H | |
MOV M,B | |
INX H | |
MOV M,B | |
INX H | |
MOV M,B | |
INX H | |
MOV M,B | |
INX H | |
MOV M,B | |
INX H | |
MOV M,B | |
INX H | |
MOV M,B | |
INX H | |
MOV M,B | |
INX H | |
MOV M,B | |
INX H | |
MOV M,B | |
INX H | |
DCR A | |
JNZ cls_next_batch16 | |
POP B | |
POP PSW | |
RET | |
;--------------------- | |
; setup_caret() | |
; | |
; Set current caret address to point to character (0,0) | |
; of the terminal. | |
;--------------------- | |
SETUP_CARET: | |
PUSH H | |
LXI H, TERMINAL; | |
SHLD CARET_ADDR | |
POP H | |
RET | |
;-------------------------- | |
; syscall(C=func, ...) | |
;-------------------------- | |
SYSCALL: | |
PUSH PSW | |
MOV A,C | |
CPI 0x02 | |
JZ SYSCALL_PUTC | |
CPI 0x09 | |
JZ SYSCALL_PRINT_STR | |
SYSCALL_END: | |
POP PSW ; | |
RET ; | |
SYSCALL_PUTC: | |
LHLD CARET_ADDR; | |
MOV A, E | |
CPI 0x0D ; CR | |
JZ SYSCALL_PUTC_CR | |
CPI 0x0A ; LF | |
JZ SYSCALL_PUTC_LF | |
MOV M, A | |
INX H | |
JMP SYSCALL_PRINT_END | |
SYSCALL_PUTC_CR: | |
MOV A, L; | |
ANI 0xC0 | |
MOV L, A; | |
JMP SYSCALL_PRINT_END | |
SYSCALL_PUTC_LF: | |
MOV A, L; | |
ADI 0x40 | |
MOV L, A; | |
MOV A, H; | |
ACI 0x00; | |
MOV H, A; | |
JMP SYSCALL_PRINT_END | |
SYSCALL_PRINT_STR: | |
LHLD CARET_ADDR; HL = Address of next character on screen. | |
SYSCALL_PRINT_STR_NEXT_CHAR: | |
LDAX D | |
INX D | |
CPI 0x24 ; '$' | |
JZ SYSCALL_PRINT_END | |
CPI 0x0D ; CR | |
JZ SYSCALL_PRINT_STR_CR | |
CPI 0x0A ; LF | |
JZ SYSCALL_PRINT_STR_LF | |
; Print the character | |
MOV M, A | |
INX H | |
JMP SYSCALL_PRINT_STR_NEXT_CHAR | |
SYSCALL_PRINT_STR_CR: | |
; Return to the beginning of the current line. | |
; Since there are 64 characters per line and TERMINAL address is a | |
; multiple of 64, chopping the lower 6 bits of L does the job. | |
MOV A, L; | |
ANI 0xC0 | |
MOV L, A; | |
JMP SYSCALL_PRINT_STR_NEXT_CHAR | |
SYSCALL_PRINT_STR_LF: | |
; Move 1 line down. | |
; There are 64 characters per line, so HL = HL + 64 | |
; NOTE: Can be done with DAD but needs a register pair. | |
MOV A, L; | |
ADI 0x40 | |
MOV L, A; | |
MOV A, H; | |
ACI 0x00; | |
MOV H, A; | |
JMP SYSCALL_PRINT_STR_NEXT_CHAR | |
SYSCALL_PRINT_END: | |
; Store current caret address. | |
SHLD CARET_ADDR; | |
JMP SYSCALL_END; | |
BIOS_VERSION_STR: | |
DB ' i8080 BIOS v1.0',CR,LF,EOS | |
CPUDIAG_STR: | |
DB ' Executing CPUDiag...',CR,LF,EOS | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment