0% found this document useful (0 votes)
66 views

Errors in C Programming

This document discusses various types of runtime errors in C programs like segmentation violations and stack overflows. It also talks about how runtime errors cause immediate program termination without flushing buffers, which can lead to unexpected behavior. The document then covers various issues related to floating point numbers like overflow, underflow and roundoff errors. It provides examples to illustrate these concepts and discusses ways to minimize roundoff errors. Finally, it talks about memory related concepts in C like physical vs logical addresses, memory segmentation and determining the accuracy of floating point number representation and calculations.

Uploaded by

CODEGURU MAHESH
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
66 views

Errors in C Programming

This document discusses various types of runtime errors in C programs like segmentation violations and stack overflows. It also talks about how runtime errors cause immediate program termination without flushing buffers, which can lead to unexpected behavior. The document then covers various issues related to floating point numbers like overflow, underflow and roundoff errors. It provides examples to illustrate these concepts and discusses ways to minimize roundoff errors. Finally, it talks about memory related concepts in C like physical vs logical addresses, memory segmentation and determining the accuracy of floating point number representation and calculations.

Uploaded by

CODEGURU MAHESH
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 19

1

Day 2(Advanced C)

Runtime Errors
Runtime errors are usually the easiest to fix. Some types of runtime errors are:
Segmentation Violation. This error indicates that the program tried to dereference
a pointer containing a bad value.

Stack Overflow. The program tried to use too many temporary variables.
Sometimes, stack overflow happens because the program is too big or is using too
many big temporary arrays, but most of the time this is due to infinite recursion
problems. Almost all UNIX systems automatically check for this error. Turbo C++ and
Borland C++ check for stack overflow only if the
compile -time option -N is used.

Divide by 0 . Divide by is an obvious error. UNIX masks the problem by reporting


an integer divide by zero with the error message "Floating exception (core dumped)."
All these errors stop program execution. On UNIX, an image of the running program,
called a core file, is written out. One problem with runtime errors is that when they
occur, the program execution stops immediately. The buffers for buffered files are not
flushed. This can lead to some unexpected surprises. Consider Example 15-10.

#include <stdio.h>
int main()
{
int i,j; /* two random integers */
i = 1;
j = 0;
printf("Starting\n");
printf("Before divide...");
i = i / j; /* divide by zero error */
printf("After\n");
return(0);
}
When run, this program outputs the following: Starting, Floating exception
(core dumped.) This program might lead you to think the divide had never started,
when in fact it had. What happened to the message "Before divide..."? The printf
statement executed and put the message in a buffer, and then the program died. The
buffer never got a chance to be emptied. By putting explicit flush buffer commands
inside the code, we get a truer picture of what is happening. See Example 15-11.

Example
[File: flush2/flush2.c]
#include <stdio.h>
int main()
{
int i,j; /* two random integers */
i = 1;
j = 0;
printf("Starting\n");
fflush(stdout);
printf("Before divide...");
fflush(stdout);
2

i = i / j; /* divide by zero error */


printf("After\n");
fflush(stdout);
return(0);
}

The flush statement makes the I/O less efficient, but more current.

Overflow and Underflow


There are limits to the size of the number that a computer can handle. What are the
results of the following calculation? 9.000E+9 x 9.000E+9 Multiplying it out, we get:
8.1 x 10 +19 However, we are limited to a single-digit exponent, too small to hold
19. This example illustrates overflow (sometimes called exponent overflow). Some
computers generate a trap when this overflow occurs, thus interrupting the program
and causing an error message to be printed. Other computers are not so nice and
generate a wrong answer (like 8.100E+9). Computers that follow the IEEE floating-
point standard generate a special value called +Infinity. Underflow occurs when the
numbers become too small for the computer to handle. For example:

1.000E-9 x 1.000E-9
The result is:
1.0 x 10 -18
Because -18 is too small to fit into one digit, we have underflow.

Roundoff Error

