Assembly Code Examples: Periodic Interrupts and Keypad Access
Example 1: Periodic Interrupt and Counter
This program demonstrates a periodic interrupt that increments a counter (0 to 99) and prints its value to the text display.
JMP boot
JMP isr
stackTop EQU 0xFF
txtDisplayTens EQU 0x2E0
txtDisplayUnits EQU 0x2E1
counter: ; the counter
DW 0
boot:
MOV SP, stackTop ; Set SP
MOV A, 2 ; Set bit 1 of IRQMASK
OUT 0 ; Unmask timer IRQ
MOV A, 0x20 ; Set timer preload
OUT 3
STI
HLT
isr:
PUSH A
PUSH B
PUSH C
MOV A, [counter] ; Increment the
INC A ; counter
CMP A, 100 ; [0 to 99]
JNZ .print
MOV A, 0
.print:
MOV [counter], A ; Print the
MOV B, A ; decimal value
DIV 10 ; of the counter
MOV C, A
MUL 10
SUB B, A
ADDB CL, 0x30
ADDB BL, 0x30
MOVB [txtDisplayTens], CL
MOVB [txtDisplayUnits], BL
MOV A, 2
OUT 2 ; Write to signal IRQEOI
POP C
POP B
POP A
IRET
Example 2: Keypad Access and Text Display (User Mode)
This example shows a user mode task accessing the keypad and the text display using two non-blocking system calls. The task polls the keypad until a key has been pressed and prints the value on the text display.
JMP boot
JMP isr ; Interrupt vector
JMP svc ; System call vector
sStackTop EQU 0x0FF ; Initial Supervisor SP
uStackTop EQU 0x1FF ; Initial User Task SP
txtDisplay EQU 0x2E0
keypressed: ; 1 = key pressed
DB 0 ; 0 = No key pressed
value: ; The number of the
DB 0 ; key pressed in ASCII
boot:
MOV SP, sStackTop ; Set Supervisor SP
MOV A, 1 ; Set bit 0 of IRQMASK
OUT 0 ; Unmask keypad IRQ
MOV A, 0x01FF ; Set the end of the
OUT 8 ; protection to 0x01FF
MOV A, 0x0109 ; Protection in seg. mode
OUT 7 ; from 0x0100, S=1, U=0
PUSH 0x0010 ; User Task SR: IRQMASK = 1
PUSH uStackTop ; User Task SP = 0x1FF
PUSH task ; User Task IP = task
SRET ; Jump to user mode
HLT ; Parachute
isr:
PUSH A ; Read the key pressed
IN 6 ; and store the ASCII
MOVB [value], AL
MOVB AL, 1
MOVB [keypressed], AL
MOV A, 1
OUT 2 ; Write to signal IRQEOI
POP A
IRET
svc: ; Supervisor call
CMP A, 0 ; A = syscall number
JNZ .not0 ; 0 -> readchar
CLI
MOV A, [keypressed] ; Write vars
PUSH B ; with IRQs
MOV B, 0 ; disabled
MOV [keypressed], B
POP B
STI
JMP .return
.not0:
CMP A, 1 ; 1 -> putchar
JNZ .return
MOVB [txtDisplay], BL
.return:
SRET ; Return to user space
ORG 0x100 ; Following instructions
; will be assembled at 0x100
task: ; The user task
MOV A, 0
MOV B, 0
loop:
CALL readchar ; Polls the keypad
CMPB AH, 1 ; using readchar
JNZ loop
MOVB BL, AL ; If key was pressed use
CALL putchar ; putchar to print it
JMP loop
readchar: ; User space wrapper
MOV A, 0 ; for readchar syscall
SVC ; Syscall #0
RET ; A -> syscall number
putchar: ; User space wrapper
PUSH A ; for putchar syscall
MOV A, 1 ; Syscall #1
SVC ; A -> syscall number
POP A ; BL -> char to print
RET