.ORG 0x0000 ; ; Define constants ; IO_BASE .EQU 0xFC00 UART0_BASE .EQU 0xFC00 ; ; Main program ; MOVE IO_BASE, R13 ; Set up stack pointer ; MAIN_LOOP MOVE PROMPT, R8 ; Get pointer to the prompt string MOVE UART0_BASE, R9 ; Which UART will be used in the following? RSUB PUTS, 1 ; Print prompt string MOVE 0xABCD, R8 RSUB PUT_W_HEX, 1 RSUB PUT_CRLF, 1 ; and print a CR/LF pair ; HALT ; ;*************************************************************************************** ;* STRCMP compares two strings ;* ;* R8: Pointer to the first string (S0), ;* R9: Pointer to the second string (S1), ;* R10: negative, if (S0 < S1), zero if (S0 == S1), positive if (S0 > S1) ; ;* The contents of R8 and R9 are being preserved during the run of this function ;*************************************************************************************** ; STRCMP ADD 0x0100, R14 ; Get a new register page MOVE R8, R0 ; Store contents of R8 MOVE R9, R1 ; for later restore operation MOVE R0, R8 ; Restore R8 MOVE R1, R9 ; and R9 SUB 0x0100, R14 ; Restore previous register page MOVE @R13++, R15 ; and return to calling program part ; ;*************************************************************************************** ;* PUT_W_HEX prints a machine word in hexadecimal notation. ;* ;* R8: Contains the machine word to be printed in hex notation. ;* R9: Contains the base address of the UART to be used as output device. ;* ;* The contents of R8 and R9 are being preserved during the run of this function. ;*************************************************************************************** ; PUT_W_HEX ADD 0x0100, R14 ; Get a new register page MOVE 0x0004, R0 ; Save constant for nibble shifting MOVE R0, R4 ; Set loop counter to four MOVE R8, R5 ; Copy contents of R8 for later restore MOVE HEX_NIBBLES, R1 ; Create a pointer to the list of nibbles ; Push four ASCII characters to the stack _PWH_SCAN MOVE R1, R2 ; and create a scratch copy of this pointer MOVE R8, R3 ; Create a local copy of the machine word AND 0x000f, R3 ; Only the four LSBs are of interest ADD R3, R2 ; Adjust pointer to the desired nibble MOVE @R2, @--R13 ; and save the ASCII character to the stack SHR R0, R8 ; Shift R8 four places right SUB 0x0001, R4 ; Decrement loop counter RBRA _PWH_SCAN, !Z ; and continue with the next nibble ; Now read these characters back and print them MOVE R0, R4 ; Initialize loop counter _PWH_PRINT MOVE @R13++, R8 ; Fetch a character from the stack RSUB PUTCHAR, 1 ; and print it SUB 0x0001, R4 ; Decrement loop counter RBRA _PWH_PRINT, !Z ; and continue with the next character ; That's all... MOVE R5, R8 ; Restore contents of R8 SUB 0x0100, R14 ; Restore correct register page MOVE @R13++, R15 ; and return to calling program part ; ;*************************************************************************************** ;* PUTS prints a null terminated string. ;* ;* R8: Pointer to the string to be printed. Of each word only the lower eight bits ;* will be printed. The terminating word has to be zero. ;* R9: Has to contain the base address of the UART to be used for output. ;* ;* The contents of R8 and R9 are being preserved during the run of this function. ;*************************************************************************************** ; PUTS ADD 0x0100, R14 ; Get a new register page MOVE R8, R1 ; Save contents of R8 MOVE R8, R0 ; Local copy of the string pointer _PUTS_LOOP MOVE @R0++, R8 ; Get a character from the string AND 0x00FF, R8 ; Only the lower eight bits are relevant RBRA _PUTS_END, Z ; Return when the string end has been reached RSUB PUTCHAR, 1 ; Print this character RBRA _PUTS_LOOP, 1 ; Continue with the next character _PUTS_END MOVE R1, R8 ; Restore contents of R8 SUB 0x0100, R14 ; Restore correct register page MOVE @R13++, R15 ; Return to the calling program part ; ;*************************************************************************************** ;* PUT_CRLF prints a CR/LF. ;* ;* R9: Has to contain the base address of the UART to be used, ;* its value will be preserved. ;*************************************************************************************** ; PUT_CRLF ADD 0x0100, R14 ; Get a new register page MOVE R8, R0 ; Save contents of R8 MOVE 0x0D, R8 RSUB PUTCHAR, 1 MOVE 0x0A, R8 RSUB PUTCHAR, 1 MOVE R0, R8 ; Restore contents of R8 SUB 0x0100, R14 ; Return to previous register page MOVE @R13++, R15 ; Return ; ;*************************************************************************************** ;* PUTCHAR prints a single character. ;* ;* R8: Contains the character to be printed ;* R9: Contains the base address of the UART to be used ; ;* The contents of R8 and R9 are being preserved during the run of this function. ;* ;* TODO: This routine is way too simple and only works with the emulator's simple ;* UART emulation. To use a real 16550 this routine will require a complete ;* rewrite! ;*************************************************************************************** ; PUTCHAR ADD 0x0100, R14 ; Get a new register page MOVE R8, @R9 ; Print character SUB 0x0100, R14 ; Restore the old page MOVE @R13++, R15 ; Return to the calling program part ; ;*************************************************************************************** ; Constants, etc. ;*************************************************************************************** ; PROMPT .ASCII_W QMON> HEX_NIBBLES .ASCII_W 0123456789ABCDEF ; ; Solved problems: ; - Problem with backward relative jumps - the assembler wrote 32 bit ints, I have masked this by 0xffff. ; - The directive .ASCII_W was undefined in the valid_directives hash. ; - SHL and SHR now expect two arguments each! ; Unsolved problems: ; - The assembler does not warn on a jump/branch without condition! This is a serious error! ; - Assembler warnings should always print the line causing the trouble. ; - The words generated by an .ASCII_x directive will not show in the listing! ; - The .ASCII_W directive should expect the string in quotes to be able to code trailing blanks ; which are currently suppressed. ; Changes of the instruction set: ; - SHL and SHR now take two parameters: The lower four bits of the left most parameter specify the ; number of shifts to be performed on the right most parameter. ;