Floating-point arithmetic is not exact. Everyone knows that 1+1 is 2, but did you
know that 1/3 + 1/3 does not equal 2/3?
This result can be shown by the following floating-point calculations:
2/3 as floating -point is 6.667E-1.
1/3 as floating -point is 3.333-1.
+3.333E-1
+3.333E-1
+6.666E-1 or 0.6666
which is not:
+6.667E-1
Every computer has a similar problem with its floating point. For example, the
number 0.2 has no exact representation in binary floating-point. Floating-point
arithmetic should never be used for money. Because we are used to dealing with
dollars and cents, you might be tempted to define the amount of $1.98 as:
float amount = 1.98;
However, the more calculations you do with floating-point arithmetic, the bigger the
roundoff error. Banks, credit card companies, and the IRS tend to be very fussy about
money. Giving the IRS a check that's almost right is not going to make them happy.
Money should be stored as an integer number of pennies.
3

Accuracy
How many digits of the fraction are accurate? At first glance you might be tempted to
say all four digits. Those of you who have read the previous section on round off error
might be tempted to change your answer to three.
The answer is: the accuracy depends on the calculation. Certain operations, like
subtracting two numbers that are close to each other, generate inexact results. For
example, consider the following equation:
1 - 1/3 - 1/3 - 1/3
1.000E+0
- 3.333E-1
- 3.333E-1
- 3.333E-1
or:
1.000E+0
- 0.333E+0
- 0.333E+0
- 0.333E+0
_____________________
0.0010E+0 or 1.000E-3
The correct answer is 0.000E+0 and we got 1.000E-3. The very first digit of the
fraction is wrong. This error is an example of the problem called "roundoff error" that
can occur during floating-point operations.

Minimizing Round off Error


There are many techniques for minimizing roundoff error. Guard digits have already
been discussed. Another trick is to use double instead of float. This solution gives
you approximately twice the accuracy as well as an enormously greater range. It also
pushes away the minimization problem twice as far. But round off errors still can
creep in. Advanced techniques for limiting the problems caused by floating point can
be found in books on numerical analysis. They are beyond the scope of this text. The
purpose of this chapter is to give you some idea of the sort of problems that can be
encountered.

Floating-point by its very nature is not exact. People tend to think of computers as
very accurate machines. They can be, but they also can give wildly wrong results. You
should be aware of the places where errors can slip into your program.

Determining Accuracy
There is a simple way of determining how accurate your floating point is (for simple
calculations). The method used in the following program is to add 1.0+0.1, 1.0+0.01,
1.0+0.001, and so on until the second number gets so small that it makes no
difference in the result. The C language specifies that all floating-point numbers are
to be done in double . This method means that the expression:
float number1, number2;
. . .
while (number1 + number2 != number1)
is equivalent to: while (double(number1) + double(number2) !=
double(number1)) When using the 1+0.001 trick, the automatic conversion of float
to double may give a distorted picture of the accuracy of your machine. (In one case,
84 bits of accuracy were reported for a 32-bit format.) Example 16-1 computes both
the accuracy of floating-point numbers as used in equations and floating-point
4

numbers as stored in memory. Note the trick used to determine the accuracy of the
floating-point numbers in storage.

float/float.c
#include <stdio.h>
int main()
{
/* two numbers to work with */
float number1, number2;
float result; /* result of calculation */
int counter; /* loop counter and accuracy check */
number1 = 1.0;
number2 = 1.0;
counter = 0;
while (number1 + number2 != number1) {
++counter;
number2 = number2 / 10.0;
}
printf("%2d digits accuracy in calculations\n", counter);
number2 = 1.0;
counter = 0;
while (1) {
result = number1 + number2;
if (result == number1)
break;
++counter;
number2 = number2 / 10.0;
}
printf("%2d digits accuracy in storage\n", counter);
return (0);
}

Running this on a Sun-3/50 with a MC68881 floating -point chip, we get: 20 digits
accuracy in calculations
8 digits accuracy in storage This program gives only an approximation of the
floating -point precision arithmetic. A more precise definition can be found in the
standard include file float.h.
5

Day 3(Advanced C)

Memory related concepts in C

TSO means terminate but stay outside. It is that program, which release the main memory after the
execution of the program. Example ms paint, notepad, turbo c compilers etc.

TSR means terminate but stay residence .It is those program, which after the execution of the program does
not release the RAM (main memory).e.g. antivirus.

In c any hexadecimal number start with 0x 0r 0X So, address range will be 0x00000 to 0xFFFFF. So in
turbo C 3.0 memory address of all variables must be within 0x00000 to oxFFFFF.

