I have an assignment to do for my Assembly programming class.
I am currently kind of lost on how to start it, the professor has given us a base to work with.
I have posted the assignment details and code below.
Thanks.
Objective: Hardware interrupt (Subroutine, I/O and ISR programming)
Download the asn5.asm. This program replaces a DOS keyboard driver
with a simple keyboard driver. It only displays numbers, uppercase of alphabets and some
symbols declared in the data segment. First, run and see how it works. Then, reboot DOS to exit
(this is the only way to exit). Modify the program as instructed below and store it in assign5.asm.
(1) Before installing a new vector table for the keyboard ISR (interrupt-type 9), store the
original vector table.
(2) Add a function in such a way that when the Esc key is pressed, exit program and return to
DOS.
(3) Before exit to DOS, restore the original vector table for the keyboard ISR (interrupt-type
9) and an original value of Interrupt Mask Register (port address 21h) so that the
keyboard functions normally without rebooting DOS.
; Simple Keyboard Driver
.8086
.model small
.stack 100h
;---------------
; Data segment
;---------------
.data
lf EQU 0Ah
cr EQU 0DH
kisr_type EQU 9 ; Keyboard interrupt
kisr_vector EQU kisr_type*4
old_vector_offset dw ?
old_vector_segment dw ?
old_mask_PIC db ?
Keyboard_character db 0FFh
Scan_table db 0,0,'1234567890-=',8,0
db 'QWERTYUIOP[]',CR,0
db 'ASDFGHJKL;',0,0,0,0
db 'ZXCVBNM,./',0,0,0
db ' ',0,0,0,0,0,0,0,0,0,0,0,0,0
db '789-456+1230'
;-------------------
; Code segment
;-------------------
.code
main PROC
MOV AX, @data
MOV DS, AX
; Disable interrupt during installing new vector table for INT 9h.
CLI
MOV AX, 0
MOV ES, AX
; enter new vector table for keyboard interrupt (INT 9h)
MOV ES:[kisr_vector], OFFSET KISR
MOV ES:[kisr_vector+2],@code
; Enable timer and keyboard interrupts only at PIC
IN AL, 21h
MOV old_mask_PIC, AL ; save original Interrupt Mask Register
MOV AL, 0FCh
OUT 21h, AL
STI ; Re-enable interrupt
forever:
CALL get_char
PUSH AX ; Pass by value through stack & store AL
CALL display_char
POP AX ; Clear stack and restore AL
CMP AL, cr
JNZ Repeat_loop
MOV AL, lf
PUSH AX ; Pass by value through stack
CALL display_char
ADD SP, 2
Repeat_loop:
JMP forever
exit:
; Restore original Interrupt Mask Register
MOV AL, old_mask_PIC
OUT 21h, AL
MOV AX, 4C00h
INT 21h
main ENDP
;--------------------
; Subroutine: Get_char
;--------------------
Get_char PROC NEAR
PUSH CX
rep_get:
CLI ; Disable interrupt during getting a character.
CMP Keyboard_character, 0FFh
JNZ accept_code
MOV CL,0
JMP Enable_intr
accept_code:
MOV AL, Keyboard_character
MOV Keyboard_character, 0FFh ; Reset keyboard_character
MOV CL, 1
Enable_intr:
STI ; Enable interrupt to receive the character.
CMP CL, 1
JNZ rep_get
POP CX
RET
Get_char ENDP
;---------------------
;Keyboard ISR: KISR
;---------------------
KISR PROC FAR
PUSH AX
PUSH BX
PUSH DS
MOV AX, @data
MOV DS, AX
IN AL, 60h ; Save the scan code from port PA (60h) in AL
PUSH AX
;Acknowledge Keyboard: Toggle PB bit 7
IN AL, 61h
OR AL, 80h
OUT 61h, AL
AND AL, 7Fh
OUT 61h, AL
POP AX
TEST AL, 80h
JNZ send_EOI
; Convert scan code to ASCII
LEA BX, Scan_table
;XLAT
XOR AH, AH
MOV DI, AX
MOV AL, [BX+DI]
CMP AL, 0
JZ send_EOI
MOV Keyboard_character, AL
send_EOI:
; indicate the end of interrupt to the 8259 chip
MOV AL, 20h
OUT 20h, AL
POP DS
POP BX
POP AX
IRET
KISR ENDP
;-----------------
; Subroutine: Display character using DOS function
;-----------------
Display_char PROC NEAR
PUSH BP ; Store original BP
MOV BP,SP
PUSH DX
PUSH AX
MOV AX, [BP+4] ; pass by value through stack
MOV AH, 2
MOV DL, AL ; A character to be displayed is in AL.
INT 21h ; When AH=2, display the charecter in DL
POP AX
POP DX
POP BP
RET
Display_char ENDP
END main