Interrupts-Microprocessor and Assembly Language Programming-Lecture Notes, Study notes of Microprocessor and Assembly Language Programming

This lecture handout was provided at Quaid-i-Azam University for Microprocessor and Assembly Language Programming course by Prof. Saleem Raza. Its main points are: Interrupts, Asynchronous, Synchronous, Flags, Register, Handler, Program, Memory, Functions

Typology: Study notes

2011/2012

Uploaded on 08/04/2012

saqqi
saqqi 🇵🇰

4

(33)

40 documents

1 / 8

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
Interrupts in reality are events that occurred outside the processor and the
processor must be informed about them. Interrupts are asynchronous and
unpredictable. Asynchronous means that the interrupts occur, independent
of the working of the processor, i.e. independent of the instruction currently
executing. Synchronous events are those that occur side by side with
another activity. Interrupts must be asynchronous as they are generated by
the external world which is unaware of the happenings inside the processor.
True interrupts that occur in real time are asynchronous with the execution.
Also it is unpredictable at which time an interrupt will come. The two
concepts of being unpredictable and asynchronous are overlapping.
Unpredictable means the time at which an interrupt will come cannot be
predicted, while asynchronous means that the interrupt has nothing to do
with the currently executing instruction and the current state of the
processor.
The 8088 processor divides interrupts into two classes. Software interrupts
and hardware interrupts. Hardware interrupts are the real interrupts
generated by the external world as discussed above. Software interrupts on
the contrary are not generated from outside the processor. They just provide
an extended far call mechanism. Far call allows us to jump anywhere in the
whole megabyte of memory. To return from the target we place both the
segment and offset on the stack. Software interrupts show a similar
behavior. It however pushes one more thing before both the segment and
offset and that is the FLAGS register. Just like the far call loads new values
in CS and IP, the interrupt call loads new values in CS, IP, and FLAGS.
Therefore the only way to retain the value of original FLAGS register is to
push and pop as part of interrupt call and return instructions. Pushing and
popping inside the routine will not work as the routine started with an
already tampered value.
The discussion of real time interrupts is deferred till the next chapter. They
play the critical part in control applications where external hardware must
be control and events and changes therein must be appropriately responded
by the processor. To generate an interrupt the INT instruction is used. The
routine that executes in response to an INT instruction is called the interrupt
service routine (ISR) or the interrupt handler. Taking example from real time
interrupts the routine to instruct an external hardware to close the valve of a
boiler in response to an interrupt from the pressure sensor is an interrupt
routine.
The software interrupt mechanism in 8088 uses vectored interrupts
meaning that the address of the interrupt routine is not directly mentioned
in an interrupt call, rather the address is lookup up from a table. 8088
provides a mechanism for mapping interrupts to interrupt handlers.
Introducing a new entry in this mapping table is called hooking an interrupt.
Syntax of the INT instruction is very simple. It takes a single byte
argument varying from 0-255. This is the interrupt number informing the
processor, which interrupt is currently of interest. This number correlates to
the interrupt handler routine by a routing or vectoring mechanism. A few
interrupt numbers in the start are reserved and we generally do not use
them. They are related to the processor working. For example INT 0 is the
pf3
pf4
pf5
pf8

Partial preview of the text

Download Interrupts-Microprocessor and Assembly Language Programming-Lecture Notes and more Study notes Microprocessor and Assembly Language Programming in PDF only on Docsity!

Interrupts in reality are events that occurred outside the processor and the

processor must be informed about them. Interrupts are asynchronous and

unpredictable. Asynchronous means that the interrupts occur, independent

of the working of the processor, i.e. independent of the instruction currently

executing. Synchronous events are those that occur side by side with

another activity. Interrupts must be asynchronous as they are generated by

the external world which is unaware of the happenings inside the processor.

True interrupts that occur in real time are asynchronous with the execution.

Also it is unpredictable at which time an interrupt will come. The two

concepts of being unpredictable and asynchronous are overlapping.

Unpredictable means the time at which an interrupt will come cannot be

predicted, while asynchronous means that the interrupt has nothing to do

with the currently executing instruction and the current state of the

processor.

The 8088 processor divides interrupts into two classes. Software interrupts

and hardware interrupts. Hardware interrupts are the real interrupts

generated by the external world as discussed above. Software interrupts on

the contrary are not generated from outside the processor. They just provide

an extended far call mechanism. Far call allows us to jump anywhere in the

whole megabyte of memory. To return from the target we place both the

segment and offset on the stack. Software interrupts show a similar

behavior. It however pushes one more thing before both the segment and

offset and that is the FLAGS register. Just like the far call loads new values

in CS and IP, the interrupt call loads new values in CS, IP, and FLAGS.

Therefore the only way to retain the value of original FLAGS register is to

push and pop as part of interrupt call and return instructions. Pushing and

popping inside the routine will not work as the routine started with an

already tampered value.

The discussion of real time interrupts is deferred till the next chapter. They

play the critical part in control applications where external hardware must

be control and events and changes therein must be appropriately responded

by the processor. To generate an interrupt the INT instruction is used. The

routine that executes in response to an INT instruction is called the interrupt

service routine (ISR) or the interrupt handler. Taking example from real time

interrupts the routine to instruct an external hardware to close the valve of a

boiler in response to an interrupt from the pressure sensor is an interrupt

routine.

The software interrupt mechanism in 8088 uses vectored interrupts

meaning that the address of the interrupt routine is not directly mentioned

in an interrupt call, rather the address is lookup up from a table. 8088

provides a mechanism for mapping interrupts to interrupt handlers.

Introducing a new entry in this mapping table is called hooking an interrupt.

Syntax of the INT instruction is very simple. It takes a single byte

argument varying from 0-255. This is the interrupt number informing the

processor, which interrupt is currently of interest. This number correlates to

the interrupt handler routine by a routing or vectoring mechanism. A few

interrupt numbers in the start are reserved and we generally do not use

them. They are related to the processor working. For example INT 0 is the

divide by zero interrupt. A list of all reserved interrupts is given later. Such

interrupts are programmed in the hardware to generate the designated

interrupt when the specified condition arises. The remaining interrupts are

provided by the processor for our use. Some of these were reserved by the

IBM PC designers to interface user programs with system software like DOS

and BIOS. This was the logical choice for them as interrupts provided a very

flexible architecture. The remaining interrupts are totally free for use in user

software.

The correlation process from the interrupt number to the interrupt handler

uses a table called interrupt vector table. Its location is fixed to physical

memory address zero. Each entry of the table is four bytes long containing

the segment and offset of the interrupt routine for the corresponding

interrupt number. The first two bytes in the entry contain the offset and the

next two bytes contain the segment. The little endian rule of putting the more

significant part (segment) at a higher address is seen here as well.

Mathematically offset of the interrupt n will be at nx4 while the segment will

be at nx4+2. One entry in this table is called a vector. If the vector is changed

for interrupt 0 then INT 0 will take execution to the new handler whose

address is now placed at those four bytes. INT 1 vector occupies location 4,

5, 6, and 7 and similarly vector for INT 2 occupies locations 8, 9, 10, and 11.

As the table is located in RAM it can be changed anytime. Immediately after

changing it the interrupt mapping is changed and now the interrupt will

result in execution of the new routine. This indirection gives the mechanism

extreme flexibility.

The operation of interrupt is same whether it is the result of an INT

instruction (software interrupt) or it is generated by an external hardware

which passes the interrupt number by a different mechanism. The currently

executing instruction is completed, the current value of FLAGS is pushed on

the stack, then the current code segment is pushed, then the offset of the

next instruction is pushed. After this it automatically clears the trap flag and

the interrupt flag to disallow further interrupts until the current routine

finishes. After this it loads the word at nx4 in IP and the word at nx4+2 in CS

if interrupt n was generated. As soon as these values are loaded in CS and IP

execution goes to the start of the interrupt handler. When the handler

finishes its work it uses the IRET instruction to return to the caller. IRET

pops IP, then CS, and then FLAGS. The original value of IF and TF is

restored which re-enables further interrupts. IF and TF will be discussed in

detail in the discussion of real time interrupts. We have discussed three

things till now.

1. The INT and IRET instruction format and syntax

2. The formation of IVT (interrupt vector table)

3. Operation of the processor when an interrupt in generated

Just as discussed in the subroutines chapter, the processor will not match

interrupt calls to interrupt returns. If a RETF is used in the end of an ISR the

processor will still return to the caller but the FLAGS will remain on the

stack which will destroy the expectations of the caller with the stack. If we

know what we are doing we may use such different combination of

instructions. Generally we will use IRET to return from an interrupt routine.

Apart from indirection the software interrupt mechanism is similar to CALL

and RET. Indirection is the major difference.

The operation of INT can be written as:

 sp  sp-

 [sp]  flag

 sp  sp-

 if  0

 tf  0

 [sp]  cs

 sp  sp-

 [sp]  ip

which informs about fatal hardware failures in the system and is tied

to interrupt 2. INT pin can be masked but NMI cannot be masked.

 INT 3, Debug Interrupt

The only special thing about this interrupt is that it has a single byte

opcode and not a two byte combination where the second byte tells the

interrupt number. This allows it to replace any instruction whatsoever.

It is also used by the debugger and will be discussed in detail with the

debugger working.

 INT 4, Arithmetic Overflow, change of sign bit

The overflow flag is set if the sign bit unexpectedly changes as a result

of a mathematical or logical instruction. However the overflow flag

signals a real overflow only if the numbers in question are treated as

signed numbers. So this interrupt is not automatically generated but

as a result of a special instruction INTO (interrupt on overflow) if the

overflow flag is set. Otherwise the INTO instruction behaves like a NOP

(no operation).

These are the five interrupts reserved by Intel and are generally not used in

our operations.

HOOKING AN INTERRUPT

To hook an interrupt we change the vector corresponding to that interrupt.

As soon as the interrupt vector changes, that interrupt will be routed to the

new handler. Our first example is with the divide by zero interrupt. The

normal system defined behavior in response to divide by zero is to display an

error message and terminate the program. We will change it to display our

own message.

Example

; hooking divide by zero interrupt [org 0x0100] jmp start

message: db 'You divided something by zero.', 0

;;;;; COPY LINES 028-050 FROM EXAMPLE 7.4 (strlen) ;;;;; ;;;;; COPY LINES 005-024 FROM EXAMPLE 7.1 (clrscr) ;;;;; ;;;;; COPY LINES 050-090 FROM EXAMPLE 7.4 (printstr) ;;;;;

; divide by zero interrupt handler myisrfor0: push ax ; push all regs push bx push cx push dx push si push di push bp push ds push es

push cs pop ds ; point ds to our data segment

call clrscr ; clear the screen mov ax, 30 push ax ; push x position mov ax, 20 push ax ; push y position mov ax, 0x71 ; white on blue attribute push ax ; push attribute mov ax, message push ax ; push offset of message call printstr ; print message

pop es pop ds pop bp

pop di pop si pop dx pop cx pop bx pop ax iret ; return from interrupt

; subroutine to generate a divide by zero interrupt genint0: mov ax, 0x8432 ; load a big number in ax mov bl, 2 ; use a very small divisor div bl ; interrupt 0 will be generated ret

start: xor ax, ax mov es, ax ; load zero in es mov word [es:04], myisrfor0 ; store offset at n mov [es:04+2], cs ; store segment at n4+ call genint0 ; generate interrupt 0

mov ax, 0x4c00 ; terminate program int 0x

93-101 We often push all registers in an interrupt service routine just to be

sure that no unintentional modification to any register is made.

Since any code may be interrupted an unintentional modification

will be hard to debug

103-104 Since interrupt can be called from anywhere we are not sure about

the value in DS so we reset it to our code segment.

When this program is executed our desired message will be shown instead

of the default message and the computer will hang thereafter. The first thing

to observe is that there is no INT 0 call anywhere in the code. INT 0 was

invoked automatically by an internal mechanism of the processor as a result

of the DIV instruction producing a result that cannot fit in the destination

register. Just by changing the vector we have changed the response of the

system to divide overflow situations.

However the system stuck instead of returning to the next instruction.

This is because divide overflow is a special type of interrupt that returns to

the same instruction instead of the next instruction. This is why the default

handler forcefully terminates the program instead of returning. Now the IRET

will take control back to the DIV instruction which will again generate the

same interrupt. So the computer is stuck in an infinite loop.

BIOS AND DOS INTERRUPTS

In IBM PC there are certain interrupts designated for user programs to

communicate with system software to access various standard services like

access to the floppy drive, hard drive, vga, clock etc. If the programmer does

not use these services he has to understand the hardware details like which

particular controller is used and how it works. To avoid this and provide

interoperability a software interface to basic hardware devices is provided

except in very early computers. Since the manufacturer knows the hardware

it burns the software to control its hardware in ROM. Such software is called

firmware and access to this firmware is provided through specified

interrupts.

This basic interface to the hardware is called BIOS (basic input output

services). When the computer is switched on, BIOS gets the control at a

specified address. The messages at boot time on the screen giving BIOS

version, detecting different hardware are from this code. BIOS has the

responsibility of testing the basic hardware including video, keyboard, floppy

drive, hard drive etc and a special program to bootstrap. Bootstrap means to

load OS from hard disk and from there OS takes control and proceeds to load

its components and display a command prompt in the end. There are two

Example

; print string using bios service [org 0x0100] jmp start message: db 'Hello World'

start: mov ah, 0x13 ; service 13 - print string mov al, 1 ; subservice 01 – update cursor mov bh, 0 ; output on page 0 mov bl, 7 ; normal attrib mov dx, 0x0A03 ; row 10 column 3 mov cx, 11 ; length of string push cs pop es ; segment of string mov bp, message ; offset of string int 0x10 ; call BIOS video service

mov ax, 0x4c00 ; terminate program int 0x

007 The sub-service are versions of printstring that update and do not

update the cursor after printing the string etc.

008 Text video screen is in the form of pages which can be upto 32. At

one time one page is visible which is by default the zeroth page

unless we change it.

When we execute it the string is printed and the cursor is updated as well.

With direct access to video memory we had no control over the cursor. To

control cursor a different mechanism to access the hardware was needed.

Our next example uses the keyboard service to read a key. The

combination of keyboard and video services is used in almost every program

that we see and use. We will wait for four key presses; clear the screen after

the first, and draw different strings after the next key presses and exiting

after the last. We will use INT 16 service 1 for this purpose. This is a blocking

service so it does not return until a key has been pressed. We also used the

blinking attribute in this example.

Example

; print string and keyboard wait using BIOS services [org 0x100] jmp start

msg1: db 'hello world', 0 msg2: db 'hello world again', 0 msg3: db 'hello world again and again', 0

;;;;; COPY LINES 005-024 FROM EXAMPLE 7.1 (clrscr) ;;;;; ;;;;; COPY LINES 050-090 FROM EXAMPLE 7.4 (printstr) ;;;;; ;;;;; COPY LINES 028-050 FROM EXAMPLE 7.4 (strlen) ;;;;;

start: mov ah, 0x10 ; service 10 – vga attributes mov al, 03 ; subservice 3 – toggle blinking mov bl, 01 ; enable blinking bit int 0x10 ; call BIOS video service

mov ah, 0 ; service 0 – get keystroke int 0x16 ; call BIOS keyboard service

call clrscr ; clear the screen

mov ah, 0 ; service 0 – get keystroke int 0x16 ; call BIOS keyboard service

mov ax, 0 push ax ; push x position mov ax, 0 push ax ; push y position mov ax, 1 ; blue on black push ax ; push attribute mov ax, msg push ax ; push offset of string call printstr ; print the string

mov ah, 0 ; service 0 – get keystroke int 0x16 ; call BIOS keyboard service

mov ax, 0 push ax ; push x position mov ax, 0 push ax ; push y position mov ax, 0x71 ; blue on white push ax ; push attribute mov ax, msg push ax ; push offset of string call printstr ; print the string

mov ah, 0 ; service 0 – get keystroke int 0x16 ; call BIOS keyboard service

mov ax, 0 push ax ; push x position mov ax, 0 push ax ; push y position mov ax, 0xF4 ; red on white blinking push ax ; push attribute mov ax, msg push ax ; push offset of string call printstr ; print the string

mov ah, 0 ; service 0 – get keystroke int 0x16 ; call BIOS keyboard service

mov ax, 0x4c00 ; terminate program int 0x

099-100 This service has no parameters so only the service number is

initialized in AH. This is the only service so there is no sub-service

number as well. The ASCII code of the char pressed is returned in

AL after this service.