It is 1MB memory range. Note. 2^10 = 1KB / 2^20 = 1MB / 2^30 = 1GB Where 10, 20, 30 are number of
bit.
Resident memory of computer
RAM has divided into two parts: (1) Extended memory (useless) (2) Residence memory

In Turbo C 3.0 compiler size of residence memory is 1MB. resident memory:

When any program is executed it is stored in the residence memory. For turbo c 3.0, it has 1MB residence
memory i.e. when we open turbo c 3.0 it stores 1MB in the RAM.

Physical address of a computer


Logical address and physical address: How to find or get a physical address of a RAM

Physical address of computer or operating system

All the c variables are stored in the residence memory. In turbo C 3.0, 20 bits address of the memory cell is
known as physical address or real address. In 20 bits, we can represent address from 0x00000 to 0xFFFFF.
That is all c variables must have memory address within this range.

A C programmer cannot not decides what will be the memory address of any variables. It is decided by
compiler. For Example: What will be output of following c code

#include<stdio.h> int main(){ int a; printf("%x",&x); return 0; }

Output: We cannot predict.

But we can say in 16 bits compilers address must be within 0x0000 to 0xFFFF and in 32 bits compilers
memory address must be within 0x00000000 to 0xFFFFFFFF.

Note: Suppose your c compiler is based on the microprocessor which total address buses are 32 then its
total size of addressable memory will be:

= 2 ^ 32 bytes
= 4 GB
6

Memory segment / Segment Address:


Memory segmentation in 8086 microprocessor : Segmented memory

Resident memory of RAM of size 1MB has divided into 16 equal parts. These parts is called segment. Each
segment has size is 64 KB.

16 * 64 KB = 1 MB
This process of division is known as segmentation.
Note: In turbo c 3.0 physical addresses of any variables
are stored in the 20 bits. But we have not any pointers

So pointers cannot access whole residence memory


address. To solve this problem we there are three types
pointers in c language. They are

1. Near pointer
2. Far pointer
3. Huge pointer

What is offset address?


Offset address and segment number in c programming language
Each segment has divided into two parts.
1. Segment no (4 bit)
2. Offset address (16 bit)

So, in the other words we can say memory address of any variable in c has two parts segment number and
offset address. In turbo c 3.0 a particular segment number offset address varies from 0x0000 to 0xFFFF
Suppose physical address of any variable in c is 0x500F1. Then its segment number is 5 and offset address is
00F1.

Write a program to find the offset address of any variable?

#include<stdio.h>
int main(){
int x;
printf("%u ",&x); //To print offset address
printf("%p ",x); //To print segment address
printf("%p ",&x); //To print offset address
printf("%fp ",&x); //To print segment address : offset address
return 0;
}

Data segment

All the segments are used for specific purpose. Like segment number 15 is used for ROM, segment number
14 is used for BIOS etc.
7

Segment number eight has special name which is known as data segment.
This segment has been divided into four parts. This is very important for c
programming.

1. Stack area

All automatic variables and constants are stored into stack area. Automatic variables and constants in c:

1. All the local variables of default storage class.


2. Variables of storage calls auto.
3. Integer constants, character constants, string constants, float constants etc in any expression.
4. Function parameters and function return value.

Variables in the stack area are always deleted when program control reaches it out of scope. Due to this
stack area is also called temporary memory area. For example:

What will be output of following c code?

#include<stdio.h>
int main(){
int i;
for(i=0;i<3;i++){
int a=5;
printf("%d",a);
}
return 0;
}

Output: 5 5 5

Explanation: Since variable a is automatic variable, it will store in the stack area. Scope of variable a is
within for loop. So after each iteration variable a will be deleted from stack and in each iteration variable a
will initialize.

This two concepts are only for Turbo C 3.0


It follows LIFO data structure. That in the stack area of memory data is stored in last in first out. For
example:
8

What will be output of flowing c code. (Turbo c 3.0)?

#include<stdio.h>
int main(){
int a =5, b = 6, c = 7,d =8;
printf("%d %d %d");
return 0;
}

Output: 8 7 6
Explanation:

Default storage class of variables a, b, c and d is auto. Since it automatic variable it will be sorted in the
stack area of memory. It will store in the stack as

Stack always follows LIFO data structure. In the printf function, name of variables is not
written explicitly. So default output will content of stack which will be in the LIFO order i.e.
8 7 6.

It has two part one for initialize variable another for non-initialize variable. All initialize
variables are more nearer than not initialized variable and vice versa. For example:

