Showing posts with label C Programming. Show all posts
Showing posts with label C Programming. Show all posts

Monday, March 21, 2022

Interaction with Hardware through 'C'

 Interrupt & Interrupt Vector table

What is Interrupt?

The interrupt is a signal produced by hardware or software when a process or an event needs immediate attention. It alerts the processor of a system to stop / suspend the current working process and give attention to the process which generates an interrupt.

After the execution of the interrupt service routine, the processor resumes the execution of the suspended program / process.

There are two types of interrupts

i)      Software Interrupt

A software interrupt is caused either by an exceptional condition or a special instruction in the program, which causes an interrupt when it is executed by the processor.

ii)    Hardware Interrupt

A hardware interrupt is an electronic signal sent to the processor from an external device or an external peripheral. For example, when we press a key on the keyboard or move the mouse, they trigger hardware interrupts which cause the processor to read the keystroke or mouse position.

Interrupt Vector Table:

The interrupt vector table, often abbreviated to IVT, is a data structure that associates a list of interrupt handlers i.e. an array of pointers to functions. The IVT and the handlers are used to handle specific exceptions, such as faults, system service requests from the application, and interrupt requests from peripherals.

ROMBIOS Philosophy:

Calling a ROM-BIOS functions is not so simple, because, ROM-BIOS functions do not have names. These can be called by obtaining their addresses, and passing control to these addresses. The addresses of ROM-BIOS functions are stored in the Interrupt Vector Table (IVT).

At the specific moment when the ROM-BIOS function is called, the microprocessor is usually busy doing something; and the microprocessor is capable of performing only one task at a time.

All ROM-BIOS functions are invoked through 'interrupts'. Each interrupt instruction selects a particular address in the IVT and passes control to this address. This design makes it possible for any program to use a ROM-BIOS function without knowing its specific memory location.

There are numerous ROM-BIOS functions available. They have been divided into subject categories, each with its own controlling interrupt. For example, all functions related with VDU are grouped under interrupt number 16, all functions related with printer are grouped under interrupt number 23 and so on.

Invoking ROM-BIOS Function:

To call ROM-BIOS function we should perform the following steps:

i)       Make an Interrupt occur.

ii)     Find the interrupt number occurred

iii)  Obtain the address of Interrupt Service Routine form IVT

iv)   Place the values in CPU registers as required by ROMBIOS function

v)     Execute the ROMBIOS function

From the steps above, except for steps (i) and (iv) all other steps are performed by the microprocessor itself. So our task is just place the values needed by the ROM-BIOS routine and make a software interrupt to occur.

In language ‘C’ the software interrupt can be caused by using the standard library function int86( ), this function is also used to place values in CPU registers, as required by the ROM-BIOS function.

The ROM-BIOS functions have been written in such a manner that, some functions expect values to be placed in registers AX, BX, CX etc., whereas some functions expect a different value in high byte (AH) of AX register, and a different value in low byte (AL) of AX register, and so on.

int86( ) function

The int86() is a standard library function present in the <dos.h> header file, is used to make a software interrupt occur and thus invoke a ROM-BIOS function. Here int stands for interrupt and 86 refers to the 8086 family of microprocessors.

The function int86( ) requires three arguments:

-          An interrupt number corresponding to the ROM-BIOS function to invoked.

-          Two union variables. The first union variable represents the value being sent to the ROM-BIOS routine and the second variable represents the value which being returned from ROM-BIOS routines.

 

The general syntax for int86( ) function is:

            int86( interrupt_no, inputRegis, outputRegis);

Example:

            Int86(16, &inregs, &outregs);

Here 16 is the interrupt number, inregs represents the register value to be sent to ROM-BIOS function and outregs represents the register value returned by the ROM-BIOS function.

Interrupts to access ROMBIOS Services.

There are number of ROM-BIOS services available, these services are grouped together according to their similarities under one interrupt for example the interaction with VDU / Monitor are grouped together under interrupt number 16.

The following table gives description of some of the ROM-BIOS services under that interrupt number.



Friday, March 18, 2022

Bit wise Operators in C

 Bit Operations

 One's Compliment operator

    Ø  Bitwise one's compliment operator will invert the binary bits.

Ø  Bitwise compliment operator is an unary operator. It is denoted by ~.

Ø  It changes 1 to 0 and 0 to 1. i.e. If a bit is 1, it will change it to 0. and If the bit is 0, it will change it to 1.

 Let’s consider a number 5.

 Then ~5 will be,

