Skip to content

Instantly share code, notes, and snippets.

@jdryg
Created January 31, 2017 18:12
Show Gist options
  • Save jdryg/9ee78251bbc5f9be9adee0492b779fb3 to your computer and use it in GitHub Desktop.
Save jdryg/9ee78251bbc5f9be9adee0492b779fb3 to your computer and use it in GitHub Desktop.
Tiny BIOS for an i8080 system
.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