📄 ashos_lc3.asm
字号:
; Ash LC-3b Operating System 1.00
; (c) Ashley Wise, 2003
; awise@crhc.uiuc.edu
;
; AshOS_LC3.asm must be linked with the user code.
; AsmOS_LC3.ah should be be included in the user code.
; R0 is used for passing values to/from OS functions.
; R6 is expected to be the User Stack Pointer (USP).
; R7 is overwritten by the TRAP instruction (return address).
; All other registers are preserved.
; Remember to NULL-terminate strings.
INCLUDE "AshOS_LC3.ah"
ORIGIN 0
SEGMENT
BootCode:
SEGMENT
; Jumps over the Trap and Interrupt vector tables.
trap MAIN
; Might want to perform some check code after "main" exits
trap HALT
TrapVectorTable:
SEGMENT 4x20
GETC: data2 _GETC
OUT: data2 _OUT
PUTS: data2 _PUTS
IN: data2 _IN
PUTSP: data2 _PUTSP
HALT: data2 _HALT
MAIN: data2 _MAIN
STRUCTDEF UndefVector data2 _UNDEF END
STRUCT UndefVector[4xD9] ?
ExceptionVectorTable:
SEGMENT 4xE0
; The program will load the pointer to their handlers here.
Privilege: data2 _Privilege
IllegalInstr: data2 _IllegalInstr
InterruptVectorTable:
SEGMENT 4x80
; The program will load the pointer to their handlers here.
Keyboard: data2 _Keyboard
TrapFunctions:
SEGMENT 4x80
; Note that in order for the trap functions to work correctly,
; the user code must have preserved R6 as the User Stack Pointer
; (USP). R6 is initialized to this value when the simulator boots.
; If you clobber R6, trap functions might not work.
; You can define NO_USP (as a global define, not in your code)
; which will tell the OS to use local storage rather than the USP.
STRUCTDEF RegisterStack
Reg: data2[8] ?
END
IFDEF NO_USP
MACRO PushRegs0(LocalRegStack)
st r0, LocalRegStack.Reg[0]
PushRegs(LocalRegStack)
END
MACRO PushRegs(LocalRegStack)
st r1, LocalRegStack.Reg[1]
st r2, LocalRegStack.Reg[2]
st r3, LocalRegStack.Reg[3]
st r4, LocalRegStack.Reg[4]
st r5, LocalRegStack.Reg[5]
st r7, LocalRegStack.Reg[7]
END
MACRO PopRegs0(LocalRegStack)
ld r0, LocalRegStack.Reg[0]
PopRegs(LocalRegStack)
END
MACRO PopRegs(LocalRegStack)
ld r1, LocalRegStack.Reg[1]
ld r2, LocalRegStack.Reg[2]
ld r3, LocalRegStack.Reg[3]
ld r4, LocalRegStack.Reg[4]
ld r5, LocalRegStack.Reg[5]
ld r7, LocalRegStack.Reg[7]
END
ELSE
MACRO PushRegs0(LocalRegStack)
Push(r0)
PushRegs(LocalRegStack)
END
MACRO PushRegs(LocalRegStack)
Push(r1)
Push(r2)
Push(r3)
Push(r4)
Push(r5)
Push(r7)
END
MACRO PopRegs0(LocalRegStack)
PopRegs(LocalRegStack)
Pop(r0)
END
MACRO PopRegs(LocalRegStack)
Pop(r7)
Pop(r5)
Pop(r4)
Pop(r3)
Pop(r2)
Pop(r1)
END
END
; GETC function
; Reads a single character from the keyboard. The character is not echoed
; onto the console. Its ASCII code is copied into R0. The high eight bits
; of R0 are cleared.
_GETC:
PushRegs(GetCRegStack)
WaitForKB:
ldi r2, pKBSR
BRzp WaitForKB
ldi r0, pKBDR
PopRegs(GetCRegStack)
ret
GetCRegStack: STRUCT RegisterStack ?
pKBSR: data2 KBSR
pKBDR: data2 KBDR
; OUT function
; Write the character in R0[7:0] to the console.
_OUT:
PushRegs0(OutRegStack)
WaitForDisplay:
ldi r2, pDSR
BRzp WaitForDisplay
sti r0, pDDR
PopRegs0(OutRegStack)
ret
OutRegStack: STRUCT RegisterStack ?
; PUTS function
; Write the string pointed to by R0 to the console.
; There is one character per memory location.
; Make sure the string is NULL-terminated!
_PUTS:
PushRegs0(PutsRegStack)
DisplayLoop2:
ldr r3, r0, 0
brz DisplayDone2
WaitForDisplay2:
ldi r2, pDSR
BRzp WaitForDisplay2
sti r3, pDDR
add r0, r0, 1
brnzp DisplayLoop2
DisplayDone2:
PopRegs0(PutsRegStack)
ret
PutsRegStack: STRUCT RegisterStack ?
pDSR: data2 DSR
pDDR: data2 DDR
; IN function
; Print a prompt to the screen and read a single character from the keyboard.
; The character is echoed onto the console along with a newline, and its
; ASCII code is copied into R0. The high eight bits of R0 are cleared.
_IN:
PushRegs(InRegStack)
lea r0, InMessage;
trap PUTS
trap GETC
trap OUT
add r1, r0, 0
ld r0, ENDL
trap OUT
add r0, r1, 0
PopRegs(InRegStack)
ret
InRegStack: STRUCT RegisterStack ?
InMessage: DATA2[] "\nPlease input a single character: \0"
ENDL: data2 '\n'
; PUTSP function
; Write the string pointed to by R0 to the console.
; There are two characters per memory location. The low-byte character
; [7:0] is written first. If there are an odd number of characters,
; the high-byte [15:8] is 4x00. There must still be a full 4x0000
; location at the end of the string.
; Make sure the string is NULL-terminated!
_PUTSP:
PushRegs0(PutspRegStack)
DisplayLoop3:
ldr r4, r0, 0
brz DisplayDone3
;Write the lower char first
WaitForDisplay3a:
ldi r2, pDSR
BRzp WaitForDisplay3a
sti r4, pDDR
;Move upper char into lower char
ld r3, UpperChar
and r4, r4, r3 ;clear out the lower part of the current double-char
and r3, r3, 0 ;zero the result
and r5, r5, 0
add r5, r5, BitMirrors$LEN ;loop count
lea r7, BitMirrors ;setup address
;R5 holds loop count
;R4 holds upper char value
;R3 holds result of moving upper char to lower char
;R7 holds address of current mirror mask
;R2 holds current mirror mask
;R1 is temporary use
;R0 keeps string pointer for PUTSP
MirrorLoop:
ldr r2, r7, 0
add r7, r7, 1
and r1, r2, r4 ;see if this bit is set in the upper char
BRz BitNotSet
add r3, r3, r2 ;add this bit to the lower char
BitNotSet:
add r5, r5, -1
BRp MirrorLoop
;Now write the upper char (which is now in the lower char location)
WaitForDisplay3b:
ldi r2, pDSR
BRzp WaitForDisplay3b
sti r3, pDDR
add r0, r0, 1
brnzp DisplayLoop3
DisplayDone3:
PopRegs0(PutspRegStack)
ret
PutspRegStack: STRUCT RegisterStack ?
UpperChar: DATA2 4xFF00
BitMirrors: DATA2[] 4x0101, 4x0202, 4x0404, 4x0808, 4x1010, 4x2020, 4x4040, 4x8080
; HALT function
; Halt execution and print a message to the console.
_HALT:
PushRegs0(HaltRegStack)
lea r0, HaltMessage;
trap PUTS
ldi r2, pMCR
ld r0, Mask
and r0, r0, R2
sti r0, pMCR
nop
PopRegs0(HaltRegStack)
ret
HaltRegStack: STRUCT RegisterStack ?
HaltMessage: DATA2[] "\nStopping program execution.\n\0"
Mask: DATA2 4x7FFF
pMCR: data2 MCR
; Undef function
; Default function if an undefined trap vector is called.
; Halt execution and print a message to the console.
_UNDEF:
PushRegs0(UndefRegStack)
lea r0, UndefMessage;
trap PUTS
and r0, r0, 0
PopRegs0(UndefRegStack)
ret
UndefRegStack: STRUCT RegisterStack ?
UndefMessage: DATA2[] "\nUndefined trap vector executed.\n\0"
; These functions are not yet implemented because the architectural
; use of the stack pointers is still not defined.
; The simulator will print a message and break on exceptions.
; Privilege exception function
; Halt execution and print a message to the console.
_Privilege:
rti
PrivMessage: DATA2[] "\nRTI instruction executed in unprivileged mode. Skipping over instruction.\n\0"
; IllegalInstr exception function
; Halt execution and print a message to the console.
_IllegalInstr:
rti
IllMessage: DATA2[] "\nIllegal instruction executed. Skipping over instruction.\n\0"
; Keyboard interrupt function
; Doesn't do anything. The user program should define and install their own handler.
_Keyboard:
rti
;The start of the user code space
_MAIN:
SEGMENT 4x2E00
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -