|
|||||
8
Software
Interrupts
8.1.
INTERRUPTS
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 all 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
Computer
Architecture & Assembly Language
Programming
Course
Code: CS401
CS401@vu.edu.pk
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+2
· [sp]
←
flag
· sp
←
sp+2
· if
←
0
· tf
←
0
· [sp]
←
cs
· sp
←
sp+2
· [sp]
←
ip
96
Computer
Architecture & Assembly Language
Programming
Course
Code: CS401
CS401@vu.edu.pk
· ip
←
[0:N*4]
· cs
←
[0:N*4+2]
The
operation of IRET can be
written as:
· ip
←
[sp]
· sp
←
sp-2
· cs
←
[sp]
· sp
←
sp-2
· flag
←
[sp]
· sp
←
sp-2
The
above is the microcode
description of INT and IRET. To
obey an
assembly
language instruction the
processor breaks it down into
small
operations.
By reading the microcode of an
instruction its working can
be
completely
understood.
The
interrupt mechanism we have
studied is an extended far
call
mechanism.
It pushes FLAGS in addition to CS
and IP and it loads CS and
IP
with a
special mechanism of indirection. It is
just like the table of
contents
that is
located at a fixed position
and allows going directly to
chapter 3, to
chapter
4 etc. If this association is
changed in the table of
contents the
direction
of the reader changes. For
example if Chapter 2 starts at
page 220
while
240 is written in the table
of contents, the reader will go to
page 240
and
not 220. The table of
contents entry is a vector to
point to map the
chapter
number to page number. IVT
has 256 chapters and
the interrupt
mechanism
looks up the appropriate
chapter number to reach the
desired
page to
find the interrupt
routine.
Another
important similarity is that
table of contents is always
placed at
the
start of the book, a well
known place. Its physical position is
fixed. If
some
publishers put it at some place,
others at another place, the
reader will
be
unable to find the desired
chapter. Similarly in 8088
the physical memory
address
zero is fixed for the
IVT and it occupies exactly
a kilobyte of memory
as the
256x4=1K where 256 is the
number of possible interrupt
vectors while
the
size of one vector is 4
bytes.
Interrupts
introduce temporary breakage in
the program flow,
sometimes
programmed
(software interrupts) and
un-programmed at other
times
(hardware
interrupts). By hooking interrupts
various system
functionalities
can be
controlled. The interrupts
reserved by the processor
and having
special
functions in 8088 are listed
below:
· INT 0,
Division by zero
Meaning
the quotient did not
fit in the destination
register. This is a bit
different
as this interrupt does not
return to the next
instruction,
rather
it returns to the same
instruction that generated
it, a DIV
instruction
of course. Here INT 0 is automatically
generated by a DIV
when a
specific situation arises,
there is no INT 0 instruction.
· INT 1,
Trap, Single step
Interrupt
This
interrupt is used in debugging with
the trap flag. If the
trap flag is
set
the Single Step Interrupt is
generated after every
instruction. By
hooking
this interrupt a debugger
can get control after
every
instruction
and display the registers
etc. 8088 was the first
processor
that
has this ability to support
debugging.
· INT 2,
NMI-Non Maskable
Interrupt
Real
interrupts come from outside
the processor. INT 0 is not
real as it
is
generated from inside. For
real interrupts there are
two pins in the
processor,
the INT pin and the NMI pin.
The processor can be
directed
to
listen or not to listen to
the INT pin. Consider a
recording studio,
when
the recording is going on,
doors are closed so that
no
interruption
occurs, and when there is a
break, the doors are
opened
so that
if someone is waiting outside
can come it. However if
there is an
urgency
like fire outside then
the door must be broken and
the
recording
must not be catered for. For
such situations is the NMI
pin
97
Computer
Architecture & Assembly Language
Programming
Course
Code: CS401
CS401@vu.edu.pk
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.
8.2.
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
8.1
001
; hooking divide by zero
interrupt
002
[org
0x0100]
003
jmp
start
004
005
message:
db
'You divided
something by zero.', 0
006
007-029
;;;;; COPY LINES
028-050 FROM EXAMPLE 7.4 (strlen)
;;;;;
030-049
;;;;; COPY LINES
005-024 FROM EXAMPLE 7.1 (clrscr)
;;;;;
050-090
;;;;; COPY LINES
050-090 FROM EXAMPLE 7.4 (printstr)
;;;;;
091
092
; divide by zero interrupt
handler
093
myisrfor0:
push
ax
; push all
regs
094
push
bx
095
push
cx
096
push
dx
097
push
si
098
push
di
099
push
bp
100
push
ds
101
push
es
102
103
push
cs
104
pop
ds
; point ds to our data
segment
105
106
call
clrscr
; clear the
screen
107
mov
ax, 30
108
push
ax
; push x
position
109
mov
ax, 20
110
push
ax
; push y
position
111
mov
ax,
0x71
; white on blue
attribute
112
push
ax
; push
attribute
113
mov
ax,
message
114
push
ax
; push offset of
message
115
call
printstr
; print
message
116
117
pop
es
118
pop
ds
119
pop
bp
98
Computer
Architecture & Assembly Language
Programming
Course
Code: CS401
CS401@vu.edu.pk
120
pop
di
121
pop
si
123
pop
dx
124
pop
cx
125
pop
bx
126
pop
ax
127
iret
; return from
interrupt
128
129
; subroutine to
generate a divide by zero interrupt
130
genint0:
mov ax,
0x8432
; load a big
number in ax
131
mov bl,
2
; use a very small
divisor
132
div
bl
; interrupt 0 will be
generated
133
ret
134
135
start:
xor
ax, ax
136
mov
es, ax
; load zero in
es
137
mov
word [es:0*4],
myisrfor0 ; store offset at n*4
138
mov
[es:0*4+2],
cs
; store segment at
n*4+2
139
call
genint0
; generate
interrupt 0
140
141
mov ax,
0x4c00
; terminate
program
142
int
0x21
We
often push all registers in
an interrupt service routine
just to be
93-101
sure
that no unintentional modification to
any register is made.
Since
any code may be interrupted an
unintentional modification
will be
hard to debug
Since
interrupt can be called from
anywhere we are not sure
about
103-104
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.
8.3.
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
99
Computer
Architecture & Assembly Language
Programming
Course
Code: CS401
CS401@vu.edu.pk
important
programs; BIOS and OS. OS
services are high level
and build upon
the
BIOS services. BIOS services
are very low level. A level
further lower is
only
directly controlling the
hardware. BIOS services
provide a hardware
independent
layer above the hardware
and OS services provide
another
higher
level layer over the
BIOS services. We have
practiced direct
hardware
access
with the video device
directly without using BIOS
or DOS. The layer of
BIOS
provides services like
display a character, clear
the screen, etc. All
these
layers are optional in that
we can skip to whatever
lower layer we want.
The
most logical way to provide
access to firmware is to use
the interrupt
mechanism.
Specific services are
provided at specific interrupts.
CALL could
also
have been used but in that
case every manufacturer
would be required
to
place specific routines at
specific addresses, which is not a
flexible
mechanism.
Interrupts provide standard
interrupt number for the
caller and
flexibility
to place the interrupt
routine anywhere in the
memory for the
manufacturer.
Now for the programmer it is
decided that video services
will
be
provided at INT 10 but the actual
address of the video
services can and do
vary on
computers from different
manufacturers. Any computer that is
IBM
compatible
must make the video services
accessible through INT
10.
Similarly
keyboard services are
available at INT 16 and this is
standard in
every
IBM compatible. Manufacturers place
the code wherever they want
and
the
services are exported
through this
interrupt.
BIOS
exports its various services
through different interrupts.
Keyboard
services
are exported through INT 16,
parallel port services
through INT 17
and
similarly others through
different interrupts. DOS
has a single entry
point
through INT 21 just like a pin
hole camera, this single
entry points
leads
to a number of DOS services. So how
one interrupt provides a
number
of
different services. A concept of
service number is used here
which is a
defecto
standard in providing multiple
services through an interrupt. INT
10
is for
video services and each of
character printing service,
screen clearing
service,
cursor movement service etc.
has a service number
associated to it.
So we
say INT 10 service 0 is used
for this purpose and INT 10
service 1 is
used
for that purpose etc.
Service numbers for
different standard services
are
also
fixed for every IBM
compatible. The concept of
exported services
through
interrupts
is expanded with the service
numbering scheme.
The
service number is usually
given in the AH register.
Sometimes these
256
services seem less. For
example DOS exports
thousands of services. So
will be
often seen an extension to a
level further with sub-services.
For
examples
INT 10 character generator services
are all provided through
a
single
service number and the
services are distinguished with a
sub-service
number.
The
finally selected service
would need some arguments
for it to work. In
interrupts
arguments are usually not
given through stack, rather
registers
are
used. The BIOS and
DOS specifications list which
register contains
which
argument for a particular
service of a particular
interrupt.
We will
touch some important BIOS
and DOS services and
not cover it
completely
neither is it possible to cover it in
this space. A very
comprehensive
reference of interrupts is the
Ralph Brown List. It is just
a
reference
and not to be studied from
end to end. All interrupts
cannot be
remembered
and there is no need to
remember them.
The
service number is almost
always in AH while the
sub-service number
is in AL or BL
and sometimes in other
registers. The documentation of
the
service
we are using will list which
register should hold what
when the
interrupt
is invoked for that
particular service.
Our
first target using BIOS is
video so let us proceed to
our first program
that
uses INT 10 service 13 to print a
string on the screen. BIOS
will work
even if
the video memory is not at
B8000 (a very old video
card) since BIOS
knows
everything about the
hardware and is hardware
specific.
100
Computer
Architecture & Assembly Language
Programming
Course
Code: CS401
CS401@vu.edu.pk
Example
8.2
001
; print string using bios
service
002
[org
0x0100]
003
jmp
start
004
message:
db
'Hello
World'
005
006
start:
mov
ah,
0x13
;
service 13 - print
string
007
mov
al, 1
;
subservice 01
update cursor
008
mov
bh, 0
;
output on page
0
009
mov
bl, 7
;
normal
attrib
010
mov
dx,
0x0A03
;
row 10
column 3
011
mov
cx, 11
;
length of
string
012
push
cs
013
pop
es
; segment of
string
014
mov
bp,
message
; offset of
string
015
int
0x10
; call BIOS video
service
016
017
mov
ax,
0x4c00
; terminate
program
018
int
0x21
The
sub-service are versions of
printstring that update and
do not
007
update
the cursor after printing
the string etc.
Text
video screen is in the form
of pages which can be upto
32. At
008
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.
101
Computer
Architecture & Assembly Language
Programming
Course
Code: CS401
CS401@vu.edu.pk
Example
8.3
001
; print string and
keyboard wait using BIOS services
002
[org
0x100]
003
jmp
start
004
005
msg1:
db
'hello world',
0
006
msg2:
db
'hello world
again', 0
007
msg3:
db
'hello world again
and again', 0
008
009-028
;;;;; COPY LINES
005-024 FROM EXAMPLE 7.1 (clrscr)
;;;;;
029-069
;;;;; COPY LINES
050-090 FROM EXAMPLE 7.4 (printstr)
;;;;;
070-092
;;;;; COPY LINES
028-050 FROM EXAMPLE 7.4 (strlen)
;;;;;
093
094
start:
mov
ah,
0x10
;
service 10
vga attributes
095
mov
al, 03
;
subservice 3
toggle blinking
096
mov
bl, 01
;
enable blinking
bit
097
int
0x10
;
call BIOS video
service
098
099
mov
ah, 0
; service 0 get
keystroke
100
int
0x16
; call BIOS
keyboard service
101
102
call clrscr
; clear the
screen
103
104
mov
ah, 0
; service 0 get
keystroke
105
int
0x16
; call BIOS
keyboard service
106
107
mov
ax, 0
108
push
ax
; push x
position
109
mov
ax, 0
110
push
ax
; push y
position
111
mov
ax, 1
; blue on
black
112
push
ax
; push
attribute
113
mov
ax,
msg1
114
push
ax
; push offset of
string
115
call
printstr
; print the
string
116
117
mov
ah, 0
; service 0 get
keystroke
118
int
0x16
; call BIOS
keyboard service
119
120
mov
ax, 0
121
push
ax
; push x
position
123
mov
ax, 0
124
push
ax
; push y
position
125
mov
ax,
0x71
; blue on
white
126
push
ax
; push
attribute
127
mov
ax,
msg2
128
push
ax
; push offset of
string
129
call
printstr
; print the
string
130
131
mov
ah, 0
; service 0 get
keystroke
132
int
0x16
; call BIOS
keyboard service
133
134
mov
ax, 0
135
push
ax
; push x
position
136
mov
ax, 0
137
push
ax
; push y
position
138
mov
ax,
0xF4
; red on white
blinking
139
push
ax
; push
attribute
140
mov
ax,
msg3
141
push
ax
; push offset of
string
142
call
printstr
; print the
string
143
144
mov
ah, 0
; service 0 get
keystroke
145
int
0x16
; call BIOS
keyboard service
146
147
mov
ax,
0x4c00
; terminate
program
148
int
0x21
This
service has no parameters so
only the service number
is
099-100
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.
102
Computer
Architecture & Assembly Language
Programming
Course
Code: CS401
CS401@vu.edu.pk
EXERCISES
1.
Write a TSR that forces a
program to exit when it
tries to become a
TSR
using INT 21h/Service 31h by converting
its call into INT
21h/Service
4Ch.
2.
Write a function to clear
the screen whose only
parameter is always
zero.
The function is hooked at
interrupt 80h and may also be
called
directly
both as a near call and as a
far call. The function
should
detect
how it is called and return
appropriately. It is provided that
the
direction
flag will be set before the
function is called.
3.
Write a function that takes
three parameters, the
interrupt number
(N)
and the segment and
offset of an interrupt handler
XISR. The
arguments
are pushed in the order N,
XISR's offset and
XISR's
segment.
It is known that the first two
instructions of XISR are
PUSHF
and CALL 0:0 followed by
the rest of the interrupt
handler.
PUSHF
instruction is of one byte
and far call is of 5 bytes
with the
first
byte being the op-code,
the next two containing the
target offset
and
the last two containing the
target segment. The function
should
hook
XISR at interrupt N and chain it to
the interrupt handler
previously
hooked at N by manipulating the
call 0:0 instruction
placed
near the start of
XISR.
4.
Write a TSR that provide
the circular queue services
via interrupt
0x80
using the code written in
Exercise 5.XX. The
interrupt
procedure
should call one of qcreate,
qdestroy, qempty,
qadd,
qremove,
and uninstall based on the
value in AH. The
uninstall
function
should restore the old
interrupt 0x80 handler and
remove
the
TSR from memory.
103
Table of Contents:
|
|||||