Title: Lecture 4: Interrupts in Turbo C
1Lecture 4 Interrupts in Turbo C
- Embedded Systems
- Black box description
- Access Keyboard, Video
- Software Engineering
- Functions Prototype, definition, call
- Local/Global Variables
- Lab requirement
- Advance reading materials
2Bitwise and
- One bit (0)(0)0, (0)(1)0, (1)(0)0,
(1)(1)1 - two bits (01)(10)0, (10)(11)10,
(11)(01)01, (11)(11)11. - 0x stands for hexadecimal notations
0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F - where A stands for ten, B eleven, C, twelve, D
thirteen, E fourteen, F fifteen. - Bitwise and of two hexadecimal numbers
(0x7)(0xb)? - First, write them in binary (0111)(1011)
- do any bit by bit 0011
- write it back to hexadecimal 0x3
- in decimal 3
- Possible quiz/exam question what is the value of
(100)(45) ?
3The Flag Register in IBM PC
15
0
CF
PF
AF
ZF
SF
TF
IF
DF
OF
_FLAGS(0x0040) is the same as _FLAGS(0000 0000
0100 0000) which is 0x0040 if ZF is 1 and zero if
ZF is zero. Similarly, _FLAGS(0x0200) is the
same as _FLAGS(0000 0010 0000 0000) which is
0x0200 if IF is 1 and zero if IF is
zero. Possible quiz/exam question how to test
if SF is one or zero?
4Ports/Addresses of Devices
Addresses
Devices
DMA controller 000-01F Interrupt
controller 020-03F Timer 040-05F Keyboard 060
-063 NMI (non-maskable interrupt) 070-07F DMA page
register 080-08F Interrupt controller
2 0A0-0BF DMA controller 2 0C0-0DF Clear/reset
math coprocessor 0F0-0F1 Math coprocessor 0F2-0FF
Fixed Disk 1F0-1F8 Joystick (game
controller) 200-207 Parallel printer
(secondary) 278-27F Serial port
(secondary) 2F8-2FF Monochrome adapter/printer 3B0
-3BF Color/graphics adapter 3D0-3DF Diskette
controller 3F0-3F7 Serial port
(primary) 3F8-3FF
5Enable Device for Keyboard
A0
Address lines
A7
Keyboard at 0x60-63 in binary they
are 01100000-01100011
Possible quiz/exam question draw the enable
device for serial port
Enable for device
AND gate
6Interrupt as a Black Box
- A black box performs certain operations in a
magic way that user may not know. - What user knows are
- input (preconditions)
- output(postconditions)
- In handout Chapter 11, we have the black box
description of video interrupt, and 12, of
keyboard interrupt.
7Black Box Description of Interrupt 0x16 service
0x16
- Precondition service number 0 in AH.
- Postcondition if there is no key in the keyboard
buffer, wait until one appears - ascii code of the key stored in AL
- PC-keyboard scan code stored in AH
- the character is removed from the buffer.
- Warning this service hang the program until a
character appears in keyboard buffer. - (see page 358 of handout chapter 12)
8A function to get a key
- char get_a_key () //prototype
- //return type char parameter list
nil function name get_a_key - //precondition nil postcondition return the
next key in the keyboard buffer - //warning the function hangs the program until a
character is read. - char get_a_key () //implementation
- char a
- _AH0x0 //service number 0x00
- geninterrupt(0x16) //interrupt 0x16
- a_AL //_AL is the ascii code for the key,
caste it to char - return a //return the key
9Use the black box description
- We can write functions to do other things using
the black box description in Chapter 11 and 12 of
the handout. - Possible quiz/exam question
- prototype a function that returns 1 if a key is
in the keyboard buffer, 0 else. - Possible lab quiz question
- Given the above prototype, implement it in turbo
c. - Advanced prototype and define a function that
returns true if F1 is pressed.
10Video Interrupt Services
Most of the useful video services are found in
the BIOS through interrupt 0x10. Some MS-DOS
video services are provided through interrupt
0x21. They are user programmed interrupts to
produce output to the video screen. Usually, one
puts the function/service number in the register
AH and then invokes the corresponding interrupt.
Very often there are some parameters for
these functions/services which are put in
register AL, BX, CX, or DX.
11Interrupt 0x10 Service 0x0E black box description
- Precondition
- The service number 0x0E is put in register AH.
- The char to be written is put in AL. The display
page number is put in BH and the foreground color
is in BL. - Postcondition
- The character is written at the cursor location,
and the cursor is advanced one position, wrapping
over to new line or scrolling the screen as
needed. - NOTE There are four characters that service 0x0E
reacts to according to their ASCII meaning 0x07
beep, 0x08 backspace, 0x0A linefeed, 0x0D
carriage return. All other characters are
displayed normally.
.
12A Function for Output a Char
- void output_a_char(int x) //prototype
- //precondition x is the ascii code of a
character - //postcondition the character is output to
screen - void output_a_char(int x) //definition
-
- _AH0x0E
- _ALx
- _BH1
- geninterrupt(0x10)
13Call the function to output characters
- output_a_char(97) //output A
- output_a_char(8) //backspace
- output_a_char(7) //output a ring
- output_a_char(0x0A) //a new line
14Caution when using Pseudo-Variables
Pseudo-variables refer to CPU registers which are
used by other programs which may run at the same
time. One must assign values right before using
them and read values right after obtaining them,
especially when we program in C. Be careful about
the following
- A pseudo-variable has no address
- The values one place in pseudo-variables may NOT
be preserved for any length of time. - Values of pseudo-variables may not remain the
same across a function call. - Do not change values of _CS, _SS, _SP, nor _BP
since they are used by machine code produced by
Turbo C compiler.
15More on Functions
- Review prototype, definition, call of function
- Local Variables/Global Variables
16User Defined Functions
- Function prototypes
- return_type function_name (parameter_list)
- here parameter_list is either empty or
- type_1 parameter_1 parameter_list
- //this is a recursive definition
- Function definitions
- return_type function_name (parameter_list)
- statements return a_value_of_return_type
- Function calls
- assign values to the variables in parameter_list
- match return_type in function call assignment.
17- A function definition is like a small program and
a function call is the same thing as running this
program. - include ltiostream.hgt
- int max(int x, int y) //function definition
- int tmpx
- if (tmplty) tmpy
- return tmp
- int main() int z
- zmax(3,4) //function call
- return 0
18- A function uses formal parameters, instead of
cin, for input. The arguments to the function
are the input and they are plugged in for the
formal parameters. - include ltiostream.hgt
- int max(int x, int y) //x3, y4 are assigned in
the - // following function call
- int tmpx if (tmplty) tmpy return tmp
- int main() int z
- zmax(3,4) //the first parameter is assigned 3
- // the second is assigned 4
- return 0
19- The output of a function is send back to the
program which calls this function, via the return
value. The function uses the return statement for
output purpose. - include ltiostream.hgt
- int max(int x, int y) int tmpx if (tmplty)
tmpy - return tmp//a value of 4 is returned as output
of max() - int main() int z
- zmax(3,4) //the returned value of 4 for max()
is - //assigned to z
- return 0
20Local Variables
- Variables declared within the body of a function
are its local variables (we also say the scope of
these variables is the body of this function.) In
the following, tmp is a local variable to the
function max(int,int). Its scope is from line two
to line five. - include ltiostream.hgt
- int max(int x, int y)
- int tmpx
- if (tmplty) tmpy
- return tmp
- int main() int z
- zmax(3,4)
- return 0
21- Variables declared within the body of the main()
function of a program is local to the main()
function. Here z is a local variable for main()
and its scope is between line 6 and line 8. - include ltiostream.hgt
- int max(int x, int y)
- int tmpx
- if (tmplty) tmpy
- return tmp
- int main() int z
- zmax(3,4)
- return 0
22- A local variable is completely unknown outside
its scope. Two local variables of different
scopes may have the same name. As in the previous
example, z and tmp has different scopes so we may
use the same variable name for them as in the
following - include ltiostream.hgt
- int max(int x, int y)
- int tmpx
- if (tmplty) tmpy
- return tmp
- int main() int tmp
- tmpmax(3,4)
- return 0
23- Moreover, a subfunction inside a function may
have a local variable of the same name as a local
variable to its parent function. Inside the
subfunction its local variable overshadows that
of its parent function. - include ltiostream.hgt
- int main()
- int max(int x, int y) //max() is a subfunction of
main() - int tmpx //the scope of tmp in max(int,int)
is between - if (tmplty) tmpy //line 3 and line 6. The
scope of tmp in return tmp // main()
is between line 2 and line 9. But its - int tmp // not known to function max(int, int)
since - tmpmax(3,4) //it is overshadowed by tmp in
max(int, int) - return 0
24- call-by-value mechanism by default, when a
function is called, the value of the arguments
are plugged in the formal parameters. More
specifically, if the arguments are variables,
their values not the variables themselves are
plugged in. - Variables declared in the parameter list of a
function are its local variables and thus their
scope is the body of this function. - include ltiostream.hgt
- void swapwrong(int x, int y) //x and y are local
variables and their values - int tmp //are unknown outside the scope of
swapwrong - tmpx xy ytmp //that is, outside line
2,3,4,5, they are unknown. - return
- int main() int x,y //local variables for
main() different from - x3 y4 coutltltx is ltlt xltlty isltlt
yltltendl//those for swapwrong(). - swapwrong(x,y) //this is equivalent to
swapwrong (3,4) - coutltltx is ltlt xltlty isltlt yltltendl//output
remains the same - return 0
25- call-by-reference mechanism use the symbol
for a variable in the parameter list of a
function prototype, this variable is passed to
the function as a call by reference variable - The control of the a variable, when calling the
function, is passed to the function. Thus, its
value can be changed within the function. - include ltiostream.hgt
- void swap(int x, int y) //x, y are
call-by-reference parameters - int tmp
- tmpx xy ytmp
- return
- int main() int a,b
- a3 b4 coutltlta is ltlt altltb isltlt bltltendl
- swap(a,b) //call to swap(int,int) and
replace x by a, y by b - coutltlta is ltlt altltb isltlt bltltendl//output will
be 4 followed by 3 - return 0
26- include ltiostream.hgt
- void swap(int x, int y) //x, y are
call-by-reference parameters - int tmp
- tmpx xy ytmp
- return
- int main() int a,b
- a3 b4 coutltlta is ltlt altltb isltlt bltltendl
- swap(a,b) //call to swap(int,int) and
replace x by a, y by b - coutltlta is ltlt altltb isltlt bltltendl//output will
be 4 followed by 3 - return 0
- The above call to swap(a,b) is equivalent to do
the following in swap() - replace x by a and replace y by b
- run swap line by line
- int tmp
- tmpa ab btmp //a becomes 4 and b becomes 3.
- return
27- A possible quiz/exam question
- Consider the following program and tell what is
the output? - include ltiostream.hgt
- void a_function(int x, int y)
- int tmp tmpx xy ytmp return
- int main() int a,b
- a3 b4 coutltlta is ltlt altltb isltlt bltltendl
- a_function(a,b)
- coutltlta is ltlt altltb isltlt bltltendl
- return 0
28- Global constant a universal constant declared in
the problem outside all functions. It can be used
by all functions but can be changed by none of
them. - includeltiostreamgt
- const double PI3.1415926
- double area (double radius) return
PIradiusradius/2 - double circumference(double radius) return
2PIradius - main () double radius
- cout ltlt Input the radius of a circleltltendl
- cin gtgt radius
- outputltltIts circumference isltltcircumference(rad
ius)ltltendl - coutltltIts area isltltarea(radius)ltltendl
- PI3.1415927 //a compiler error
29- Global variable universal for the problem,
declared in the problem outside all functions. It
can be used and changed by them. - includeltiostreamgt
- const double PI3.1415926
- double radius
- double area () return PIradiusradius/2
- double circumference() return 2PIradius
- main ()
- cout ltlt Input the radius of a circleltltendl
- cin gtgt radius
- outputltltIts circumference isltltcircumference()ltlt
endl - coutltltIts area isltltarea()ltltendl
30Top Down Design
- Consider a program which takes two numbers and
output them in increasing order. We divide them
into subtasks - take input
- order them
- output results
- In the implementation part, we write a function
for each of them. Thus our main program is - main() int x, y
- take_input(x,y) order(x,y) give_output(x,y)
31- the prototype of
- void take_input(int x,int y) //get 2 inputs
from //keyboard store in x and y as
call-by-reference variable - the definition
- void take_input(int x,int y)
- cout ltlt Enter two integersltltendl
- cin gtgt x gtgt y
- return
Here is an example of void function for which we
end the function by a statement return
32- the prototype of
- void order(int x,int y) //order x and y
- the definition
- void order(int x,int y)
- if (xgty) swap(x,y)
- return
Here we have an example of calling a function
from another function.
33- the prototype of
- void give_output(int x,int y) //puts the values
of x/y on to the screen. - the definition
- void give_output(int x,int y)
- cout ltlt In increasing order the two integers
are - cout ltlt x ltltand ltlt yltltendl
- return
34Preconditions and Postconditions
- For each function prototype, it is important to
state, as comments, what conditions are assumed
true of the parameters before the function is
called (the preconditions) and state what happens
to the parameters after the function is returned
(the postconditions).
35- swap(int x, int y)
- //precondition x and y are assigned values
- //postcondition the values of x and y are
exchanged - void take_input(int x,int y)
- //precondition null
- //postcondition 2 inputs from keyboard are in
x/y - void order(int x,int y)
- //precondition x and y are assigned values
- //postcondition x and y are in increasing order
now - void give_output(int x,int y)
- //precondition x and y are assigned values
- //values of x/y are put on the screen.
36LAB requirement
- Choose an interrupt service (video/keyboard) and
put it in function form. - Practice local variables and global variables
using the examples given in the class.
37Addressing Memory in PC
- Memory is divided into blocks of size 64K bytes
each. - 1K210 bytes
- Address is divided into two numbers of two bytes
each - the segment number
- the offset number
- The exact address is 0x10 times the segment
number (or shift 4 bit position to the left),
then, plus the offset number. - Since the offset number is two bytes, it covers
21664K memory locations (Thus, one block is
64K). - However, there are possibly two ways to represent
one memory location - segment number 0x1000 offset number 0xFFFF is
0x1FFFF - segment number 0x1F00 offset number 0x0FFF is
also 0x1FFFF
38Interrupt Vectors
- A vector is a memory address which contains the
address of an interrupt handler - The address of an interrupt n is at the segment
number (stored in n42) and offset number stored
in n4. - The exact address is 0x10 times the segment
number (or shift 4 bit position to the left),
then, plus the offset number.
- In Turbo C, there are two library routines which
allow for changes in interrupt vectors - setvect(int_num,point_to_handler) //it sets the
interrupt int_num to point to point_to_handler. - getvect(int_num) //return a far pointer in the
vector.
39Define a struct in Turbo C
- Syntax
- struct struct_type
-
- variable-type variable_name
- variable-type variable_name
-
- variable-type variable_name
- //dont forget this
- struct CharInt
-
- char x
- int y
-
Declare a variable of user defined
struct-type struct_type struct_name //after
struct_type is defined CharInt key_and_num
40A Function to get a key and its key number
- struct CharInt char x int y //define a
struct type - CharInt get_key_number () //return type of the
function is CharInt - char a int b
- CharInt tmp
- _AH0x0 //service number 0x00
- geninterrupt(0x16) //interrupt 0x16
- a_AL b_AH //_AL is the key and _AH is the
keynumber - tmp.xa tmp.yb //assign them to a variable of
type CharInt - return tmp //return the value
41Write a function to get a character
- int key_ready() //return 1 if a key is ready, 0
otherwise - long int x
- _AH1 //service number 0x01
- geninterrupt(0x16) //interrupt 0x16
- x_FLAGS //get flag register
- if (x(0x40)0) return 1 //if ZF0 a key is
ready - else return 0 //else no key
-
- char read_a_key() //return char if a key is
ready - if (key_ready())
- return get_key_number().x
- else return 0
42Time Services (Clock)
- Timer chip as three output channels.
- Channel 0 system clock tick timer. Oscillate
18.2 ticks per second. Interrupt 0x08 is
generated each time the clock ticks - Channel 1 dedicated to producing the RAM refresh
timing signal not for use in programs. - Channel 2 used to control the computers
speaker. Its frequency determines the frequency
of the sound emitted by the loudspeaker. - Interrupt 0x21 Function 0x2C CH contains the
hours (0-23), CL contains the minutes (0-59), DH
contains the seconds (0-59), DL contains
hundredths of a second (0-99).
43Time Services (Clock)
- struct the_time int hrs, mins, secs, hundth
- the_time get_time()
- the_time tmp
- int I,j,k,l
- _AH0x2C //service 0x2C for get time
- interrupt(0x21) //interrupt 0x21
- I_CH j_CL k_DH l_DL
- tmp.hrsI tmp.minsj tmp.secsk tmp.hundthl
- return tmp
44Get the Time of Hitting a Key
Using the above functions written with
interrupts, we may obtain the approximate time
of hitting a key as follows call function
read_a_key() call function get_time()