5 = (00000101)2

~5 = (11111010)2. It will convert all 1 to 0 and 0 to 1.

 Program:

 #include <stdio.h>

#include <conio.h>

void main()

{

   int a = 9; 

   int c;          

   c = ~(a);     

   printf("The Ones Complement is %d", c);

   getch();

}

Right shift Operator: The right shift operator is represented by >>. It needs two operands. It shifts each bit in its left operand to the right.

The >> (right shift) in C takes two numbers, right shifts the bits of the first operand, the second operand decides the number of places to shift. In other words, right shifting an integer “a” with an integer “b” can be denoted as a>>b.

 For example: if the variable ch contains the bit pattern 11010111, then, ch >> 1 would give 01101011

 Program:

     #include <stdio.h>

#include <conio.h>

void main()

{

   int a = 5; 

   int c;          

   c = a>>1;     

   printf("After Right Shift result is %d", c);

   getch();

}

 Left shift Operator: The left shift operator is represented by <<. It needs two operands. It shifts each bit in its left operand to the left.

The << (left shift) in C takes two numbers, left shifts the bits of the first operand, the second operand decides the number of places to shift. In other words, left shifting an integer “a” with an integer “b” can be denoted as a<<b.

 For example: if the variable ch contains the bit pattern 11010111, then, ch << 1 would give 10101110



Program:

      #include <stdio.h>

#include <conio.h>

void main()

{

   int a = 5; 

   int c;          

   c = a<<1;     

   printf("After Left Shift result is %d", c);

   getch();

}

 

Bit wise operator- AND

This operator is represented as &. It is different than &&, the logical AND operator. The bit wise & operator operates on two operands. While operating upon these two operands they are compared on a bit-by-bit basis so both the operands must be of the same data type.

The rules for bit wise & operations are as follows:

 


For example:

A=5;

B=4;

C = A & B

It can be represented as

00000101            Original Bit Pattern

00000100             Mask with 4

----------------

00000000             Result

 

Program:

      #include <stdio.h>

#include <conio.h>

void main()

{

   int a = 5, b = 4; 

   int c;          

   c = a & b;     

   printf("After AND operation result is %d", c);

   getch();

}

Bit wise operator- OR

This operator is represented as |. It is different than ||, the logical OR operator. The bit wise | operator operates on two operands. While operating upon these two operands they are compared on a bit-by-bit basis so both the operands must be of the same data type.

 The rules for bit wise | operations are as follows:

 


For example:

A=5;

B=4;

C = A | B

It can be represented as

00000101            Original Bit Pattern

00000100             Mask with 4

----------------

00000101             Result

 Program:

      #include <stdio.h>

#include <conio.h>

void main()

{

   int a = 5, b = 4; 

   int c;          

   c = a | b;     

   printf("After OR operation result is %d", c);

   getch();

}

Bit wise operator- XOR

This operator is represented as ^. The bit wise ^ operator operates on two operands. While operating upon these two operands they are compared on a bit-by-bit basis so both the operands must be of the same data type.

 The rules for bit wise ^ operations are as follows:



 For example:

A=5;

B=4;

C = A ^ B

It can be represented as

00000101            Original Bit Pattern

00000100             Mask with 4

----------------

00000001             Result

 

Program:

      #include <stdio.h>

#include <conio.h>

void main()

{

   int a = 5, b = 4; 

   int c;          

   c = a ^ b;     

   printf("After XOR operation result is %d", c);

   getch();

}

 

Structure and Union

 Structure and Union

Introduction of structure,

Ø  Structure is a user-defined datatype in C language which allows us to combine data of different types together.

  • The keyword struct  is used to define a structure.
  • The collection of variables inside the structure are called as members of structure
  • The size of structure can be calculated as the total size of all members used in the structure.
  • To access the members of structure dot ( . ) operator is used, if we are working with pointer structure then points to (->) operator is used.

Declaration & initialization.

The general syntax of structure is

struct name_of_structure

{

   data_type variableName1 / MemberName1

   data_type variableName2 / MemberName2

   data_type variableName3 / MemberName3

   .

   .

   .

   data_type variableNamen / MemberNamen

};

 

Example:

struct Student

{

   int sno;

  char sname[20];

  float avg;

};

In above example struct Student is a structure with sno, sname and avg as members of that structure.

Creating Variable of Structure:

To create variable of structure following statement is used

            struct Student s1;

Initializing the members of structure:

The structure members can be initialize in two different ways

1) struct Student s1 = {12,”Rajesh”,88.9};

2)       struct Student s1;

            s1.sno = 90;

            s1.sname=”Rajesh”;

            s1.avg=88.9;

in above example s1 is a variable / instance of structure student. The members of structure are accessed using dot ( . ) operator.

Programe:

#include<stdio.h>

#include<conio.h>

struct Student

{

    int rno;

    char sname[20];

};

void main()

{

     struct Student s1;

     clrscr();

     printf(“Enter Roll number of Student “);

     scanf(“%d”, &s1.rno);

     printf(“Enter Name of Student “);

     scanf(“%s”, &s1.sname);

     printf(“Roll Number = %d”,s1.rno);

     printf(“\n Name = %s”, s1.sname);

     getch();

}

 

Arrays of Structures:

We can also declare an array of structure variables in which each element of the array will represent a structure variable. 

Example : struct Student s1[5];

The program below defines an array s1 of size 5. Every element of the array s1 is of type Student.

Programe:

#include<stdio.h>

#include<conio.h>

struct Student

{

    int rno;

    char sname[20];

};

void main()

{

     struct Student s1[5];

     int i;

     clrscr();

     for(i=0;i<5;i++)

     {

        printf(“Enter Roll number of Student “);

        scanf(“%d”, &s1[i].rno);

        printf(“Enter Name of Student “);

        scanf(“%s”, &s1[i].sname);

      }

      for(i=0;i<5;i++)

      {

        printf(“Roll Number = %d”,s1[i].rno);

        printf(“\n Name = %s”, s1[i].sname);

      }

       getch();

}

 

Structure within structure

In C, we can declare and place a structure inside another structure. This is also known as nesting of structure; it is also known as Structure within Structure. The declaration is same as the declaration of data type in structure. Structure within structure (or) nesting of structure is used to create complex records.

Example 1:

struct Student

{

    int rno;

    char sname[20];

    struct CollegeDetails

    {

          int collegeNo;

          char collName[20];

     } clg;

};

The above nesting structure can also be written as

struct CollegeDetails

{

    int collegeNo;

    char collName[20];

};

struct Student

{

    int rno;

    char sname[20];

    struct CollegeDetails clg;

};

 

The programe can be written as

#include<stdio.h>

#include<conio.h>

 struct CollegeDetails

{

    int collegeNo;

    char collName[20];

};

 struct Student

{

    int rno;

    char sname[20];

    struct CollegeDetails clg;

};

void main()

{

     struct Student s1;

     clrscr();

     printf(“Enter Roll number of Student “);

     scanf(“%d”, &s1.rno);

     printf(“Enter Name of Student “);

     scanf(“%s”, &s1.sname);

     printf(“Enter College Number “);

     scanf(“%d”, &s1.clg.collegeNo);

     printf(“Enter College Name “);

     scanf(“%s”, &s1.clg.collName);

      printf(“Roll Number = %d”,s1.rno);

     printf(“\n Name = %s”, s1.sname);

     printf(“\n College Number = %d”,s1.clg.collegeNo);

     printf(“\n College Name = %s”, s1.clg.collName);

      getch();

}

 

Introduction to Union.

Ø  A union is a user defined datatype in C programming language.

Ø  It is a collection of variables of different datatypes in the same memory location.

Ø  We can define a union with many members, but at a given point of time only one member can contain a value.

Ø  Union in C language allow data members which are mutually exclusive to share the same memory.

Ø  The size of the union is the size of its largest member because sufficient number of bytes must be reserved to store the largest sized member.

Declaration & initialization

Syntax for declaring a union is same as that of declaring a structure except the keyword struct.

union name_of_union

{

   data_type variableName1 / MemberName1

   data_type variableName2 / MemberName2

   data_type variableName3 / MemberName3

   .

   .

   .

   data_type variableNamen / MemberNamen

};

 

Example:

union Student

{

   int sno;

  char sname[20];

};

 Programe:

#include<stdio.h>

#include<conio.h>

union Day

{

    int dayno;

    char dayname[20];

};

void main()

{

     union Day d1;

     clrscr();

     printf(“Enter Day number “);

     scanf(“%d”, &d1.dayno);

     printf(“\n Day Number is %d”, d1.dayno); // will display day number

     printf(“\n Enter Day Name “);

     scanf(“%s”, &d1.dayname);

     printf(“\n Day Name = %s”,d1.dayname); // will display day name

     printf(“\n Day Number = %d”, s1.dayno);  // will display garbage value

     getch();

}