Created
October 28, 2015 00:15
-
-
Save ramblingenzyme/f79fd1adb7e7dac01477 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
; demo operating system | |
; | |
; system calls | |
; exit = os executes halt instruction! | |
; read = os will under interrupts read a line from keyboard | |
; returning when a newline character read | |
; write = os will under interrupts write a line to teletype | |
; returning when line all written (nul character at end) | |
; os will use "wait" when it cannot return | |
; | |
; define the operating system calls as trap instructions | |
exit=104400 | |
readline=104401 | |
writeline=104402 | |
; | |
; data for the trap instruction | |
trapaddr=34 ; "interrupt entry point" - start address of request handler | |
trapsw=36 ; location for status word | |
opsyssw=40 ; value of status word - priority 1 | |
; | |
; data for the teleprinter | |
ttyaddr=64 ; interrupt entry point for tty - set to address of handler routine | |
ttysw=66 ; holds status word to load when start handling tty event | |
tpsw=200 ; value to put in status word - priority 4 | |
tps=177564 ; control register for console output | |
tpb=177566 ; data register for console output | |
; | |
; data for the keyboard | |
kbdaddr=60 ; interrupt entry point for kbd - set to address of handler routine | |
kbdsw=62 ; holds status word to load when start handling kbd event | |
kbsw=200 ; value to put in status word | |
kbdc=177560 ; control register for console input | |
kbdb=177562 ; data register for console input | |
; | |
; now get code for os | |
.origin 1000 | |
osstart: mov #os,@#trapaddr | |
mov #opsyssw, @#trapsw | |
mov #tput,@#ttyaddr | |
mov #tpsw,@#ttysw | |
mov #kget,@#kbdaddr | |
mov #kbsw,@#kbdsw | |
; | |
; need to enable interrupts from keyboard and teletype | |
; set 'enable' and 'done' in tty | |
; enable only in kbd | |
mov #300,@#tps | |
mov #100,@#kbdc | |
; | |
; hopefully all is ready | |
; start the application | |
jmp application | |
; ---------------------------------------------------------------------------------------- | |
; teletype output | |
; two parts | |
; 1) interrupt handling - each byte gets sent until find a null | |
; 2) the os call writeline | |
tput:tstb @obufptr | |
beq msgdone | |
; There is another character to go | |
movb @obufptr,@#tpb | |
inc obufptr | |
rti | |
msgdone:inc printdoneflag | |
rti | |
; | |
; os variables | |
obufptr: .blkw 1 | |
printdoneflag: .blkw 1 | |
; | |
; write - called by os code handling 'writeline' | |
; on entry r1 contains address of the request in user code | |
; the address of buffer is next word | |
write:inc r1 | |
inc r1 | |
mov (r1),obufptr | |
clr printdoneflag | |
; send the first character | |
movb @obufptr,@#tpb | |
inc obufptr | |
; now wait in os until printdoneflag is set | |
wrtwait:tst printdoneflag | |
bgt olinedone | |
; nothing to do - it's kind of wait loop | |
wait | |
br wrtwait | |
olinedone:mov #1,r0 | |
jmp osreturn | |
; ---------------------------------------------------------------------------------------- | |
; keyboard handling | |
; two parts | |
; 1) interrupt handling - store bytes until get \n (add a nul) | |
; 2) the os call readline | |
kget:movb @#kbdb,ch | |
movb ch, @ibufptr | |
inc ibufptr | |
cmpb #15,ch | |
beq ilinedone | |
rti | |
; ilinedone - add the nul byte, set flag saying input ready | |
ilinedone: clrb @ibufptr | |
inc kbdoneflag | |
rti | |
; | |
; os variables | |
ibufptr:.blkw 1 | |
kbdoneflag:.blkw 1 | |
ch:.blkw 1 | |
; | |
; read - called by os code handling 'readline' | |
; on entry r1 contains address of the request in user code | |
; the address of buffer is next word | |
read:inc r1 | |
inc r1 | |
mov (r1),ibufptr | |
clr kbdoneflag | |
; and enable input | |
inc @#kbdc | |
; now wait in os until kbdoneflag is set | |
kbwait:tst kbdoneflag | |
bgt kblinedone | |
; nothing to do - it's kind of wait loop | |
wait | |
br kbwait | |
kblinedone:mov #1,r0 | |
jmp osreturn | |
; | |
;-------------------------------------------------------------------- | |
; my micro operating system | |
os:mov r0,-(sp) | |
mov r1,-(sp) | |
mov 4(sp),r1 | |
; program counter has been incremented - take off 2 | |
dec r1 | |
dec r1 | |
; r1 should hold the address of the trap instruction | |
mov (r1),r0 | |
; bottom 8 bits contain request id - (though typically far fewer calls defined) | |
; clear the top byte | |
bic #177400,r0 | |
; all that this demo does is maintain counts of trap requests 0-7 | |
; convert index to byte offset | |
rol r0 | |
jmp @osfns(r0) | |
; | |
; handle return from os call | |
; when reach here r0 should hold number of arguments used | |
; by last os call; need to adjust return address that is on stack | |
osreturn:rol r0 | |
add r0,4(sp) | |
; and put back registers | |
mov (sp)+,r1 | |
mov (sp)+,r0 | |
rtt | |
; | |
; function table for my os | |
osfns: exitos | |
read | |
write | |
; | |
; exit from os | |
exitos: nop | |
nop | |
halt | |
br exitos ; no escape | |
; | |
;--------------------------------------------------------------------------- | |
; | |
; library functions | |
; | |
; equivalent of libc in Linux | |
; | |
; just readint and printint | |
; | |
; readint - invokes system function readline, reading into buffer | |
; unpacks contents as integer - or 0 if cannot understand | |
; | |
; printint - creates decimal string in buffer, then calls system function | |
; writeline | |
; | |
printint: clr numsign | |
tst r0 | |
bge wpos | |
inc numsign | |
neg r0 | |
wpos: mov #obuf,r2 | |
mov #10,r1 | |
wclr: movb #40,(r2)+ | |
sob r1,wclr | |
wlp: mov r0,r1 | |
clr r0 | |
div #12,r0 | |
add #60,r1 | |
movb r1,-(r2) | |
tst r0 | |
bgt wlp | |
tst numsign | |
beq wdone | |
movb #55,-(r2) | |
wdone: writeline | |
obuf | |
return | |
readint: readline | |
inbuf | |
writeline | |
inbuf | |
clr ival | |
clr numsign | |
mov #inbuf,r0 | |
cmpb (r0),#55 ; checking for negative sign | |
bne rilp | |
; -ve number | |
inc numsign | |
inc r0 | |
rilp: movb (r0)+,r1 | |
; is it a digit | |
; | |
cmp r1,#60 | |
blt rdone | |
cmp r1,#71 | |
bgt rdone | |
sub #60,r1 | |
mov ival,r3 | |
mul #12,r3 | |
add r1,r3 | |
mov r3,ival | |
br rilp | |
rdone: mov ival,r0 | |
tst numsign | |
beq unsigned | |
neg r0 | |
unsigned: | |
return | |
ival: 0 | |
numsign: 0 | |
inbuf: .blkw 10 | |
obuf: .blkw 10 | |
newline:writeline | |
newl | |
return | |
newl: .word 15 | |
; readoct and printoct added later | |
readoct: readline | |
inbuf | |
writeline | |
inbuf | |
clr ival2 | |
mov #inbuf,r0 | |
rilp2: movb (r0)+,r1 | |
; is it an octal digit | |
cmp r1,#60 | |
blt rdone2 | |
cmp r1,#67 | |
bgt rdone2 | |
sub #60,r1 | |
mov ival2,r3 | |
ash #3,r3 | |
add r1,r3 | |
mov r3,ival2 | |
br rilp2 | |
rdone2: mov ival2,r0 | |
return | |
ival2: 0 | |
; print number as unsigned octal bit pattern | |
; start by clearing output buffer | |
printoct:mov #obuf2,r2 | |
mov #10,r1 | |
wclr2: movb #40,(r2)+ | |
sob r1,wclr2 | |
mov #5,r3 | |
wlp2:mov r0,r1 | |
bic mask,r1 | |
add #60,r1 | |
movb r1,-(r2) | |
asr r0 | |
asr r0 | |
asr r0 | |
sob r3,wlp2 | |
bic mask2,r0 | |
add #60,r0 | |
movb r0,-(r2) | |
writeline | |
obuf2 | |
return | |
mask:177770 | |
mask2:17776 | |
obuf2:.blkw 10 | |
;---------------------------- | |
.origin 2400 | |
application: writeline | |
msg0 | |
call newline | |
writeline | |
msg1 | |
call readint | |
mov r0,x | |
call newline | |
writeline | |
msg2 | |
if0: mov x,-(sp) | |
mov #3,-(sp) | |
clr r0 | |
cmp (sp)+,(sp)+ | |
ble cmp0 | |
inc r0 | |
cmp0: tst r0 | |
beq eif0 | |
writeline | |
msg3 | |
eif0: call newline | |
writeline | |
msg4 | |
if1: mov x,-(sp) | |
mov #3,-(sp) | |
clr r0 | |
cmp (sp)+,(sp)+ | |
blt cmp1 | |
inc r0 | |
cmp1: tst r0 | |
beq eif1 | |
writeline | |
msg5 | |
eif1: call newline | |
writeline | |
msg6 | |
if2: mov x,-(sp) | |
mov #3,-(sp) | |
clr r0 | |
cmp (sp)+,(sp)+ | |
bne cmp2 | |
inc r0 | |
cmp2: tst r0 | |
beq eif2 | |
writeline | |
msg7 | |
eif2: call newline | |
writeline | |
msg8 | |
if3: mov x,-(sp) | |
mov #3,-(sp) | |
clr r0 | |
cmp (sp)+,(sp)+ | |
beq cmp3 | |
inc r0 | |
cmp3: tst r0 | |
beq eif3 | |
writeline | |
msg9 | |
eif3: call newline | |
writeline | |
msg10 | |
if4: mov x,-(sp) | |
mov #3,-(sp) | |
clr r0 | |
sub (sp)+,(sp)+ | |
bgt cmp4 | |
inc r0 | |
cmp4: tst r0 | |
beq eif4 | |
writeline | |
msg11 | |
eif4: call newline | |
writeline | |
msg12 | |
if5: mov x,-(sp) | |
mov #3,-(sp) | |
clr r0 | |
sub (sp)+,(sp)+ | |
bge cmp5 | |
inc r0 | |
cmp5: tst r0 | |
beq eif5 | |
writeline | |
msg13 | |
call newline | |
eif5: exit | |
x: .word 0 | |
msg0: .string "Program ifs" | |
msg1: .string "Enter value x = " | |
msg2: .string "x < 3" | |
msg3: .string " - True" | |
msg4: .string "x <= 3" | |
msg5: .string " - True" | |
msg6: .string "x == 3" | |
msg7: .string " - True" | |
msg8: .string "x != 3" | |
msg9: .string " - True" | |
msg10: .string "x >= 3" | |
msg11: .string " - True" | |
msg12: .string "x > 3" | |
msg13: .string " - True" | |
.end osstart |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment