systemprogfile.pdf
TRANSCRIPT
-
8/14/2019 systemprogfile.pdf
1/11
Experiment No.1
Aim-To understand the concept of macros.
Theory-:
A macrois a fragment of code which has been given a name. Whenever the name is used, it
is replaced by the contents of the macro. There are two kinds of macros. They differ mostly
in what they look like when they are used. Object-likemacros resemble data objects when
used, function-likemacros resemble function calls.
You may define any valid identifier as a macro, even if it is a C keyword. The preprocessor
does not know anything about keywords. This can be useful if you wish to hide a keyword
such as const from an older compiler that does not understand it. However, the preprocessor
operator defined can never be defined as a macro
Q1>Write a program to implement macro to add two numbers.
Write a program
#include
#define macro1(a,b) (a+b)
#include
Void main()
{
Int n1,n2;
clrscr();
printf(enter two numbers);
scanf(%d%d,&n1,&n2);
printf(Sumof two numbers %d,macro1(n1,n2));
getch();
}
-
8/14/2019 systemprogfile.pdf
2/11
Experiment No.2
Aim-To check the validity of string for a given grammar
Theory-:
Informal language theory, a context-free grammar (CFG) is aformal grammar in which
everyproduction rule is of the form
V w
where V is a singlenonterminal symbol, and w is a string ofterminals and/or
nonterminals (w can be empty).
Thelanguages generated by context-free grammars are known as thecontext-free
languages.
A formal grammar is considered "context free" when its production rules can be appliedregardless of the context of a nonterminal.
Context-free grammars are important inlinguistics for describing the structure of
sentences and words innatural language, and incomputer science for describing the
structure ofprogramming languages and other formal languages.
Inlinguistics,some authors use the termphrase structure grammar to refer to context-free
grammars, whereby phrase structure grammars are distinct fromdependency grammars.
Incomputer science,a popular notation for context-free grammars isBackusNaur Form,
or BNF.
A context-free grammar G is defined by the 4-tuple:[3]
where
1. is a finite set; each element is called a non-terminal character or a variable.Each variable represents a different type of phrase or clause in the sentence.
Variables are also sometimes called syntactic categories. Each variable defines a sub-
language of the language defined by .
2. is a finite set of terminals, disjoint from , which make up the actual content of thesentence. The set of terminals is the alphabet of the language defined by thegrammar .
3. is a finite relation from to , where the asterisk represents theKleenestar operation. The members of are called the (rewrite) rules or productions of the
grammar. (also commonly symbolized by a )
4. is the start variable (or start symbol), used to represent the whole sentence (orprogram). It must be an element of .
http://en.wikipedia.org/wiki/Formal_language_theoryhttp://en.wikipedia.org/wiki/Formal_grammarhttp://en.wikipedia.org/wiki/Production_(computer_science)http://en.wikipedia.org/wiki/Nonterminalhttp://en.wikipedia.org/wiki/Terminal_and_nonterminal_symbolshttp://en.wikipedia.org/wiki/Formal_languagehttp://en.wikipedia.org/wiki/Context-free_languagehttp://en.wikipedia.org/wiki/Context-free_languagehttp://en.wikipedia.org/wiki/Linguisticshttp://en.wikipedia.org/wiki/Natural_languagehttp://en.wikipedia.org/wiki/Computer_sciencehttp://en.wikipedia.org/wiki/Programming_languagehttp://en.wikipedia.org/wiki/Linguisticshttp://en.wikipedia.org/wiki/Phrase_structure_grammarhttp://en.wikipedia.org/wiki/Dependency_grammarhttp://en.wikipedia.org/wiki/Computer_sciencehttp://en.wikipedia.org/wiki/Backus%E2%80%93Naur_Formhttp://en.wikipedia.org/wiki/Backus%E2%80%93Naur_Formhttp://en.wikipedia.org/wiki/Backus%E2%80%93Naur_Formhttp://en.wikipedia.org/wiki/Tuplehttp://en.wikipedia.org/wiki/Context-free_grammar#cite_note-3http://en.wikipedia.org/wiki/Kleene_starhttp://en.wikipedia.org/wiki/Kleene_starhttp://en.wikipedia.org/wiki/Kleene_starhttp://en.wikipedia.org/wiki/Kleene_starhttp://en.wikipedia.org/wiki/Context-free_grammar#cite_note-3http://en.wikipedia.org/wiki/Tuplehttp://en.wikipedia.org/wiki/Backus%E2%80%93Naur_Formhttp://en.wikipedia.org/wiki/Computer_sciencehttp://en.wikipedia.org/wiki/Dependency_grammarhttp://en.wikipedia.org/wiki/Phrase_structure_grammarhttp://en.wikipedia.org/wiki/Linguisticshttp://en.wikipedia.org/wiki/Programming_languagehttp://en.wikipedia.org/wiki/Computer_sciencehttp://en.wikipedia.org/wiki/Natural_languagehttp://en.wikipedia.org/wiki/Linguisticshttp://en.wikipedia.org/wiki/Context-free_languagehttp://en.wikipedia.org/wiki/Context-free_languagehttp://en.wikipedia.org/wiki/Formal_languagehttp://en.wikipedia.org/wiki/Terminal_and_nonterminal_symbolshttp://en.wikipedia.org/wiki/Nonterminalhttp://en.wikipedia.org/wiki/Production_(computer_science)http://en.wikipedia.org/wiki/Formal_grammarhttp://en.wikipedia.org/wiki/Formal_language_theory -
8/14/2019 systemprogfile.pdf
3/11
Q2>Write a program to check whether the entered string is accepted or not for a givengrammar. Strings acceptable by grammar are of form: ab*c(a+b)
#include
#include
#include#include
char a[100];
int n, i;
void main()
{
clrscr();
printf(\nenter string);
scanf(%s,&a);
n=strlen(a);
if(a[0]==a && (a[n-1]==a || a[n-1]==b) && a[n-2]==c)
{for(i=1; i
-
8/14/2019 systemprogfile.pdf
4/11
Experiment No.3
Aim-To understand the implementation of far, near, huge pointer
Theory-:
Four registers are used to refer to four segments on the 16-bit x86 segmented memory
architecture. DS (data segment), CS (code segment), SS (stack segment), and ES (extra
segment). A logical address on this platform is written segment:offset, inhexadecimal.In real
mode, in order to calculate the physical address of a byte of memory, one left-shifts the
contents of the appropriate register 4 bits, and then adds the offset.
For example the logical address 7522:F139 yields the 20-bit physical address:
75220 + F139 = 84359
Note that this process leads toaliasing of memory, such that any given physical address may
have multiple logical representations. This makes comparison of pointers difficult.
Actually there are 3 types of pointers:
1) near
2) far
3) huge
Near Pointers: These pointers are 2 bytes long always i.e. any pointer that you declared
normally they are 2 bytes long. This permits only 2^16 values which implies that you can
access only the code which is in your data segment (since 1 segment is 64KB = 2^16). Any
attempt to access data will result in segment protection error from the OS.
Far and Huge Pointers: We take both these two since they are common and differ only
when some arithmetic is performed using these pointers.
Far and Huge pointers are both 4 bytes long. This means they can handle about 2^32= 2GB
of memory locations. Now since we dont have that much amount of memory when we are
real mode (when computer starts up) we are safe since only 1MB is available (only 20
address lines available instead of 32 present address lines). We can access the whole of
memory when we are in protected mode. This mode gives the whole 2GB memory as a flat
i.e. no segments are available when in protected mode. But since we are in real mode our max
http://en.wikipedia.org/wiki/X86http://en.wikipedia.org/wiki/Hexadecimalhttp://en.wikipedia.org/wiki/Aliasing_%28computing%29http://en.wikipedia.org/wiki/Aliasing_%28computing%29http://en.wikipedia.org/wiki/Hexadecimalhttp://en.wikipedia.org/wiki/X86 -
8/14/2019 systemprogfile.pdf
5/11
memory limit is 1MB and our memory is fragmented into different segments of 64Kb each in
size.
To access any memory location in the 1MB limit we first find the starting address of the
segment then to this address (base address of segment) an offset of 16 bits is added. The way
these addresses are added is a bit tricky. First the segments address is left shifted by 4 bits
(padded with 4 zeros in the end) and then the offset is added to it. Now this is a full 20 bit
address and processor use this address to locate a memory location in the 1MB limit. The
shifting need not be done by us since processor does that for us we just need to supply the
segments base address and an offset within that segment.
All segments starts at some multiple of 16 also called a paragraph boundary. This is because
for each 16 bit segment address it is first left shifted by 4 bits (2^4=16 bytes).
One more thing where these pointers differ from each other is in the way they are stored. Far
pointers are not normalized while huge pointers are normalized. Normalization means that
they have most part of the address in the segment. This is not a problem if you will perform
logical / arithmetic operations on such pointers but if you do then using huge will benefit you
since the results will be same as expected while with far pointers you may get strange results.
Huge pointer arithmetic is therefore more complex which requires macros and thus slows
down the performance.
Declaring far /huge pointers
The Turbo C provides us the keywords far and huge to declare such pointers. Just add these
keywords and declare these pointers like you normally do.
Example int far *ptr; (this ptr is a far pointer to an int)
int huge *ptr(this ptr is huge pointer to an int)
Why do we need these pointers while writing ISRs?
Well as I said before with normal / near pointer declaration we cant access the code outside
of our data segment. Since ISR s require us to go beyond our data segment we must use these
pointers. Only far can be used huge may not be required since theres not much in the data
segment which we need to access. Using huge pointers we can access more than 1MBs of
data in the data segment while 1MB when we use far.
-
8/14/2019 systemprogfile.pdf
6/11
Q3>Write a program to study the implementation of far, huge, near pointers.
Far pointer
Void main()
{
char far *a = 0x00000120;
char far *b = 0x00100020;
char far *c = 0x00120000;
if(a==b)
printf(\n hello);
if(a==c)
printf(\n hi)
if(b==c)
printf(\n hello hi);
if(a>b && a>c && b>c)
printf(bye);
}
Near pointer
Void main()
{
char near *a = 0x00000120;
char near *b = 0x00100020;
char near *c = 0x00120000;
if(a==b)
printf(\n hello);
if(a==c)
printf(\n hi)
if(b==c)
printf(\n hello hi);
if(a>b && a>c && b>c)
printf(bye); }
-
8/14/2019 systemprogfile.pdf
7/11
Huge pointer
Void main()
{
char huge *a = 0x00000120;
char huge *b = 0x00100020;
char huge *c = 0x00120000;
if(a==b)
printf(\n hello);
if(a==c)
printf(\n hi)
if(b==c)
printf(\n hello hi);
if(a>b && a>c && b>c)
printf(bye);
}
-
8/14/2019 systemprogfile.pdf
8/11
Experiment No.4
Aim-To understand concept of absolute loaderTheory-:
Definition of Loader:Loader is utility program which takes object code as input prepares itfor execution and loads the executable code into the memory. Thus loader is actually
responsible for initiating the execution process.
Absolute Loader: Absolute loader is a kind of loader in which relocated object files are
created, loader accepts these files and places them at specified locations in the memory. This
type of loader is called absolute because no relocation information is needed; rather it is
obtained from the programmer or assembler. The starting address of every module is known
to the programmer, this corresponding starting address is stored in the object file, then task of
loader becomes very simple and that is to simply place the executable form of the machine
instructions at the locations mentioned in the object file. In this scheme, the programmer or
assembler should have knowledge of memory management. The resolution of external
references or linking of different subroutines are the issues which need to be handled by the
programmer. The programmer should take care of two things: first thing is : specification of
starting address of each module to be used. If some modification is done in some module then
the length of that module may vary. This causes a change in the starting address of immediate
next . modules, its then the programmer's duty to make necessary changes in the starting
addresses of respective modules. Second thing is ,while branching from one segment to
another the absolute starting address of respective module is to be known by the programmer
so that such address can be specified at respective JMP instruction.
The absolute loader is simple to implement in this scheme-
l) Allocation is done by either programmer or assembler
2) Linking is done by the programmer or assembler
3) Resolution is done by assembler
4) Simply loading is done by the loader
-
8/14/2019 systemprogfile.pdf
9/11
Q4>Write a c program to implement absolute loader.
#include
#include
#include
#include
void main()
{
char *record,*obj,*names;
int addr,len,i;
FILE *fp;
clrscr();
fp=fopen("IN.TXT","r");
fscanf(fp,"%s%s%d%d",record,name,&addr,&len);
if(strcmp(record;"H")==0)
{
printf("program name=%s",name);
printf("starting address=%d",addr);
}
while(!feof(fp))
{
fsane(fp,"%s",record);
if(strcmp(record,"E")==0)
{
fscan(fp,%x",&addr);
printf("address of the first statment %d",addr);
break;
}
else if(strcmp(record,"T")==0)
{
-
8/14/2019 systemprogfile.pdf
10/11
fscanf(fp,"%x5x%s",&addr,&len,obj);
for(i=0;i
-
8/14/2019 systemprogfile.pdf
11/11
Experiment No.5
Aim-Conversion of a physical address into segment and offset
Theory-:
There are often many different Segment:Offset pairs which can be used to address the same
location in your computer's memory. This scheme is a relative way of viewing computer
memory as opposed to a Linear or Absolute addressing scheme. When an Absolute
addressing scheme is used, each memory location has its own unique designation; which is a
much easier way for people to view things. So, why did anyone ever create this awkward
"Segment:Offset scheme" for dealing with computer memory? As an answer, here's a brief
lesson on the 8086 CPU with an historical slant:
Segment:Offset addressing was introduced at a time when the largest register in a CPU was
only 16-bits long which meant it could address only 65,536 bytes (64 KiB[1]) of memory,
directly. But everyone was hungry for a way to run much larger programs! Rather than create
a CPU with larger register sizes (as some CPU manufacturers had done), the designers at
Intel decided to keep the 16-bit registers for their new 8086 CPU and added a different way
to access more memory: They expanded the instruction set, so programs could tell the CPU to
group two 16-bit registers together whenever they needed to refer to an Absolute memory
location beyond 64 KiB.
Q5>Write a program in c to print Segment:Offset value.
#include
main()
{
Char far * ptr;
Unsigned seg,off;
Ptr=MK_FP(0xb000,0);
Seg=FP_SEG(ptr);
Off=FP_OFF(ptr);
Printf(\n far ptr %Fp,ptr);
Printf(\n segment %x,offset %x,seg,off);
}