System Programming - CS609 Handouts
System Programming - CS609 Handouts
CS609
Knowledge beyond
CS609-System Programming
VU
Table of Contents
01 - Introduction, Means of I/O...........................................................................................3
02 - Interrupt Mechanism...................................................................................................11
03 - Use of ISRs for C Library Functions..........................................................................19
04 - TSR programs and Interrupts......................................................................................26
05 - TSR programs and Interrupts (Keyboard interrupt)....................................................33
06 - TSR programs and Interrupts (Disk interrupt, Keyboard hook).................................40
07 - Hardware Interrupts....................................................................................................46
08 - Hardware Interrupts and TSR programs.....................................................................54
09 - The interval Timer.......................................................................................................68
10 - Peripheral Programmable Interface (PPI)...................................................................76
11 - Peripheral Programmable Interface (PPI) II...............................................................83
12 - Parallel Port Programming..........................................................................................95
13 - Serial Communication..............................................................................................103
14 - Serial Communication (Universal Asynchronous Receiver Transmitter).................110
15 - COM Ports................................................................................................................117
16 - COM Ports II............................................................................................................125
17 - Real Time Clock (RTC)............................................................................................133
18 - Real Time Clock (RTC) II.........................................................................................146
19 - Real Time Clock (RTC) III.......................................................................................155
20 - Determining system information..............................................................................163
21 - Keyboard Interface....................................................................................................172
22 - Keyboard Interface, DMA Controller.......................................................................180
23 - Direct Memory Access (DMA).................................................................................186
24 - Direct Memory Access (DMA) II.............................................................................192
25 - File Systems..............................................................................................................199
26 - Hard Disk..................................................................................................................207
27 - Hard Disk, Partition Table........................................................................................216
28 - Partition Table II.......................................................................................................223
29 - Reading Extended Partition......................................................................................229
30 - File System Data Structures (LSN, BPB).................................................................236
31 - File System Data Structures II (Boot block).............................................................244
32 - File System Data Structures III (DPB).....................................................................249
33 - Root Directory, FAT12 File System..........................................................................256
34 - FAT12 File System II, FAT16 File System...............................................................262
35 - FAT12 File System (Selecting a 12-bit entry within FAT12 System).......................267
36 - File Organization......................................................................................................274
37 - FAT32 File System....................................................................................................283
38 - FAT32 File System II................................................................................................291
39 - New Technology File System (NTFS)......................................................................301
40 - Disassembling the NTFS based file..........................................................................306
41 - Disk Utilities.............................................................................................................312
42 - Memory Management...............................................................................................317
43 - Non-Contiguous memory allocation.........................................................................324
44 - Address translation in Protected mode......................................................................329
45 - Viruses.......................................................................................................................332
CS609-System Programming
VU
While designing software the programmer may determine the required inputs for
that program, the wanted outputs and the processing the software would perform
in order to give those wanted outputs. The implementation of the processing part
is associated with application programming. Application programming facilitates
the implementation of the required processing that software is supposed to
perform; everything that is left now is facilitated by system programming.
Systems programming is the study of techniques that facilitate the acquisition of
data from input devices, these techniques also facilitates the output of data which
may be the result of processing performed by an application.
Three Layered Approach
A system programmer may use a three layered approach for systems
programming. As you can see in the figure the user may directly access the
programmable hardware in order to perform I/O operations. The user may use
the trivial BIOS (Basic Input Output System) routines in order to perform I/O in
which case the programmer need not know the internal working of the hardware
and need only the knowledge BIOS routines and their parameters.
In this case the BIOS programs the hardware for required I/O operation which is
hidden to the user. In the third case the programmer may invoke operating
systems (DOS or whatever) routines in order to perform I/O operations. The
operating system in turn will use BIOS routines or may program the hardware
directly in order to perform the operation.
No I/O device is directly connected to the CPU. To provide control signals to the
I/O device a I/O controller is required. I/O controller is located between the CPU
and the I/O device. For example the monitor is not directly collected to the CPU
rather the monitor is connected to a VGA card and this VGA card is in turn
connected to the CPU through busses. The keyboard is not directly connected to
CPU rather its connected to a keyboard controller and the keyboard controller is
connected to the CPU. The function of this I/O controller is to provide
I/O control signals
Buffering
Error Correction and Detection
We shall discuss various such I/O controllers interfaced with CPU and also the
techniques and rules by which they can be programmed to perform the required
I/O operation.
Some of such controllers are
DMA controller
Interrupt controller
Programmable Peripheral Interface (PPI)
Interval Timer
Universal Asynchronous Receiver Transmitter
We shall discuss all of them in detail and how they can be used to perform I/O
operations.
Operating systems
Systems programming is not just the study of programmable hardware devices.
To develop effective system software one needs to the internals of the operating
system as well. Operating systems make use of some data structures or tables
for management of computer resources. We will take up different functions of the
operating systems and discuss how they are performed and how can the data
structures used for these operations be accessed.
Copyright Virtual University of Pakistan
In case of programmed I/O the CPU is in a constant loop checking for an I/O
opportunity and when its available it performs the computations operations
required for the I/O operations. As the I/O devices are generally slower than the
CPU, CPU has to wait for I/O operation to complete so that next data item can be
sent to the device. The CPU sends data on the data lines. The device need to be
signaled that the data has been sent this is done with the help of STROBE signal.
An electrical pulse is sent to the device by turning this signal to 0 and then 1. The
device on getting the strobe signal receives the data and starts its output. While
the device is performing the output its busy and cannot accept any further data
on the other and CPU is a lot faster device and can process lot more bytes during
the output of previously sent data so it should be synchronized with the slower
I/O device. This is usually done by another feed back signal of BUSY which is
kept active as long as the device is busy. So the CPU is only waiting for the
Copyright Virtual University of Pakistan
Literally to interrupt means to break the continuity of some on going task. When
we talk of computer interrupt we mean exactly the same in terms of the
processor. When an interrupt occurs the continuity of the processor is broken and
the execution branches to an interrupt service routine. This interrupt service
routine is a set of instruction carried out by the CPU to perform or initiate an I/O
operation generally. When the routine is over the execution of the CPU returns to
the point of interruption and continues with the on going process.
10
11
02 - Interrupt Mechanism
Interrupt Mechanism
Interrupt follow a follow a certain mechanism for their invocation just like near or far
procedures. To understand this mechanism we need to understand its differences with
procedure calls.
Difference between interrupt and procedure calls
Procedures or functions of sub-routines in various different languages are called by
different methods as can be seen in the examples.
Call MyProc
A= Addition(4,5);
Printf(hello world);
The general concept for procedure call in most of the programming languages is that on
invocation of the procedure the parameter list and the return address (which is the value if
IP register in case of near or the value of CS and IP registers in case of far procedure) is
pushed Moreover in various programming languages whenever a procedure is called its
address need to be specified by some notation i.e. in C language the name of the
procedure is specified to call a procedure which effectively can be used as its address.
However in case of interrupts the a number is used to specify the interrupt number in the
call
Int 21h
Int 10h
Int3
Fig 1 (Call to interrupt service routine and procedures/functions)
Moreover when an interrupt is invoked three registers are pushed as the return address i.e.
the values of IP, CS and Flags in the described order which are restored on return. Also no
Copyright Virtual University of Pakistan
12
Moreover it is important to understand the meaning of the four bytes within the interrupt
vector. Each entry within the IVT contains a far address the first two bytes (lower word)
of which is the offset and the next two bytes (higher word) is the segment address.
13
Name
--------
IO
Size
-----000400
000100
000200
000370
CON
AUX
PRN
CLOCK$
COM1
LPT1
LPT2
LPT3
COM2
COM3
COM4
System Data
System Device
System Device
System Device
System Device
System Device
System Device
System Device
System Device
System Device
System Device
System Device
Driver
Driver
Driver
Driver
Driver
Driver
Driver
Driver
Driver
Driver
Driver
000A70
MSDOS
002080
IO
002030
KBD
000CE0
HIMEM
0004E0
XMSXXXX0
000490
000090
000120
0007D0
COMMAND
000A20
MSDOS
000070
COMMAND
0006D0
DOSX
0087A0
MEM
000610
MEM
0174E0
MSDOS
07AAD0
SYSTEM
02F000
System Data
System Program
DEVICE=
Installed Device Driver
FILES=
FCBS=
LASTDRIVE=
STACKS=
Program
-- Free -Environment
Program
Environment
Program
-- Free -System Program
IO
MOUSE
MSDOS
MSCDEXNT
REDIR
DOSX
MSDOS
System Data
System Program
-- Free -Program
Program
Data
-- Free --
0040C0
004AF0
004B70
005250
00DA00
00E020
025510
09FFF0
0CF000
0D2110
0D2720
0D2900
0D3380
0D3410
001610
Type
-----Interrupt Vector
ROM Communication Area
DOS Communication Area
003100
0030F0
000600
0001D0
000A70
000080
00CBE0
System Data
Interrupt Invocation
Although hardware and software interrupts are invoked differently i.e hardware interrupts
are invoked by means of some hardware whereas software interrupts are invoked by
means of software instruction or statement but no matter how an interrupt has been
invoked processor follows a certain set steps after invocation of interrupts in exactly same
way in both the cases. These steps are listed as below
Push Flags, CS, IP Registers, Clear Interrupt Flag
Use (INT#)*4 as Offset and Zero as Segment
Copyright Virtual University of Pakistan
15
17
B8
B8
EA
B8
B8
B8
8A
03
10
10
AE
10
10
10
04
-a
0AF1:0100 int 21
0AF1:0102
-r
AX=0000 BX=0000
DS=0AF1 ES=0AF1
0AF1:0100 CD21
-t
AX=0000 BX=0000
DS=0AF1 ES=0AF1
00A7:107C 90
-d ss:ffe8
0AF1:FFE0
0AF1:FFF0
00
55
A7
A7
10
A7
A7
A7
10
05
00
00
A7
00
00
00
02
7C
86
54
B8
00
B8
B8
B8
10
10
02
10
E8
10
10
10
A7
A7
70
A7
00
A7
A7
A7
00-4F
00-90
00-F2
00-40
F0-B8
00-B8
00-B8
00-B8
03
10
04
01
10
10
10
10
55
A7
74
21
A7
A7
A7
A7
05
00
CC
04
00
00
00
00
8A
9A
B8
50
C4
B8
B8
B8
03
10
10
09
23
10
10
10
55
A7
A7
AB
02
A7
A7
A7
05
00
00
D4
C9
00
00
00
|...O.U...U.
..U.............
....T.p...t.....
........@.!.P...
.............#..
................7
................
................
....
CX=0000 DX=0000
SS=0AF1 CS=0AF1
INT
21
SP=FFEE
IP=0100
CX=0000 DX=0000
SS=0AF1 CS=00A7
NOP
SP=FFE8
IP=107C
02 01 F1 0A 02 F2 00 00
00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
The dump at the address 0000:0084 H shows the value of the vector of the interrupt #
21H i.e. 21H * 4 = 84H. This address holds the value 107CH in lower word and 00A7H
in the higher word which indicates that the segment address of interrupt # 21 is 00A7H
and the offset address of this ISR is 107CH.
Moreover the instruction INT 21H can be assembled and executed in the debug program,
on doing exactly so the instruction is traced through and the result is monitored. It can be
seen that on execution of this instruction the value of IP is changed to 107CH and the
value of CS is changed to 00A7H which cause the execution to branch to the Interrupt #
21H in memory and the previous values of flags, CS and IP registers are temporarily
saved onto the stack as the value of SP is reduced by 6 and the dump at the location
SS:SP will show these saved values as well.
Parameter passing into Software interrupts
In case of procedures or function in various programming languages parameters are
passed through stack. Interrupts are also kind of function provided by the operating
system but they do not accept parameters by stack rather they need to passed parameters
through registers.
Software interrupts invocation
Now lets see how various interrupts can be invoked by means of software statements.
First there should be way to pass parameters into a software interrupt before invoking the
Copyright Virtual University of Pakistan
16
18
Service # 42H
AL = Move Technique
BX = File Handle
CX-DX = No of Bytes File to be moved
AH = Service # = 42H
Output
DX-AX = No of Bytes File pointer actually moved.
This service is used to move the file pointer to a certain position relative to a certain
point. The value in AL specify the point relative to which the pointer is moved. If the
value of AL = 0 then file pointer is moved relative to the BOF (begin of File) if AL=1
then its moved relative to current position and if AL = 2 then its moved relative to the
EOF (end of file).
CX-DX specify the number of bytes to move a double word is needed to specify this
value as the size of file in DOS can be up to 2 GB.
On return of the service DX-AX will contain the number of bytes the file pointer is
actually moved eg. If the file pointer is moved relative to the EOF zero bytes the DX-AX
on return will contain the size of file if the file pointer was at BOF before calling the
service.
Copyright Virtual University of Pakistan
19
20
Service # 01H
Entry
AH = 01
CH = Beginning Scan Line
CL = Ending Scan Line
On Exit
Unchanged
The size of the cursor depends upon the number of net scan lines used to display the
cursor if the beginning scan line is greater than the ending scan line the cursor will
disappear. The following tries to accomplish just that
void main()
{
char st[80];
union REGS regs;
regs.h.ah = 0x01;
regs.h.ch = 0x01;
regs.h.cl = 0x00;
int86(0x10,®s,®s); //corrected
gets(st);
}
The program is quite self explanatory as it puts the starting scan line to be 1 and the
ending scan line to be 0. Henceforth when the service execute the cursor will disappear.
Use of ISRs for C Library functions
There are various library function that a programmer would typically use in a program to
perform input output operations. These library functions perform trivial I/O operations
like character input (putch()) and character output (getch(), getc() etc). All
these function call various ISRs to perform this I/O. In BIOS and DOS documentation
number of services can be found that lie in correspondence with some C library function
in terms of its functionality.
Writing S/W ISRs
Lets now see how can a programmer write an ISR routine and what needs to be done in
order make the service work properly. To exhibit this we will make use of an interrupt
which is not used by DOS or BIOS so that our experiment does not put any interference
to the normal functions of DOS and BIOS. One such interrupt is interrupt # 65H. The
vector of int 65H is typically filled with zeros another indication that it is not being used.
Getting interrupt vector
As we have discussed earlier IVT is a table containing 4 byte entries each of which is a
far address of an interrupt service routine. All the vectors are arranged serially such that
the interrupt number can be used as an index into the IVT.
Getting interrupt vector refers to the operation which used to reading the far address
stored within the vector. The vector is double word, the lower word of it being the offset
address and the higher word being the segment address. Moreover the address read from a
vector can be used as a function pointer. The C library function used to do the exactly
Copyright Virtual University of Pakistan
21
Function pointers
Another thing required to be understood are the function pointers. C language is a very
flexible language just like there are pointers for integers, characters and other data types
there are pointers for functions as well as illustrated by the following example
void myfunc()
{
}
void
(*funcptr) ( )
funcptr = myfunc;
(*funcptr) ( );
myfunc();
There are three fragments of code in this example. The first fragment shows the
declaration of a function myfunc()
The second fragment show declaration of a pointer to function named funcptr which is
a pointer to a function that returns void.
In the third fragment funcptr is assigned the address of myfunc as the name of the
function can be used as its address just like in the cases of arrays in C. Then the function
pointed by funcptr by the statement (*funcptr)(); is called and then the original
myfunc() is called. The user will observe in both the cases same function myproc()
will be invoked.
22
23
}
setvect(0x08, newint);
C program making use of Int 65H
Here is a listing of a program that makes use of int 65H to exhibit how software interrupts
needs to be programmed.
void
char
void
void
{
interrupt (*oldint65)( );
st[80] = {Hello World$};
interrupt newint65(void);
main()
oldint65 = getvect(0x65);
setvect(0x65, newint65);
geninterrupt (0x65);
geninterrupt (0x65);
geninterrupt (0x65);
setvect(0x65, oldint65);
}
void interrupt newint65( )
{
_AH = 0x09;
_DX=(unsigned int)st;
geninterrupt (0x21);
}
The above listing saves the address of original int 65H in the pointer oldint65. It then
places the address of its own function newint65 at the vector of interrupt number 65H.
From this point onwards whenever int 65H is invokes the function newint65 will be
invoked. Int 65 is invoked thrice which will force the newint65 function to be invoked
thrice accordingly. After this the original value of the vector stored in oldint65 is restored.
The newint65 function only displays the string st. As the interrupt 65 is invoked thrice
this string will be printed thrice.
The Keep function
One deficiency in the above listing is that it is not good enough for other application i.e.
after the termination of this program the newint65 function is de-allocated from the
memory and the interrupt vector needs to be restored otherwise it will act as a dangling
Copyright Virtual University of Pakistan
24
}
void interrupt newint65( )
{
_AH = 0x09;
_DX=(unsigned int)st;
geninterrupt (0x21);
}
The main()function gets and sets the vector of int 65H such that the address of
newint65 is placed at its vector. In this case the program is made memory resident
using the keep function and 1000 paragraphs of memory is reserved for the program (the
amount of paragraphs is just a calculated guess work based upon the size of application).
Now if any application as in the following case invokes int 65H the string st which is also
now memory resident will be displayed.
25
26
Care must be taken while invoking the original interrupt. Generally in case hardware
interrupts are intercepted invoking the original interrupt at the start of new routine might
cause some problems whereas in case of software interrupts the original interrupt can be
invoked anywhere.
Sample Program for interrupt Interception
void interrupt newint();
void interrupt (*old)();
void main()
{
old=getvect(0x08);
setvect(0x08,newint);
keep(0,1000);
}
void interrupt newint ()
{
(*old)();
}
The above program gets the address stored at the vector of interrupt 8 and stores it in the
pointer oldint. The address of the interrupt function newint is then placed at the vector of
int 8 and the program is made memory resident. From this point onwards whenever
interrupt 8 occurs the interrupt function newint is invoked. This function after performing
its operation calls the original interrupt 8 whose address has been stored in oldint pointer.
Timer Interrupt
In the coming few examples we will intercept interrupt 8. This is the timer interrupt. The
timer interrupt has following properties.
Its an Hardware Interrupts
It is Invoked by Means of Hardware
It approximately occurs 18.2 times every second by means of hardware.
Another Example
#include <dos.h>
void interrupt (*old)();
void interrupt new();
char far *scr=(char far* ) 0x00400017;
void main()
{
old=getvect(0x08);
setvect(0x08,new);
keep(0,1000);
}
void interrupt new (){
*scr=64;
(*old)();
}
This fairly simple example intercepts the timer interrupt such that whenever the timer
interrupt occurs the function new() is invoked. Remember this is .C program and not a
.CPP program. Save the code file with .C extension after writing this code. On occurrence
of interrupt 8 the function new sets the caps lock bit in key board status by placing 64 at
this position through its far pointer. So even if the user turns of the caps lock on the next
occurrence of int 8 ( almost immediately) the caps lock will be turned on again (turing on
the caps lock on like this will not effect its LED in the keyboard only letters will be typed
in caps).
The attribute byte (higher byte) describes the forecolor and the backcolor in which the
character will be displayed. The DOS screen carries black as the backcolor and white as
the fore color by default. The lower 4 bits (lower nibble) represents the forecolor and the
higher 4 bits (higher nibble) represents the back color as described by the diagram below
Fig 8 (Attribute Byte)
This program works like a screen saver. The newTimer function increments t whenever
it is invoked so the value of t reaches 182 after ten second. At this moment the function
saves the value in display text memory in a character array and fills the screen with
spaces and sets a flag m. The newKey function is invoked when a key press occurs.
In the above example the function Proc1() is invoked. On invocation the register AX
contained the value 1234H, the code within the function Proc1() changes the value in AX
to FF55H. On return AX will contain the value 1234H if the function have been
implemented as a reentrant procedure i.e a reentrant procedure would restore the values in
registers their previous value (saved in the stacked) before returning.
C language reentrant procedures save the registers in stack following the order AX, BX,
CX, DX, ES, DS, SI, DI, BP on invocation and restores in reverse order before return.
This fact about reentrant procedures can be analysed through following example.
#include <stdio.h>
void interrupt *old();
void interrupt newint()
void main ()
{
old = getvect(0x65);
setvect(0x65,newint);
_AX=0xf00f;
geninterrupt(0x65);
a = _AX
printf(%x,a);
}
The registers Flags, CS and IP are pushed on execution of INT instruction and executions
branches to the interrupt procedure. The interrupt procedure pushes register AX, BX, CX,
DX, ES, DS, SI, DI, BP in this order. The interrupt procedure then executes, before
returning it pops all the registers in the reverse order as BP, DI, SI, DS, ES, DX, CX, BX
and AX. IP, CS and flags are poped on execution of the IRET instruction.
Next diagram shows the status of the stack after invocation of the interrupt procedure.
The arguments in simple procedure or functions are saved in the stack for the scope of the
function/procedure. When an argument is accessed in fact stack memory is accessed.
Now we will take a look how stack memory can be accessed for instance in case of
interrupt procedures to modify the value of register in stack.
Accessing Stack Example
void interrupt newint ( unsigned int BP,unsigned int DI,
unsigned int SI,unsigned int DS, unsigned int
ES,unsigned int DX, unsigned int CX,unsigned
int BX, unsigned int AX,unsigned int IP,
unsigned int CS,unsigned int flags)
//corrected
{
a = AX;
b = BX;
d = ES;
}
Although interrupt do not take parameters through stack but an interrupt procedure can
still have parameters. This parameter list can be used to access the stack. The leftmost
parameter accesses the item on top of the stack and the rest of the parameters accesses
deeper into the stack according to its order toward left. In the above example value of AX
in stack is moved in a, the value of BX is moved into b and the value of ES is moved into
d.
Example:
int
SI,unsigned
int DX,
unsigned int
CS,unsigned
}
void main ( )
{
setvect(0x65,newint);
_AX = 0x1234;
geninterrupt (0x65);
a = _AX;
printf (%x, a);
}
In this example the value on invocation in AX is 0x1234, the interrupt procedure does not
change the current value of the register through pseudo variables rather it changes the
corresponding of AX in stack which will be restored in AX before return.
Disk Interrupt
The following example makes use of disk interrupt 13H and its service 3H. The details of
this service are as under.
On Entry
AH = Service # = 03
AL = No of Blocks to write
BX = Offset Address of Data
CH = Track #
, CL = Sector #
DH = Head #
DL = Drive #(Starts from 0x80 for fixed disk & 0 for removable disks)
ES = Segment Address of data buffer.
On Exit
AH = return Code
Carry flag = 0 ( No Error AH = 0)
Carry flag = 1 ( Error AH = Error Code)
Boot block is a special block on disk which contains information about the operating
system to be loaded. If the data on boot block is somehow destroyed the disk would be
rendered inaccessible. The address of partition block on hard disk is head # =1, track# = 0
and sector # = 1. Now lets write an application that will protect the boot block to be
written by any other application.
#pragma inline
07 - Hardware Interrupts
The microprocessor package has many signals for data, control and addresses. Some of
these signals may be input signals and some might be output. Hardware interrupts make
use of two of such input signals namely NMI (Non maskable Interrupt) & INTR(Interrupt
Request).
NMI is a higher priority signal than INTR, HOLD has even higher priority and RESET
has the highest priority. If any of the NMI or INTR pins are activated the microprocessor
is interrupted on the basis of priority, if no higher priority signals are present. This is how
microprocessor can be interrupted without the use of any software instruction hence the
name hardware interrupts.
Hardware Interrupt and Arbitration
Most of the devices use the INTR line. NMI signal is used by devices which perform
operations of the utmost need like the division by zero interrupt which is generated by
ALU circuitry which performs division. Definitely this operation is not possible and the
circuitry generates an interrupt if it receives a 0 as divisor from the control unit.
INTR is used by other devices like COM ports LPT ports, keyboard, timer etc. Since only
one signal is available for microprocessor interruption, this signal is arbitrated among
various devices. This arbitration can be performed by a special hardware called the
Programmable Interrupt Controller (PIC).
As it can be seen from the diagram above the PIC device has 8 inputs IRQ0-IRQ7. IRQ0
has the highest priority and IRQ7 has the lowest. Each IRQ input is attached to an I/O
device whenever the device requires an I/O operation it sends a signal to the PIC. The PIC
on the basis of its priority and presence of other requests decides which request to serve.
Whenever a request is to be served by PIC it interrupt the processor with the INT output
connected to the INTR input of the processor and send the interrupt # to be generated the
data lines connected to the lower 8 datelines of the data bus to inform the processor about
the interrupt number. In case no higher priority signal is available to the processor and the
processor is successfully interrupted the microprocessor sends back an INTA (interrupt
Acknowledge) signal to inform the PIC that the processor has been interrupted.
The following diagram also shows the typical connectivity of the IRQ lines with various
devices
The PICs are cascaded such that a total of 16 IRQ levels can be provided number IRQ0IRQ15. The IRQ level 2 is used to cascade both of the PIC devices. The Data lines are
multiplexed such that the interrupt number is issued by the concerned PIC. The IRQ 2
input of the Master PIC is connected to the INT output of the Slave PIC. If the slave PIC
is interrupted by a device its request ins propagated to the master PIC and the master PIC
ultimately interrupts the processor on INTR line according to the priorities.
In a standard PC the PICs are programmed such that the master PIC generated the
interrupt number 8-15 for IRQ0 IRQ7 respectively and the slave PIC generates interrupt
number 70-77H for IRQ8-IRQ15
Hardware Interrupts are Non-Preemptive
As described earlier IRQ 0 has the highest priority and IRQ 15 has the lowest priority. If a
number of requests are available instantaneously the request with higher priority will be
sent for service first by the PIC. Now what will happen if a lower priority interrupt is
being service and a higher priority interrupt request occurs, will the lower priority
interrupt be preempted? The answer is that the interrupt being serviced will not be
preempted no matter what. The reason for this non-preemptive can be understood by the
example illustrated as below. Lets first consider that the hardware interrupts are
preemptive for argument sake. If a character A is input a H/W interrupt will occur to
process it, while this interrupt is being processed another character is input say B in case
the interrupts have been preemptive the previous instance will be preempted and another
instance for the H/W interrupt call will be generated, and similarly consider another
character is input C and the same happened for this input as well. In this case the
character first to be fully processed and received will be C and then B will be
The input will be received in correct sequence only if the H/W interrupts are nonpreemptive as illustrated in the diagram below.
The values shown in the various registers illustrate that the currently in-service interrupt
is that generated through IRQ4 of the PIC (int 0CH in case of mater PIC), also the
interrupt through IRQ1 has been masked (int 9h (keyboard interrupt) in case of master
PIC) which means that even though a request for this interrupt is received by the PIC but
this request is ignored by the PIC until this bit is cleared. And the requests through IRQ7,
IRQ6, IRQ2 and IRQ0 are pending and waiting for the previously issued interrupt to
return.
Port Addresses
Few of the operation control words can be altered after boot time. The addresses for these
OCW are listed as below
Lets now discuss an example that accesses these ports to control the PIC
#include <stdio.h>
#include <bios.h>
void main()
{
outport(0x21,0x02);
}
This example simply accesses the bit # 1 of IMR in the master PIC. It sets the bit #1 in
IMR which masks the keyboard interrupt. As a result no input could be received from the
keyboard after running this program.
Lets now look at another example
#include <dos.h>
#include <stdio.h>
#include <bios.h>
void interrupt(*oldints)();
void interrupt newint8();
int t=0; //corrected
void main()
{
oldints=getvect(0x08);
setvect(0x08,newint8);
keep(0,1000);
}
void interrupt newint8()
{
t++:
if (t==182)
{
outport(0x21,2);
}
else{
if (t==364)
{
outport(0x21,0);
t=0;
}
}
(*oldints)();
}
The keyboard buffer is a memory area reserved in the BIOS data area. This area stores the
ASCII or special key codes pressed from the keyboard. It works as a circular buffer and
two bytes are reserved for each character, moreover 2 bytes are used to store a single
character. The first character stores the ASCII code and the second byte stores 0 in case an
ASCII key is pressed. In case a extended key like F1- F12 or arrow key is pressed the first
byte stores a 0 indicating a extended key and the second byte stores its extended key
code.
Circular buffer
The circular keyboard buffer starts at the address 40:1EH and contains 32 bytes. The
address 40:1AH stores the head of this circular buffer while the address 40:1CH stores the
tail of this buffer. If the buffer is empty the head and tail points at the same location as
shown in the diagram above.
Storing characters in the keyboard buffer
The above slide shows how characters are stored in the buffer. If A; is to be stored then
the first byte in the buffer will store its ASCII code and the second will store 0, and if
As discussed earlier the keyboard buffer is a circular buffer therefore the tail need to be
placed appropriately. In the given example the input A stored in the buffer is consumed.
On consumption of this character the tail index is updated so that it points to the next
character in the buffer. In brief the tail would point to the next byte to be consumed in the
buffer while head points to the place where next character can be stored.
Example
The program listed in the slides above intercepts interrupt 9. Whenever the interrupt 9
occurs it reads the keyboard port 0x60. If the port contains 83 then it means DEL was
pressed, if so it places the code 25 in the buffer and then updates the head in circular
manner. The code 25 placed instead of 83 represents the combinations CTRL+Y. The
program when resident will cause the program to receive CTRL+Y combination
whenever DEL is pressed by the user. i.e in Borland C environment CTRL+Y
combination is used to delete a line, if this program is resident then in Borland C
environment a line will be deleted whenever DEL is pressed by the user. But the thing
worth noticing is that the interrupt function returns and does not call the real interrupt 9
after placing 25 in the buffer, rather it returns directly. But before returning as it has
intercepted a hardware interrupt it needs to notify the PIC, this is done by
outport(0x20,0x20); statement. 0x20 is the address of the OCW that receives the EOI
code which incidentally is also 0x20.
As discussed earlier the slave PIC is cascaded with the master PIC. If the hardware
interrupt to be processed is issued by the master PIC then the ISR needs to send the EOI
code to the master PIC but if the interrupt request is issued by the slave PIC then the ISR
needs to inform both master and slave PICs as both of them are cascaded as shown in the
slide.
The same port i.e 0x20 is used to access the OCWs. 00 is placed in bits number 4 and 3 to
indicate an EOI is being received and 01 is placed to indicate that a internal register is to
be accessed.
The value in bits number 1 and 0 indicate which Register is to accessed. 10 is for IRR and
11 is for ISR.
A value is placed in the port 0x20 as shown in the above slide to indicate that a register is
to be accessed.
Then again a value in that same port is placed to indicate which register is to be accessed,
as in the above slide IRR is to be accessed.
And in this slide a value is formed which can be programmed in the port 0x20 to access
the ISR.
A sample program
The above program makes use of the technique described to access the ISR and IRR.
Firstly 0x08 is placed to specify that a register is to be accessed then 0x0A is placed to
indicate that IRR is to accessed. Now this port 0x20 can be read which will contain the
value in IRR. Similarly it is done again by placing the 0x0B in port 0x20 to access the
ISR.
This will not work as this global variable is only global for this instance of the program.
Other instances in memory will have their own memory space. So the
The interval timer is used to divide an input frequency. The input frequency used by the
interval timer is the PCLK signal generated by the clock generator. The interval timer has
three different each with an individual output and memory for storing the divisor value.
A counter register can be used to divide the clock signal. As shown in the slide above, 0
of the clock register is used to divide the clock frequency by 2 subsequently bit 1 is used
to divide it by 4 and so on.
The Division mechanism
The above slide shows a sequence of output that a 8bit clock register will generate in
sequence whenever it receives the clock signal. Observe bit #1, its value changes between
0 and 1 between two clock cycles so it can be used to divide the basic frequency by 2.
Here is the timing diagram for above example. Bit #1 performs one cycle in between 2
clock cycles. Similarly bit #2 performs one cycle in between 4 clock cycles and so on.
Command register and the channels need to be programmed for the interval timer to
generate a wanted frequency.
Command Register
The interval timer can operate in six modes. Each mode has a different square wave
pattern according to need of the application. Some modes might be suitable to control a
motor and some might be suitable to control the speaker.
Binary counter
The interval timer channels can be used as a binary as well as a BCD counter. In case its
used in binary mode its counter registers will count in binary sequence and if its used as a
BCD counter its registers will count in BCD sequence as described above.
The interval timer has 3 channels each channel is 16 bit wide. The port 43H is an 8 bit
port used as the command register. Ports 40h, 41H and 42H are associated with the
channels o, 1 and 2 respectively. Channels are 16 bit wide whereas the ports are 8 bit
wide. A 16 bit value can be loaded serially through the ports into the register.
Steps for programming the interval timer
the port 61h is used to control the speaker only the least significant 2 bits are important.
Bit 0 is used to connect the interval timer to the speaker and the bit #1 is used to turn the
speaker on off. Rest of the bits are used by other devices.
Example
The above programs the interval timer and then turns it on. A value of 0xb4 is loaded into
the command register 0x43. This value signifies that the channel 2 is to programmed,
Delay can be produced using double word variable in the BIOS Data area placed at the
location 0040:006C. This value contains a timer count and is incremented every 1/18th of
a second. In this program the this double word is read, placed in a program variable and
incremented by 18. The value of 40:6cH is compared with this variable in a loop. This
loop iterates until the value of 40:6cH is not greater. In this way this loop will keep on
iterating for a second approximately.
The inner while loop in the program is used to induce delay. The outer loop simply
reloads the divisor value each time it iterates after reducing this value by 30. In this way
the output frequency of the interval timer changes after every quarter of a second
approximately. The speaker will turn on with a low frequency pitch and this frequency
will increase gradually producing a spectrum of various sound pitches.
Sample Program
The above program is a TSR program that can be used to turn the speaker on/off. The
above program intercepts the int 15h. Whenever this interrupt occurs it looks for service #
0x4f (keyboard hook). If S(0x1f scan code) has been pressed it toggles the speaker.
This program generates a tune with 4 different pitches. This program is quite similar to
the one discussed earlier. The only major difference is that in that program the pitch was
gradually altered from low to high in this the pitches change periodically until a key is
pressed to terminate the outer loop. Four various pitches are maintained and their divisor
values are placed in the divisors[] array. All these divisor values are loaded one by one
after a delay of approximately quarter of a second and this continues until a key is
pressed.
This is an interrupt driven version of the previous program. This program makes use of
the timer interrupt rather than a loop to vary the divisor value. Moreover interrupt 15 is
used to turn the speaker on /off.
The speaker turns on whenever S (scan code 0x1f) is pressed and turns off whenever A
(scan code 0x1E) is pressed.
The timer interrupt shift the divisor value stored in the tones structure whenever the
required numbered of ticks( timer counts) have passed as required by the value stored in
the delay field of the tone structure.
More such divisor values and their delays can be initialized in the tones structure to
generate an alluring tune.
PPI is used to perform parallel communication. Devices like printer are generally based
on parallel communication. The principle of parallel communication is explained in the
slide above. Its called parallel because a number of bits are transferred from one point ot
another parallel on various lines simultaneously.
The PPI acts as an interface between the CPU and a parallel I/O device. A I/O device
cannot be directly connected to the buses so they generally require a controller to be
placed between the CPU and I/O device. One such controller is the PPI. Here we will see
how we can program the PPI to control the device connected to the PPI which generally is
the printer.
Int 17H
Int 17H is used to control the printer via the BIOS. The BIOS functions that perform the
printer I/O are listed in the slide above with its other parameter i.e DX which contains the
LPT number. A standard PC can have 4 PPI named LPT1, LPT2, LPT3 and LPT4.
The above listed function returns a status byte in the AH register whose meaning is
described in the slide above. Various bits of the byte describe the status of the printer.
Time out Byte
The BIOS service once invoked will try to perform the requested operation on the printer
repeated for a certain time period. In case if the operation is rendered unsuccessful due to
any reason BIOS will not quit trying and will try again and again until the number of tries
specified in the timeout bytes shown above runs out.
The status of the printer can be used in the above described manner to check if the printer
can perform printing or not. In case there is a transfer error, the printer is out of paper or
there is a timeout the printer could not be accessed. Or if the printer is busy or if the
printer is offline the printer cannot be accessed. The pseudo is just performing these
checks.
Sample Program
The above program performs programmed I/O on the printer using BIOS services. The
program firstly initializes the printer int 17H/01. The while loop will end when the end of
file is reached, in the loop it checks the printer status (int 17h/02) and write the next byte
in the file if the printer is found idle by checking the most significant bit of the status
byte.
Sample Program
The above program intercepts int 17H. Whenever a certain program issues int 17H to
print a character the above TSR program will intercept the service and do nothing if A or
In this sample program again int 17H is intercepted. The new interrupt function will
ignore all the spaces in the print document.
In this program interrupt 17h is again intercepted. Whenever a character is to printed the
new function call the old function thrice. As a result a single character in the print
document will be repeated 4 times.
Now we will see how the register within the PPI can be accessed directly to control the
printer.
Above slide list the addresses within the BIOS data area where the base address (starting
port number) of LPT devices is stored.
Dump of BIOS data area
The dump of BIOS data area address specified in the previous slide for a certain computer
shows that the base port address of LPT1 is 0x03bc, for lpt2 it is 0x0378, for Lpt3 it is
0x0278. These values need not be the same for all the computer and can vary from
computer to computer.
The LPTs can be swapped i.e LPT1 can be made LPT2 and vice versa for LPT2. This can
be accomplished simply by swapping their addresses in the BIOS data area as shown in
the slide above.
The first port (Base +0) is the data port. Data to be sent/received is placed in this port. In
case of printer the (Base + 1) is the printer status port as described in the slide. Each bit
represents the various status of the printer quite similar to the status byte in case of BIOS
service.
Printer Control Register
(Base +2) is the printer control register it is used to pass on some control information to
the printer as described in the slide.
The above program directly accesses the registers of the PPI to print a file. The while loop
terminates when the file ends. The if statement only schecks if the printer is busy of not.
If the printer is idle the program writes the next byte in file on to the data port and then
turns the strobe bit to 1 and then 0 to indicate that a byte has been sent to the printer. The
loop then again starts checking the busy status of the printer and the process continue.
The printer interface uses the IRQ 7 as shown in the slide above. Therefore if interrupt
driven I/O is to be performed int 0x0f need to be programmed as an hardware interrupt.
Above is a listing of a program that uses int 0x0f to perform interrupt driven I/O. To
enable the interrupt 0x0f three things are required to be done. The interrupt should be
enabled in the printer control register; secondly it should also be unmasked in the IMR in
PIC. The program can then intercept or set the vector of interrupt 0x0f by placing the
address of its function newint();
The newint() will now be called whenever the printer can perform output. This newint()
function writes the next byte in buffer to the data registers and then send a pulse on the
strobe signal to tell the printer that data has been sent to it. When whole of the buffer has
been sent the int 0x0f vector is restored, interrupt is masked and the memory for the
program is de-allocated.
The above listing might not work. Not all of the printer interfaces are designed as
described above. Some modifications in the printer interface will not allow the interrupt
driven I/O to work in this manner. If this does not work the following strategy can be
adopted to send printing to the printer in background.
This program uses the timer interrupt to send printing to the printer in the back ground.
Whenever the timer interrupt occurs the interrupt function checks if the printer is idle or
not. If its the printer is idle it takes a byte from the buffer and sends it to the data port of
the printer interface and then sends a pulse through the strobe signal. When the buffer is
full the program restores the int 8 vector and the relinquishes the memory occupied by the
program.
Not all the bits of the internal registers of the PPI are available in standard PCs. In
standard PCs the PPI is connected to a DB25 connector. And some of the bits of its
internal registers are available as pin outs as describes in the slide above.
It might be desirable to connect one computer to another via PPIs to transfer data. One
might desire to connect them such that one port of PPI at one end is connected to another
port of the other PPI at the other end. But interconnecting the whole 8 bits of PPI cannot
be made possible as all the bits of the internal ports are not available as pinouts. So the
answer is to connect a nibble (4-bits) at one end to the nibble at the other. In this way two
way communication can be performed. The nibbles are connected as shown in the slide
above.
The pins that are interconnected are shown in the slide above. Another thing worth
noticing is that the 4th bit of the data port is connected to the BUSY and vice versa. The
BUSY is inverted before it can be read from the status port. So the 4th bit in data port at
PC1 will be inverted before it can be read at the 7th bit of status register at PC2.
Flow Control
An algorithm should be devised to control the flow of data so the receiver and sender may
know when the data is to be received and when it is to be sent. The following slides
illustrate one such algorithm.
The receiver then sends back the nibble turning its D4 bit to 0 as an acknowledgement of
the receipt of the low nibble. This will turn the BUSY bit to 1 at the sender side.
The receiver then sends back the high nibble to the sender as an acknowledgment.
13 - Serial Communication
Program implementing the described protocol
This is the sender program. This program if find the BUSY bit clear sends the low nibble
but turns the D4 bit to 0 before sending. Similarly it right shifts the byte 4 times sets the
D4 bit and then sends the high nibble and waits for acknowledgment until the BUSY is
cleared.
This is receiver program. If the BUSY bit is clear it receives the low nibble and stores it
in x. Similarly if the BUSY bit is 0 it receives the high nibble and concatenates the both
nibble to form a byte.
Serial Communication
In case of serial communication the bits travel one after the other in serial pattern. The
advantage of this technique is that in this case the cost is reduced as only 1 or 2 lines
maybe required to transfer data.
The major disadvantage of Serial communication is that the speed of data transfer maybe
reduced as data is transferred in serial pattern.
There are two kinds of serial communications.
Synchronous Communication
13 - Serial Communication
Asynchronous Communication
In case of asynchronous communication no timing signal is required but each byte needs
to be encapsulated to know the end and start of a byte.
13 - Serial Communication
UART (Universal Asynchronous Receiver Transmitter)
13 - Serial Communication
13 - Serial Communication
The pin outs of the DB25 connector used with RS232C is shown in the slide above.
13 - Serial Communication
Data is received through the RxD line. Data is send through the TxD line. DTR (data
terminal ready) indicates that the data terminal is live and kicking. DSR(data set ready)
indicates that the data set is live. Whenever the sender can send data it sends the signal
RTS( Request to send) if as a result the receiver is free and can receive data it send the
sender an acknowledge through CTS( clear to send) indicating that its clear to send now.
DB 9 Connector for UART
This slide shows the various internal registers within a UART device. The programmer
only needs to program these registers efficiently in order to perform asynchronous
communication.
Register summary
The above table lists the registers within the UART ans also shows their abbreviation.
Also it shows there offsets with respect to the base register.
The above dump of the BIOS data area for a certain computer shows that the address of
COM1 is 03F8 , the address of COM2 is 02F8 and the address of COM3 is 03E8. These
addresses may not be same for all the computers and may vary computer to computer.
The baud rate is set in accordance with the divisor value loaded within the UART internal
registers base +0 and base +1.
Line Control Register
The line control register contains important information about the behaviour of the line
through which the data will be transferred. In it various bits signify the word size, length
of stop bits, parity check, parity type and also the a control bit to load the divisor value.
The bit 7 if set indicates that the base +0 and base + 1 will act as the divisor register
otherwise if cleared will indicate that base + 0 is the data register.
Line status register illustrates the status of the line. It indicates if the data can be sent or
received. If bit 5 and 6 both are set then 2 consecutive bytes can be sent for output. Also
this register indicates any error that might occur during communication.
Interrupt Enable Register
If interrupt driven output is to be performed then this register is used to enable interrupt
for the UART. It can also used to select the events for which to generate interrupt as
described in the slide.
Once an interrupt occurs it may be required to identify the case of the interrupt. This
register is used to identify the cause of the interrupt.
15 - COM Ports
Modem Control Register
In case software oriented flow control technique is used the bits 0 and 1 need to be set in
that case. Bit #3 need to be set to enable interrupts. Moreover if a single computer is
available to a developer the UART contains a self test mode which can be used by the
programmer to self test the software. In self test mode the output of the UART is routed to
its input. So you receive what you send.
This register indicates the status of the modem status line or any change in the status of
these lines.
FIFO Queue
This feature is available in the newer version of the UART numbered 16500. A queue or a
buffer of the input or output bytes is maintained within the UART in order to facilitate
more efficient I/O. The size of the queue can be controlled through this register as shown
by the slide.
15 - COM Ports
Interrupt ID Register
The following slide shows how int 14H service 0 can be used to set the line parameter of
the UART or COM port. This illustrates the various bits of AL that should be set
according before calling this service.
15 - COM Ports
The Service on return places the line status in AH register as shown in the slide below.
15 - COM Ports
And places the modem status in the AL register as shown in slide below.
Other service of 14h include service #1 which is used to send a byte and service #2 which
is used to receive a byte as shown in the slide below.
15 - COM Ports
Communication through Modem
Modem is generally used to send/receive data to/from an analog telephone. Had the
telephone line been purely digital there would have been no need of a modem in this
form. If data is to be transferred from one computer to another through some media which
can carry digital data then the modem can be eliminated and the UART on both
computers can be interconnected. Such arrangement is called a NULL modem.
15 - COM Ports
NULL Modem Configuration
The above slide shows the configuration used to interconnect two UARTs In this way a
full duplex communication can be performed and moreover flow control can also be
performed using DSR, DTS, RTS and CTS signals.
Sample Program
15 - COM Ports
15 - COM Ports
16 - COM Ports II
Sample Program using BIOS routines
The initialize () function initializes the COM port whose number is passed as parameter
using BIOS services. The recievechar() function uses the COM port number to receive a
byte from the COM port using BIOS services.
15 - COM Ports
The sendchar() function sends a character to the COM port using BIOS service whose
number is passed as parameter. And the getcomstatus() function retrieves the status of the
COM port whose number has been specified and returns the modem and line status in an
unsigned int.
15 - COM Ports
The second if statement checks if a byte can be read from the COM port. If the Data
ready bit is set then it receives a byte from the data port and displays it on the screen.
Moreover there is another check to end the program. The program looks for an escape
character ASCII = 27 either in input or in output. If this is the case then it simply breaks
the loop.
Sample Program
This program does more or less the same as the previous program but the only difference
is that in this case the I/O is done directly using the ports and also that the Self Test
facility is used to check the software.
The initialize() loads the divisor value of 0x0180 high byte in base +1 and low byte in
base +0. It also programs the line control register for all the required line parameters.
The SelfTestOn() function simply enables the self test facility within the modem control
register.
15 - COM Ports
The SelfTestOff() function turns this facility off. The writechar() function writes the a
byte passed to this function on the data port. The readchar() function reads a byte from the
data port.
The main function after initializing and turning the self test mode on enters a loop which
will terminate on input of the escape character. This loop also controls the position of the
cursor such the cursor goes to the next line right after a full line has been typed.
15 - COM Ports
All the input from the keyboard is directed to the output of the UART and all the input
from the UART is also directed to the lower part of the screen. As the UART is in self test
mode the output becomes the input. And hence the user can see output send to the UART
in the lower part of the screen as shown in the slide below
15 - COM Ports
Sample Program using interrupt driven I/O
15 - COM Ports
This si program is also quite similar to the previous one. The only difference is that in this
the I/O is performed in an interrupt driven patter using the Int 0x0C as the COM1 uses
IRQ4. Also to use it in this way IRQ4 must be unmasked from the IMR register in PIC.
Also before returning from the ISR the PIC must be signaled an EOI code.
15 - COM Ports
15 - COM Ports
This program is same functionally as one of the previous programs which used BIOS
services to get the input data and send the output data. The only difference is that in this
case it does the same directly accessing the ports.
15 - COM Ports
Only two or three of the lines are being used to send receive data rest of the lines are
being used for flow control. The cost of these lines can be reduced by reducing the lines
used to flow control and incorporating software oriented flow control rather than
hardware oriented flow control as show in the slide below.
The DTR, DSR, RTS and CTS lines have been eliminated to reduce cost but in this flow
control will be performed in a software oriented manner.
15 - COM Ports
XON whenever received indicates the start of communication and XOFF whenever
received indicates a temporary pause in the communication.
Following is a pseudo code which can be used to implement the software oriented flow
control.
the received character is firstly analysed for XON or XOFF character. If XON is received
the status is set to TRUE and if XOFF is received the status is set to FALSE. The
characters will only be received if the status is TRUE otherwise they will be discarded.
Real time clock is a device incorporated into the PC to update time even if the computer
is off. It has the characteristics shown in the slide above which enables it to update time
even if the computer is off.
The BIOS interrupt 0x1Ah can be used to configure this clock as shown in the slide
below it has various service for getting/setting time/date and alarm.
The RTC internally has an array of registers which can be used to access the 64 byte
battery powered CMOS RAM.
The value in the days of the week byte indicates the day according to slide shown above.
Generally BCD values are used to represent the units of time and date.
Following slide shown a fragment of code that can be used to read or write onto any byte
within the 64 byte battery powered RAM.
The lower 4 bits of this register stores a code indicating the frequency with which the
RTC hardware interrupt can interrupt the processor. The next field is used to specify the
time frequency i.e. the frequency with the time is sampled and hence updated. The most
significant bit indicates that after time sampling if the time has been updated in to the 64
byte RAM or not.
The status register B is the main control register. It is used to specify the date time
formats and is also used to enable interrupt on various events like alarm time and time updation. Another feature of RTC is periodic interrupt which occur with a frequency
specified in the A register.
Status register is used to identify the reason of interrupt generation as described in the
slide above.
Only the most significant byte in status register D is important which on being 0 indicates
that the battery is dead.
Sample Program.
The above program uses the service int 1Ah/02H to read the time from the real time
clock. It reads the time and converts the packed BCD values into unpacked BCD values.
These values are then converted into ASCII and displayed using the printf() statement.
The time units are similarly read and converted to ASCII and displayed.
Write the Time on RTC
The above listing of the program inputs the time from the user which is in ASCII format.
It converts the ASCII in packed BCD and uses BIOS services to update the time. In DOS
or windows this time change may not remain effective after the completion of the
program as the DOS or windows device drivers will revert the time to original even if it
has been changed using this method.
To elaborate more on the problem posed by the OS device drivers here is another
program. This program first updates the time accessing the 64 byte RAM directly and
taking the new time as input from the user. After updating the program produces a delay
of 30 seconds and then reads time to display it. A difference of 30 seconds will be noticed
in the time entered and the time displayed. This shows that during the execution of the
program the time was successfully changed and was being updated accordingly.
The above sample program takes ASCII input from the user for the new date. After taking
all the date units as input the program sets the new date using the BIOS service 1Ah/05H.
Setting the Alarm
The alarm can be set using BIOS function 1Ah/06h. Once the alarm is set BIOS will
generate the interrupt 4Ah when the alarm time is reached. The above program intercepts
the interrupt 4Ah such that newint() function is invoked at the time of alarm. The newint()
function will just display a character A on the upper left corner of the screen. But this
program may not work in the presence of DOS or Windows drivers.
Another way to set Alarm
Interrupt 11H is used to determine the systems information. On return this service returns
the systems info in AX register. The detail of the information in AX register is shown in
the slide above.
Int 12H is used to determine the amount of conventional memory interfaced with the
processor in kilobytes. The amount of memory above conventional memory (extended
memory) can be determined using the service 15H/88H.
The above slides show the test that can be used to determine if the underlying processor is
8086 or not. If its not 8086 some test for it to be 80286 should be performed.
If the bits 14-12 are cleared on pushing the flags register then the processor is 80286. This
can be checked as shown in the slide above.
In 32-bit processors it is more optimal in terms of speed if double word are placed at
addresses which ate multiples of 4. If data items are placed at odd addresses the access to
such data items is slower by the virtue of the memory interface of such PCs. So it more
optimal to assign such variables addresses which are multiple of 4. The 386 and 486 are
both 32 bit processors but 486 has alignment check which 386 does not have. This
In the above slide a double word is moved into a odd address. If the processor is 386 then
the 18th bit of the EFLAGS register will not be set, it will be set if the processor is higher
than 386.
A Pentium and 486 both will pass the alignment test. But a 486 does not support the
CPUID instruction. We will next incorporate the CPUID instruction support test to find if
the processor is 486 or a Pentium as Pentium does support CPUID instruction.
If the CPUID instruction is available the processor is a Pentium processor otherwise its a
486.
The CPUID instruction, if available, returns the vendor name and information about the
model as shown in the slide above. Beside rest of the test the CPUID instruction can also
be used by the software to identify the vendor name.
The coprocessor control word contains some control information about the coprocessor.
The bit number 7 of coprocessor control word is the Interrupt Enable Flag and bit number
8 & 9 should contain 11 on initialization.
Coprocessor Status Word
The coprocessor status register stores the status of the coprocessor. Very much like the
flags register in the microprocessor the Coprocessor status word can be used to determine
the result of a comparison as shown in the slide.
Once its established that the coprocessor is present then the model of the coprocessor
should be determined. In case an invalid numerical operation is requested the 8087
coprocessor generates an interrupt while the higher coprocessors does not use interrupts
in fact they make use of exceptions. This feature can be used to distinguish between 8087
and higher processor as shown in the slide above. The higher processor will not respond
to an attempt made to set the IEM flag while 8087 will respond.
If the sign of infinity can be reversed than the coprocessor is 80387 otherwise its 80387
In this program the general configurations of the computer are read using interrupt 11H,
12H and 15H. First its determined if the Processor is and AT (advanced technology all
processors above 8086) type computer or not. This can be done easily by checking its
signature byte placed at the location F000:FFFEH which will contain neither 0xFF nor
0xFE if its an AT computer. The program shows the size of conventional RAM using the
interrupt 12H, then if the computer is an AT computer then the program checks the
extended memory size using int 15H/88H and reports its size. And ultimately the program
calls int 11H to show the number and kind of I/O interfaces available.
21 - Keyboard Interface
Processor Identification
In the above slide the test for 8086 or not is performed by clearing all the bits of flags
register then reading its value by pushing flags and then poping it in AX, the bits 15-12 of
ax are checked if they have been set then its a 8086.
The above code performs the alignment test as discussed before by test the 18th bit after
addressing a double word at an odd address.
the above code performs a test to see if CPUID instruction is available or not for which
the bit number 21 of flags is set and then read back.
A CPUID Program
The above program places 0 in eax register before issuing the CPUID instruction. The
string returned by the instruction is then stored and printed moreover other information
about family, model etc is also printed.
Detecting a Co Processor
After initialization the control word is read if the higher byte contains the value 3.
In the code above the IEM bit is set and then the value of control word is read to analyse
change in the control word. If the most significant bit is set then its a 8087 co processor
otherwise other tests must be performed.
21 - Keyboard Interface
An operation (like division by zero is performed) which results in infinity. Then the sign
of the result is reversed, if it can be reversed then its 80387 co processor otherwise its
certainly 80287.
The keyboard interface as discussed earlier uses the IRQ1 and the port 60H as data port, it
also uses another port number 64H as a status port. The keyboard can perform
synchronous serial I/O.
21 - Keyboard Interface
The above slide shows the detailed meaning of bits in port 64H.
The typematic rate of the keyboard can be controlled by a control word as depicted in the
slide above. The delay and typematic rates need to be specified in this control word. The
delay indicates the delay between first and second character input whenever a key is
pressed. The timing of rest of the successive character inputs for the same key is
determined by the typematic rate.
21 - Keyboard Interface
The input character scan code is received at port 60H. A certain bit in the port 64H or
keyboard controller is used as the IBF (input buffer full) bit. A device driver can check
this bit to see if a character has been received from the keyboard on which this bit will
turn to 1.
Similarly some data (as control information) can be send to the keyboard. The processor
will write on the port 60H. The device driver will check the OBF( output buffer full bit of
port 64H which remains set as long as the byte is not received by the keyboard. On
receipt of the byte from the port 60H the keyboard device write a code 0xFA on the port
60H to indicate that the byte has been received properly.
21 - Keyboard Interface
Keyboard is a typically an input device but some data can also be send to the keyboard
device. This data is used as some control information by the keyboard. One such
information is the typematic rate. This type matic rate can be conveyed to the keyboard as
described by the slide below.
Other such control information is the LED status. Every keyboard has three LEDs for
representing the status of Num Lock, Caps Lock and the Scroll Lock. If the device driver
21 - Keyboard Interface
needs to change the status then the LED status byte should be written on the keyboard as
described below. But before writing this byte the keyboard should be told that the control
byte is to be written. This is done by sending the code 0XED before sending the status
byte using the above described protocol.
21 - Keyboard Interface
The above program has function SendKbdRate(). This function takes 2 parameters, first
one is value to be sent and the second one is the maximum number of retries it performs if
the byte cannot be sent. This function implements the described protocol. It first waits for
the IBF to be cleared and then starts trying to send the byte. The functions stops trying
either if 0xFA is received (success) or if the number of retries end (failure).
Now this function is used to change the typematic rate. Firstly 0XF3 is written to indicate
that the typematic rate is to be changed then the typematic rate is set to 0x7F and a strng
can be type to experience the new typematic rate. Again this rate is set to 0. This program
will not work if you have booted the system in windows. First boot the system in DOS
and then run this program.
21 - Keyboard Interface
Changing LEDs Status
21 - Keyboard Interface
Again the same function is being used in this program to turn on the keyboard LEDs.
Firstly 0xED is sent to indicate the operation and then 7 is written to turn on all the LEDs.
But tuning on the LEDs like this will not change the keyboard status indicated by the byte
at 40:17H. If the status for the device driver usage is to changes as well then the
corresponding at 40:17H can be set by ORing it with 0x70. This program will not work if
you have booted the system in windows. First boot the system in DOS and then run this
program.
21 - Keyboard Interface
DMA is a device which can acquire complete control of the buses and hence can be used
to transfer data directly from port to memory or vice versa. Transferring data like this can
prove faster because a transfer will consume 2 bus cycles if it is performed using the
processor. So in this approach the processor is bypasses and its cycles are stolen and are
used by the DMA controller.
21 - Keyboard Interface
A single DMA can transfer 8bit operands to and from memory in a single a bus cycle. If
16bit values are to be transmitted then two DMA controllers are required and should be
cascaded as shown above.
21 - Keyboard Interface
The above slides shows the characteristics of each register when a DMA channel is to be
programmed and also shows the total number of registers in the DMA controller. Some of
the registers are common for all channels and some are individual for each channel.
The DMA can work in above listed modes. In block transfer mode the DMA is
programmed to transfer a block and does not pause or halt until the whole block is
transferred irrespective of the requests received meanwhile.
In Single transfer mode the DMA transfers a single byte on each request and updates the
counter registers on each transfer and the registers need not be programmed again. On the
next request the DMA will again transfer a single byte beginning from the location it last
ended.
Demand transfer is same as block transfer, only difference is that the DREQ signal
remains active throughout the transfer and as soon as the signal deactivates the transfer
stops and on reactivation of the DREQ signal the transfer may start from the point it left.
The above table shows the addresses of all the registers that should be programmed to
perform a transfer. These registers act as status and control registers and are common for
all the channels.
Terminal count if reached signifies that the whole of the block as requested through some
DMA channel has been transferred. The above status register maintains the status of
Terminal count (TC) and DREQ for each channel within the DMA.
This register can be used to simulate a DMA request through software (in case of memory
to memory transfer). The lower 2 bits contains the channel number to be requested and
the bit # 2 is set to indicate a request.
This register can be used to mask/unmask requests from a device for a certain DMA
channel. The lower 2 bits contains the channel number and the bit #2 is set if the channel
is to be masked.
This register can also be used to mask the DMA channels. It contains a single bit for each
channel. The corresponding bit is set to mask the requests for that channel.
This register can be used to set the mode on each. The slide shows the detail of the values
and bits which should be placed in the register in order to program a required mode.
A channel is programmed for a start address and the count of bytes to be transferred
before the transfer can take place. Both these values are placed in various registers
according to the channel number as shown by the slide above. Once the transfer starts
these values start changing. The start address is updated in to the current address and the
count is also updates as bytes are transferred. During the transfer the status of the transfer
can be analyzed by getting the values of these registers listed In the slide above for the
channel(s) involved in the transfer.
The above slide shows the port number for each channel in which the higher 4 or 8 bits of
the absolute address is stored in case of 20 or 24 bit address bus.
This program, programs the DMA channel 3 for read cycle by placing 0x0B in mode
register (0x0B). Before the channel is unmasked and the channel mode is programmed the
base address the count and the higher 4 or 8 bits of the address should be placed in base
register, count register and Latch B respectively. The 20 (or 24) bit address is calculated.
The higher 4 ( or 8) bits are placed in the Latch B for channel 3, then the rest of the 16
bits of the base address are placed in base register for channe3 and ultimately the count is
25 - File Systems
This program attempts to perform memory to memory transfer operation. This program
will only work for a 8086 processor, higher processors DMA may not support memor to
memory transfer.
This program, programs the channel 0 and channel 1 of the DMA. It loads the address of
Source string st in base register and the Latch B and loads the count register for channel 0
and does the same for st1. It then programs the mode, mask and command register for
memory to memory transfer and to unmask channel 0 and channel 1.
File Systems
25 - File Systems
Tracks are the circular division of the disk and the sectors are the longitudinal division of
the disk as shown in the diagram above.
25 - File Systems
An addressable unit on disk can be addressed by three parameters i.e. head #, sector # and
track #. The disk rotates and changing sectors and a head can move to and fro changing
tracks. Each addressable unit has a unique combination of sec#, head# and track# as its
physical address.
25 - File Systems
25 - File Systems
25 - File Systems
25 - File Systems
25 - File Systems
26 - Hard Disk
Now we establish how a block can be read or written if its address is known. The function
biosdisk() can be used to read or write a physical block. The slide shows its parameter. It
takes the command (cmd), drive number, head number, track number, number of sectors
to be read or written and the memory from where the data is to read from or written to.
Command signifies the operation that is to be performed.
Drive number is described in the slide below it starts from 0 for first removable disk and
starts from 0x80 for first fixed disk.
25 - File Systems
25 - File Systems
The above program reads a physically addressed block from disk using bios disk()
function for first fixed disk. The program after reading the specified block writes it to a
file and then closes the file.
However there are some limitation of this biosdisk() while using large disks. This
function uses the int 13H services listed in the slide above.
25 - File Systems
The parameter sizes provided by these services may not be sufficient to hold the track
number of block to be accessed.
Above slide shows for which disks extended services are required to access the block
efficiently.
25 - File Systems
But IDE disk interface can support disks with memory space larger than 504MB as shown
in the next slide.
25 - File Systems
Extended services require that the address of the block is specified as a LBA address.
LBA translation is done by numbering the blocks with a single index. The indexes are
assigned to blocks as shown in the slide below. In terms of the disk geometry firstly all
the sectors of a track will be indexed sequentially, then the track exhausts the next track is
chosen on the other side of the disk and so on all the tracks in a cylinder are indexed.
When all the blocks within a cylinder has been indexed the same is done with the next
cylinder.
if the CHS (cylinder, head , sector) address of a disk is known it can be translated in to the
LBA address and vice versa. For this purpose the total number of cylinders, heads and
sectors must also be known.
26 - Hard Disk
Also conversely LBA to CHS translation can also be done using the formulae discussed in
the following slide but for this the total number of cylinders, heads and sectors within the
disk geometry should be known.
26 - Hard Disk
Disk Address Packet is a data structure used by extended int 13H services to address a
block and other information for accessing the block. Its structure is defined in the slide
below.
26 - Hard Disk
Interrupt 13H/42H can be used to read a LBA addressed block whose LBA address is
placed in the Disk Address packet as described in the slide above.
Similarly int 13H / 43H can be used to write onto to LBA addressed block as described in
the slide above.
26 - Hard Disk
26 - Hard Disk
The above slides list a program that that performs a block read operation using the
interrupt 13H/42H. A structure of type DAP is create an appropriate values are placed into
it which includes its LBA address. The offset address of dap is placed in SI register and
the DS already contains its segment address as it has been declared a global variable. The
drive number is also specified and the interrupt is invoked. The interrupt service reads the
contents of the block and places it in a buffer whose address was specified in dap. The
contents of this buffer are then written on to a file. Slide 7
26 - Hard Disk
The data part can contain information about four different partitions for different
Operating systems. Each partition information chunk is 16 bytes long and the last two
bytes at the end of the partition table data part is the partition table signature whose value
should be AA55 indicating that the code part contains valid executable code.
26 - Hard Disk
The structure of the information stored in each 16 byte for partition is shown in the slides
below
The byte at the offset 4 in the 16 byte data part contains the file system ID which can have
various values depending upon the type of OS in use as described by the slides below.
26 - Hard Disk
26 - Hard Disk
However if a single operating system is to be kept for instance, then the disk can be
divided into primary and extended partitions. Information about primary and extended
partition is kept in the first physical block. The extended partition may again be divided
into a number of partitions, information about further partitions will be kept in extended
partition table which will be the first physical block within extended partition (i.e. it will
not the first block of primary partition.). Moreover there can be extended partitions within
extended partitions and such that in then end there are number of logical partitions this
can go on till the last drive number in DOS.
26 - Hard Disk
28 - Partition Table II
26 - Hard Disk
Here it can be seen that the first partition table maintains information about the primary
and extended partitions. The second partition table similarly stores information about a
logical and a extended partition within the previous extended partition. Similarly for each
such extended partition there will be a partition table that stores information about the
logical partition and may also contain information about any further extended partition. In
this way the partition tables form a chain as depicted in the slide below. The last partition
table within the chain contains just a single entry signifying the logical drive.
26 - Hard Disk
The above dump shows the dump of the data part of the first partition table which has two
16 bytes entries, the values in the entries can be interpreted as the values shown in the
following slide.
26 - Hard Disk
Here is the information found in the partition table of first extended partition table which
implies another extended and a logical partition.
26 - Hard Disk
Here is information in the partition table of the second extended partition that implies yet
another extended partition and a logical partition with the details shown in the following
slide.
26 - Hard Disk
Above slides shows the information collected as yet which indicates the logical drive
there starting LBA blocks, the number of block , the hidden blocks etc. The following
slide shows the contents of the data part of partition table of the last extended partition.
It has just one data entry for the logical drive indicating that this is the partition table in
the chain. The detail of the contents this partition table are shown below.
The following slide shows the summary of all the data collected as yet depicting 4 logical
drives and the number of blocks within.
Above is a listing of a simple program that reads the partition table using the extended
13H services. It then displays the contents of the data part of the partition table read. For
this purpose it uses various data structures designed in reflection of the partition table and
16 bytes data entries within. The program uses recursion and calls the getpart() function
recursively whenever it finds an extended partition to read the data within the extended
partition table.
The partition table data entry also stores the CHS address of the starting block. But this
address is left insignificant if a LBA enable disk is in question. However LBA address can
be used in place of the CHS address, and in case CHS address is required it can be
calculated if the total number of tracks, sectors and heads are known. To get the total
number of tracks, sectors and head the above described service can be used.
Above slides shows the structure of result buffer used by extended 13H services. If a
extended service returns a value it will be stored in the result buffer as described above.
The above program uses a RESULTBUFFER data structure in reflection of the result
buffer described in previous slides. It uses the interrupt 13H/48H to get the drive
parameters and then displays the received total number of sectors, heads and cylinders.
This is also a quite similar program only difference is that it also translates a LBA address
into CHS address and displays it, for this purpose it gets the drive parameters to know the
total number of heads, sectors and cylinders.
LSN is also indexed like LBA the only difference is that LBA is the address relative to the
start of physical drive (i.e. absolute), whereas LSN address is the address from the start of
logical partition i.e relative.
As in the above example it can be noticed that the LBA = 0 is not the same as LSN=0.
The LBA=0 block is the first block on disk. Whereas each logical partition has LSN=0
block which is the first block in logical drive and is not necessarily the first block on
physical drive. Also notice the hidden blocks between the first physical block on each
partition and its first LSN block. These hidden blocks are not used by the operating
system for storing any kind of data.
To understand the file systems of DOS and Windows the above given data structure
should be understood which are used by the operating system for file management. In the
coming lecture these data structures will be discussed in detail.
Above slide shows the overall anatomy of a FAT based system. Starting block(s) is /are
the boot block(s), immediately after which the FAT (File allocation table) starts. A typical
volume will contain two copies of FAT. After FAT the root directory is situated which
contain information about the files and folders in the root directory. Whole of this area
constitutes the systems area rest of the area is used to store user data and folders.
BIOS parameter block is a data structure maintained by DOS in the boot block for each
drive. The boot block is typically a 512 byte block which as seen the previous slides is the
first logical block i.e. LSN = 0. It contains some code and data. The data part constitutes
the BPB. Details for FAT 12 and 16 are shown in following slides.
The LSN of the boot block is 0. The information contained within the BPB in boot block
can be used to calculate the LSN of the block from where the user data starts. It can be
simply calculated by adding the number of reserved sector, sectors occupied by FAT
copies * number of FAT copies and the the number of blocks reserved for root dir.
The above slide shows the location of BPB within the boot block. A jump instruction
(near jump of 3 bytes size) is used to jump to the code part and skip the data part so that it
is not interpreted as instructions by the processor.
Above is the dump of the boot block for a FAT 12 system. The contents of the BPB can be
read from it the following slide shows the detail of the information obtained from the
above BPB.
Following is another dump showing the boot block for a FAT 16 system.
Besides the LBA address a LSN address can also be used to address a block. If the LSN
address is known the absread() function can be used to read a block and abswrite() can be
used to write on it as described in the slide below where nsect is the number of sector to
be read/written.
The DPB contains the information shown in the table below. This information can be
derived from the BPB but is placed in memory in the form of DPB.
The following code shows how the service 21H/32H is invoked and the registers in which
it returns a value. It also shows the contents of the DPB by taking the dump at the
location returned by the service for a FAT 12 volume (i.e. Floppy disk).
The details of the information read from the dump of the DPB are shown below.
The following code shows how the service 21H/32H is invoked and the registers in which
it returns a value. It also shows the contents of the DPB by taking the dump at the
location returned by the service for a FAT 16 volume (i.e. hard disk partition smaller than
2 GB approx.).
The above program creates a data structure in reflection of the BPB and reads the boot
record of the volume using absread(). It extracts the data part of the boot block and
displays all the values stored in it.
The above program is doing is the same using the DPB rather than BPB.
The DOS directory structure is a Tree like structure. The top most level of the tree being
the root directory. The root directory contains files and folders. Each folder can contains
more files and folders and so on it continues recursively as shown by the slide.
Control information about files are maintained in a data structure called the File control
block (FCB). The FCB for each file is created and stored in the disk.
The root directory consists of FCBs for all the files and folders stored on the root
directory. To obtain these FCBs, the portion on disk reserved for root directory can be
read.
In the above two slides first the contents of DPB are read to find the start of the root
directory. Using this block number the contents of root directory are read, as it can be
seen they contain number of FCBs each containing information about a file within the
directory.
The user data area is divided into clusters. The first cluster in user data area is numbered 2
in a FAT based systems. A cluster is not the same as block and also there are no system
calls available which use the cluster number. All the system calls use the LSN address. If
the cluster number is known it should be converted into LSN to access the blocks within
the cluster. Moreover all the information about file management uses the cluster number
using the information the above slide the following formula can be devised as shown in
the slide below to convert the cluster number into LSN.
The following memory dump extracts the starting cluster number from the FCB of a file
and then converts the cluster number in sector to get its starting block.
The contents of the blocks/cluster at the start of file are then examined by loading the
sectors within the first cluster to that file in the following slide. Here the contents of the
file can be seen on the right side column.
Once the DPB has been read the blocks reserved for root directory are determined and are
then read to get the contents of the root directory.
The root directory contains a collection of FCBs. The FCB for the file in question is
searched from where the first cluster of the file can be get.
After calculating the sector number for the cluster the contents of the file can be accessed
by reading all the blocks within the cluster. In this way only the starting cluster will be
read. If the file contains a number of cluster the subsequent clusters numbers within the
file chain can be accessed from the FAT.
Above slides show how a cluster chain for a file is maintained in the FAT. The first cluster
number is in the FCB. Subsequent clusters will be accessed from the FAT using the
previous cluster number as index to look up into the FAT for the next cluster number.
A FAT theoretically will contain 2n entries where n is 12 for FAT 12 and 16 for FAT16.
But all the entries are not used some of the entries are reserved following slide shows its
detail.
There can various volume with various sizes with FAT12 or FAT16. The number of
entries for FAT 12 or FAT16 are limited then the question arises how can a certain volume
with moderate space and another volume with large space can be managed by the same
FAT system. The answer is that the number of entries might be same but the size of
cluster may be different. The cluster size can vary from 512 bytes to 32K in powers of 2
depending upon the volume size. The above slide shows how the cluster size and the
exact number of required FAT entries can be determined.
Here a familiar operation has been performed. After reading the DPB the root directory is
read to search for the entry of file CPAPER.TXT.
Following slide shows the dump for the FAT12 for the particular volume.
Using the root directory entry and the FAT contents the contents of the file can be
accessed.
Not all the entries in FAT16 will be used, the following shows which ones of the entry are
reserved.
The following slide shows the content of the DPB for a FAT16 volume. Same int 21h/32H
is used to determine its address and the parameters can be determined by taking dump of
the memory at the address returned.
Here the slide shows the contents of the root directory depicting the FCB of a file named
CPAPER.TXT. The control information about this file can be read from the dump.
The above slides shows that the first cluster of the file is 0008. The following slide shows
the contents of FAT. The FAT is loaded firstly in memory at the offset address 1000H.
Each entry occupies 2 bytes. So the index 0008 will be located at 1000H + 0008*2 =
1010H. At 1010H, 0009 is stored which is the next cluster of the file, using 0009H as
index we look up at 1012H, which stores 0055H, which means 0055H is the next cluster.
using 0055H as index we look up at 10AAH to find the next cluster number and so on.
36 - File Organization
Now converting all those cluster number in previous lecture into LSN we get the starting
LSN for each cluster.
For cluster # 0009H and 55h
Now on the same volume the file TEST.TXT is deleted. Lets analyse the contents of the
root directory now.
The entry for TEST.TXT still exists as can be seen from the next slide. The only
difference that have occurred is that the first character has been replaced by a byte with
the value 0xE5
But when the DIR command execute on the same volume the file does not show.
Now lets see the contents of the file by converting the first cluster number in the FCB
into LSN and taking its dump. We get the following slide.
Not only the file is marked for deletion but also the chain of its cluster in FAT is
reclaimed by putting zeros in there place. This also indicates that these clusters are now
free.
Now lets have some discussion about sub-directories. In the contents of the above given
root directory notice an entry named SECOND. The attribute byte of this entry is 0x20
which indicates that its a directory, the size is 0 which shows that there is now user data
in it, but even though the size 0 its has a first cluster which is 0x12. Converting 0x12 into
LSN and then reading its contents we get the following dump. This shows that this cluster
contains the FCBs for all the file and folders within this directory.
The following slide shows the contents of SUB5 and also the contents of file
MYFILE.TXT in SUB5.
Notice the contents of SECOND directory. The . entry has the cluster number 0012H
which is the cluster number for the SECOND directory and the .. entry has cluster number
which indicates the higher level directory which is the root directory.
Also examine the contents of SUB2 directory the . directory has cluster number 0017h
which the cluster number for SUB2 and the .. entry has the cluster number 0012H which
is the cluster number of its parent directory SECOND
Same can be observed for SUB3, SUB4, SUB5 or any other sub-directory in question.
So this how CD. command gives the current path and CD.. moves to the one higher level
directory.
Using the information in DPB the root directory entries are read and are being shown in
the slide below.
I n the above slide it can be noticed that the long file name is also stored with the FCBs.
Also the fragments of Unicode strings in the long file name forms a chain. The first byte
in the chain will be 0x01, the first byte of the next fragment will be 0x02 and so on till the
last fragment. If the last fragment is the nth fragment starting from 0 such that n is
between 0 and 25 the first byte of the last fragment will be given as ASCII of A plus n.
Now lets move our discussion to FAT32. In theory the major difference between FAT 16
and FAT 32 is of course the FAT size. FAT32 evidently will contain more entries and can
hence manage a very large disk whereas FAT16 can manage a space of 2 GB maximum
practically.
Following slide shows the structure of the BPB for FAT32. Clearly there would be some
additional information required in FAT32 so the structure for BPB used in FAT32 is
different.
There can be different volumes with different volume sizes. The device driver for file
handling would require knowing the FAT size. The following slide illustrates an algorithm
that can be used to determine the FAT size in use after reading the BPB.
FCB in FAT32 system has an enhanced meaning as shown by the slide below.
Anatomy of FAT32 based system differs from FAT16 based systems significantly as
explained by the slide below.
In reflection of the anatomy of FAT32 based system the method used to translate the
cluster # into LSN also varies. The following formula is used for this purpose.
Now we determine all the parameters in the above slide for a certain volume to translate a
cluster number into LSN.
So using all this information we calculate the LSN for cluster number 2 as shown the
slide below for this particular volume.
To examine the contents of a file first a file is created whose contents are also shown in
the slide.
Now we examine the contents of cluster number 2 which contains the root directory as
already seen in the previous slides.
Using the cluster number above the LSN for this cluster is determined as shown in the
slide below.
In the FAT32 there is another special reserved block called FSInfo sector. The block
contains some information required by the operating system while cluster
allocation/deallocation to files. This information is also critical for FAT16 based systems.
But in FAT12 and 16 this information is calculated when ever required. This calculation at
the time of allocation is not feasible in FAT32 as the size of FAT32 is very large and such
calculations will consume a lots of time, so to save time this information is stored in the
FSInfo block and is updated at the time of allocation/deallocation.
The following slides show the Boot sector structure for a NTFS based system.
The first 16 entries of the MFT are reserved. Rests of the entries are used for user files.
There is an entry for each file in the MFT. There can be difference in the way a file is
managed depending upon the size of the file.
Following slide shows the detail about the first 16 system entries within the MFT.
The first logical block is read to read the contents of the BPB in NTFS. Following shows
the contents of boot block for this volume.
For NTFS simply the following formula will be used to translate the sector number into
cluster number.
Following slide shows how the sector number for the MFT on this volume was
calculated. The first block of MFT no this volume is 6291456.
The above dump shows the file name as well as the contents of the file are stored in this
entry. Has the file been larger it would not have been possible to store the content of the
file in this entry so other clusters would have been used and there would indexes would
have been kept in the entry.
As an exercise one can try to find out the sub folders and the contents of the files stored in
it.
41 - Disk Utilities
The above program uses the DPB to reach the clusters of a file. The getDPB() function
gets the far address of the DPB. Using this address the drive parameters are used to
determine the location of FAT and root directory. The file is firstly searched in the root
directory through sequential search. If the file name and extension is found the first
cluster number is used to look up into the FAT for subsequent clusters. The particular
block containing the next cluster within the FAT is loaded and the entry is read, similarly
the whole chain is traversed till the end of file is encountered.
42 - Memory Management
The following slide shows the memory map of the first 1MB of RAM. The first 640KB is
called conventional RAM and the higher 384KB is called system memory. Some of the
memory areas are reserved for special purposes as described by the slide rest is user area
where user application can reside.
All the MCB forms a chain. If the address of first MCB is known the segment
address of next MCB can be determined by adding the number of paragraph
controlled by MCB + ! into the segment address of the MCB. Same is true for all
MCBs and hence the whole chain can be traversed.
The above slide shows how service 21H/52H is used to get the address of first MCB in
memory.
In the following slide the dump of the first MCB is taken. M in the first byte at the
location read indicates the placement of MCB at this location. The address of next MCB
can be calculated by adding the number of paragraphs controlled by MCB + 1 into the
segment address. Using this method all the MCBs in memory are traversed till the last
MCB with first byte Z is encountered.
This program used the same method as discussed in previous lecture to get the address of
first MCB, calculate the addresses of subsequent MCBs and traverse the MCBs to reach
the last MCB.
The following slide shows the structure of descriptors of 80286 and 80386 processors
The hidden cache is illustrated in the slide below. The registers in dotted lines are hidden
i.e. are not accessible to any application directly.
45 - Viruses