What will be output of following program (Turbo c 3.0)?


#include<stdio.h>
int main(){
int a =5, b, c =7;
printf("%d %d %d");
return 0;
}

Output: 7 5 garbage value


Explanation:

Automatic variable a and c has initialized while b has not initialized. Initialize variables are more nearer than
uninitialized variable .They will be stored in the stack. So due to LIFO first output will be 7 then 6 (since a
is more nearer than b with respect to c) then any garbage value will be output which is present in the stack.

Note: Default storage class of any local variable is auto.

2. Data area:
All static and extern variable are stored in the data area. It is permanent memory space and variable will
store in the memory unless and until program end. For example:

What will be output of following c code?

#include<stdio.h>
int main(){
9

int i;
for(i=0;i<3;i++){
static int a=5;
printf("%d",a);
}
return 0;
}

Output: 5 6 7

3. Heap area:

This memory area is use to allocate memory dynamically. In c we can allocate the memory space
dynamically by using function malloc and calloc. It always allocates memory in the heap area. Its size is
variable and depends upon free space in the memory.

4. Code area:

Function pointer can only access code area. Size of this area is always fixed and it is read only memory area.

How to create dos command in c?

(1) Create a dos command: type by c program.

#include <stdio.h>
void main(int count,char * argv[])
{
int i;
FILE *ptr;
char *str;
char ch;
if(count==1)
{
printf("The syntax of the command is incorrect.\n");
}
for(i=1;i<count;i++)
{
ptr=fopen(argv[i],"r");
if(ptr==NULL)
{
printf("The system cannot find the file specified.");
if(count>2)
printf("\nError occurred while procesing : %s.\n",argv[i]);
}
else
{
if(count>2)
{
printf("%s\n\n",argv[i]);
}
while((ch=getc(ptr))!=-1)
10

printf("%c",ch);
}
fclose(ptr);
}
}

Step 2: Save the as open.c (You can give any name) Step 3: Compile and execute the file. Step 4: Write
click on My computer of Window XP operating system and select properties. Step 5: Select Advanced ->
Environment Variables Step 6: You will find following window: Click on new button (Button inside the red
box)

Step 7: Write following: Variable name: path Variable value: c:\tc\bin\open.c (the path where you have
saved)

Step 8: Open command prompt and write open then file name and press enter button.
11

Day 4(Advanced C)

System level programming

IVT in C:

An interrupt is an exception, a change of the normal progression, or interruption in the normal flow of
program execution. An interrupt is essentially a hardware generated function call. Interrupts are caused by
both internal and external sources. An interrupt causes the normal program execution to halt and for the
interrupt service routine (ISR) to be executed. At the conclusion of the ISR, normal program execution is
resumed at the point where it was last. On the x86 architecture, the Interrupt Vector Table (IVT) is
a table that specifies the addresses of all the 256 interrupt handlers used in real mode. An interrupt vector
table, a concept common across various processor architectures, is a table of interrupt vectors that associates
an interrupt handler with an interrupt request in a machine specific way. A dispatch table is one method of
implementing an interrupt vector table. Most processors have an interrupt vector table (IVT), including chips
from Infineon, Microchip Atmel, Free scale, AMD, Intel, etc.

