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