Interrupts should be used for infrequent events (1000's of clock cycles)

-keyboard strokes
-1ms clock ticks
-serial data (USART, SPI, TWI)
-analog to digital conversion
The "interrupt acknowledge" method, the external device gives the CPU an interrupt handler number. The
interrupt acknowledge method is used by the Intel Pentium and many older microprocessors. When the CPU
is interrupted by an interrupt, it looks up the interrupt handler in the interrupt vector table, and transfers
control to it.

Important structure and union:


The header file dos.h defines two important structures and one union. They are:

1. struct BYTEREGS {
unsigned char al, ah, bl, bh;
unsigned char cl, ch, dl, dh;
};
2. struct WORDREGS {
unsigned int ax, bx, cx, dx;
unsigned int si, di, cflag, flags;
};
3. union REGS {
struct WORDREGS x;
struct BYTEREGS h;
};

There is also one very important function int86 () which has been defined in dos.h header file. It is general
8086 software interrupt interface. It will better to explain it by an example.
12

Write a c program to display mouse pointer?


Answer:

#include <dos.h>
#include <stdio.h>
void main()
{
union REGS i,o;
i.x.ax=1;
int86(0x33,&i,&o);
getch();
}

To write such program you must have one interrupt table. Following table is only small part of interrupt
table.
This table consists for column. They are:
(1) Input
(2) Output
(3) Service number
(4) Purpose

Now look at the first row of interrupt table. To show the


mouse pointer assign ax equal to 1 i.e. service number
while ax is define in the WORDREGS

struct WORDREGS {
unsigned int ax, bx, cx, dx;
unsigned int si, di, cflag, flags;
};
And WORDRGS is define in the union REGS
union REGS {
struct WORDREGS x;
struct BYTEREGS h;
};
So to access the structure member ax first declare a variable of REGS i.e. REGS i, o; Note: We generally
use i for input and o for output

To access the ax write i.x.ax (We are using structure variable i because ax is input(See in the interrupt table)
So to show mouse pointer assign the value of service number to it: i.x.ax=1;

To provide this information to microprocessor we use int86 function. It has three parameters

1. Interrupt number i.e. 0x33


2. union REGS *inputregiste i.e. &i
3. union REGS *outputregiste i.e. &o;
So write: int86 (0x33, &i, &o);
13

The Interrupt Descriptor Table (IDT) is a data structure used by the x86 architecture to implement
an interrupt vector table. The IDT is used by the processor to determine the correct response
to interrupts and exceptions.
Use of the IDT is triggered by three types of events: hardware interrupts, software interrupts, and processor
exceptions, which together are referred to as "interrupts". The IDT consists of 256 interrupt vectors–the first
32 (0-31 or 00-1F) of which are reserved for processor exceptions.

Real mode

In the 8086 processor, the IDT resides at a fixed location in memory from address 0x0000 to 0x03ff, and
consists of 256 four-byte real mode pointers (256 × 4 = 1024 bytes of memory). In the 80286 and later, the
size and locations of the IDT can be changed in the same way as it is done in protected mode, though it does
not change the format of it. A real mode pointer is defined as a 16-bit segment address and a 16-bit offset
into that segment. A segment address is expanded internally by the processor to 20 bits thus limiting real
mode interrupt handlers to the first 1 megabyte of addressable memory. The first 32 vectors are reserved for
the processor's internal exceptions, and hardware interrupts may be mapped to any of the vectors by way of
a programmable interrupt controller.

A commonly used x86 real mode interrupt is INT 10, the Video BIOS code to handle primitive screen
drawing functions such as pixel drawing and changing the screen resolution.
# include <stdlib.h> # include <stdio.h> # include <conio.h> # include <dos.h>
int main( )
{
unsigned long far* ptrIVT=(unsigned long far*)0x00000000;
unsigned int uiSegment;
unsigned int uiOffset;

int iCount;

FILE* oFile=fopen("IVT.txt","wt");

if(oFile==NULL)
{
clrscr( );
printf("Error : Unable to create IVT.txt file.");
printf("Press any key to exit.");
getch( );
exit(1);
}
fprintf(oFile,"Interrupt Number ---> Vector (Segment:Offset)\n");
fprintf(oFile," ( Hex ) ( Hex ) \n\n");
for(iCount=0;iCount<256;iCount++)
{
uiSegment=FP_SEG(*ptrIVT);
uiOffset=FP_OFF(*ptrIVT);
fprintf(oFile," INT 0x%02X ---> %4X : %X \n",iCount,uiSegment,uiOffset);
ptrIVT++;
}
fclose(oFile);
getch();
return 0; }
14

Interrupt Number ---> Vector (Segment:Offset) INT 0x33 ---> C7FF : 10


( Hex ) ( Hex ) INT 0x34 ---> F000 : 1060
INT 0x35 ---> F000 : 1060
INT 0x00 ---> 8D5A : 1A0 INT 0x36 ---> F000 : 1060
INT 0x01 ---> DDB : 103F INT 0x37 ---> F000 : 1060
INT 0x02 ---> 70 : 8 INT 0x38 ---> F000 : 1060
INT 0x03 ---> DDB : 104E INT 0x39 ---> F000 : 1060
INT 0x04 ---> 70 : 8
INT 0x05 ---> F000 : 1060
INT 0x06 ---> F000 : 1060
INT 0x07 ---> F000 : 1060
INT 0x08 ---> F000 : FEA5
INT 0x09 ---> DDB : 10A3
INT 0x0A ---> F000 : FF55
INT 0x0B ---> F000 : 1060
INT 0x0C ---> F000 : 1060
INT 0x0D ---> F000 : 1060
INT 0x0E ---> F000 : 1080
INT 0x0F ---> F000 : 1060
INT 0x10 ---> DDB : 115C
INT 0x11 ---> F000 : 1100
INT 0x12 ---> F22 : 3CD
INT 0x13 ---> DDB : 1149
INT 0x14 ---> F000 : 11A0
INT 0x15 ---> F000 : 11C0
INT 0x16 ---> F22 : 3E9
INT 0x17 ---> F000 : 1220
INT 0x18 ---> F000 : 12C0
INT 0x19 ---> F000 : 12C0
INT 0x1A ---> F000 : 1240
INT 0x1B ---> 628 : 23
INT 0x1C ---> F000 : 1260
INT 0x1D ---> F000 : F0A4
INT 0x1E ---> F000 : 1060
INT 0x1F ---> C000 : 500
INT 0x20 ---> F000 : 1480
INT 0x21 ---> DDB : 116F
INT 0x22 ---> 1AE : 5F0
INT 0x23 ---> 642 : 399A
INT 0x24 ---> 53D : B35
INT 0x25 ---> F000 : 14C0
INT 0x26 ---> F000 : 14E0
INT 0x27 ---> F000 : 1500
INT 0x28 ---> F000 : 1520
INT 0x29 ---> F000 : 1540
INT 0x2A ---> F000 : 15C0
INT 0x2B ---> F000 : 1060
INT 0x2C ---> F000 : 1060
INT 0x2D ---> F000 : 1060
INT 0x2E ---> F000 : 1060
INT 0x2F ---> DDB : 4
INT 0x30 ---> F000 : 1060
INT 0x31 ---> F000 : 1060
INT 0x32 ---> F000 : 1060
15

Day 5(Advanced C)
Introduction to microprocessor

In order to learn programming a microprocessor, first we need to learn how to use registers.

What are registers?

Registers are like utilities of a microprocessor to store data temporarily and manipulate it as per our requirements.
Suppose say if the user wants to add 3 with 2, the user asks the computer to store number 3 in one register and number
2 in more register and then add the contents of the these two registers and the result is placed in another register by the
CPU which is the output that we desire to see. There are four types of registers and are listed below.

 General purpose registers


 Segment registers
 Stack registers
 Index registers

Let me brief you about each of the types.

General purpose registers: These are used to store temporary data required by the program during its lifecycle. Each
of these registers is 16 bit wide or 2 bytes long.

 AX - the accumulator register


 BX - the base address register
 CX - the count register
 DX - the data register

Segment Registers: To represent a memory address to a microprocessor, there are two terms we need to be aware of:

 Segment: It is usually the beginning of the block of a memory.


 Offset: It is the index of memory block onto it.

Example: Suppose say, there is a byte whose value is 'X' that is present on a block of memory whose start address is

0x7c00 and the byte is located at the 10th position from the beginning. In this situation, We represent segment as
0x7c00 and the offset as 10. The absolute address is 0x7c00 + 10.

There are four categories that should be listed out.

 CS - code segment
 SS - stack segment
 DS - data segment
 ES - extended segment

But there is always a limitation with these registers. You cannot directly assign an address to these registers. What we
can do is, copy the address to a general purpose registers and then copy the address from that register to the segment
registers. Example: To solve the problem of locating byte 'X', we do the following way…

movw $0x07c0, %ax


movw %ax , %ds
movw (0x0A) , %ax

In our case what happens is

 set 0x07c0 * 16 in AX
16

 set DS = AX = 0x7c00
 set 0x7c00 + 0x0a to ax

There are various addressing modes that we need to understand while writing programs.

Stack Registers:

 BP - base pointer
 SP - stack pointer

Index Registers:

 SI - source index register.


 DI - destination index register.
 AX: CPU uses it for arithmetic operations.
 BX: It can hold the address of a procedure or variable (SI, DI, and BP can also). And also perform arithmetic
and data movement.
 CX: It acts as a counter for repeating or looping instructions.
 DX: It holds the high 16 bits of the product in multiply (also handles divide operations).
 CS: It holds base location for all executable instructions in a program.
 SS: It holds the base location of the stack.
 DS: It holds the default base location for variables.
 ES: It holds additional base location for memory variables.
 BP: It contains an assumed offset from the SS register. Often used by a subroutine to locate variables that
were passed on the stack by a calling program.
 SP: Contains the offset of the top of the stack.
 SI: Used in string movement instructions. The source string is pointed to by the SI register.
 DI: Acts as the destination for string movement instructions.

What is a bit?

In computing, a bit is the smallest unit where data can be stored. Bits store data in the form of binary. Either a 1(On)
or 0(Off).

More about registers:

The registers are further divided as below following left to right order or bits:

 AX: The first 8 bits of AX is identified as AL and the last 8 bits is identified as AH
 BX: The first 8 bits of BX is identified as BL and the last 8 bits is identified as BH
 CX: The first 8 bits of CX is identified as CL and the last 8 bits is identified as CH
 DX: The first 8 bits of DX is identified as DL and the last 8 bits is identified as DH

How to access BIOS functions?


BIOS provide a set of functions that let us draw the attention of the CPU. One will be able to access BIOS features
through interrupts.

What are interrupts?

To interrupt the ordinary flow of a program and to process events that require prompt response we use interrupts. The
hardware of a computer provides a mechanism called interrupts to handle events. For example, when a mouse is
moved, the mouse hardware interrupts the current program to handle the mouse movement (to move the mouse cursor,
etc.) Interrupts cause control to be passed to an interrupt handler. Interrupt handlers are routines that process the
interrupt. Each type of interrupt is assigned an integer number. At the beginning of physical memory, a table of
interrupt vectors resides that contain the segmented addresses of the interrupt handlers. The number of interrupt is
essentially an index into this table. We can also called as the interrupt as a service offered by BIOS.
17

Which interrupt service are we going to use in our programs?

Bios interrupt 0x10.

Writing code in an Assembler

What are the various Data types available in GNU Assembler?

A group of bits used in representing a unit to frame various data types.

What is a data type?

A data type is used to identify the characteristic of a data. Various data types are as below.

 byte
 word
 int
 ascii
 asciz

byte: It is eight bits long. A byte is considered as the smallest unit on a computer onto which data can be stored
through programming.
word: It is a unit of data that is 16 bits long.
What is an int?
An int is a data type that represents data of 32 bits long. Four bytes or two words constitute an int.
What is an ascii?
A data type to represent a group of bytes without a null terminator.
What is an asciz?
A data type to represent a group of bytes terminated with a null character in the end.

1. System level programs (Interrupt Service Routine)

/***************************************************************************************
This is a demo ISR to show how to create an ISR in C using the
_interrupt keyword. */

#include "dos.h"

// pointer to shift status


#define ISLEFTALT (*(unsigned char _far *)0x00400018)
// pointer to screen memory pos 0,0
#define OURSCRNPOS (*(unsigned char _far *)0xB8000000)
clrscr();
char orgchar; // orig. char

void (_interrupt _far *old_isr)(); // holds old interrupt handler

void _interrupt _far Timer() {

if ((ISLEFTALT & 0x02) != 0)


OURSCRNPOS = 0x01; // smiley face
else
OURSCRNPOS = orgchar; // orig. char
}
18

int main(int argc, char *argv[]) {


printf("\nPress the ESC key to exit"
"\nPress the Left ALT key");
orgchar = OURSCRNPOS; // get the current char

old_isr = _dos_getvect(0x1C); // install our ISR


_dos_setvect(0x1C, Timer); // Put our ISR in 0x1C

while (getch() != 0x1B); {} // wait for user to hit a key

_dos_setvect(0x1C, old_isr); // replace old ISR


getch();
return 0;
}

2. System level programs (Hardware configuration)

# include <stdio.h>
# include <conio.h>

int main( )
{
unsigned char far* ptrPcType=(unsigned char far*)0xF000FFFE;
clrscr();
printf("Model Identification Code:\n\n");
printf(" Code (Hex) ::: Meanings\n");
printf(" FC : AT\n");
printf(" FE : XT\n");
printf(" FB : XT\n");
printf(" FF : PC\n");

printf("\n\nYour PC Type Code (Hex): %X",*ptrPcType);

getch( );
return 0;
}
19

You might also like