0% found this document useful (0 votes)
15 views16 pages

SPCC

The document discusses the differences between system software and application software. System software maintains system resources and allows application software to run, while application software is built for specific tasks. System software programming is more complex and operates independently of users, while application software is dependent on system software and connects users to computers.

Uploaded by

rp2145611
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
15 views16 pages

SPCC

The document discusses the differences between system software and application software. System software maintains system resources and allows application software to run, while application software is built for specific tasks. System software programming is more complex and operates independently of users, while application software is dependent on system software and connects users to computers.

Uploaded by

rp2145611
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 16

Q1 Difference Between System Software And Application Software.

System Software Application Software


System Software maintains the system Application software is built for specific
resources and gives the path for application tasks.
software to run.
Low-level languages are used to write the While high-level languages are used to write
system software. the application software.
It is general-purpose software. While it’s a specific purpose software.
Without system software, the system stops and While Without application software system
can’t run. always runs.
System Software programming is more Application software programming is simpler
complex than application software. in
comparison to system software.
A system software operates the system in the Application software runs in the front end
background until the shutdown of the according to the user’s request.
computer.
System software runs independently. Application software is dependent on system
software because they need a set platform for
its functioning.
The system software has no interaction with Application software connects an
users. It serves as an interface between intermediary between the user and the
hardware and the end user. computer.
System software runs when the system is While application software runs as per the
turned on and stops when the system is user’s request.
turned
off.
Example: System software is an operating Example: Application software is Photoshop,
system, etc. VLC player, etc.
Q2 Compare Bottom Up And Top Down Parser.
Top Down Parsing Bottom Up Parsing
It is a parsing strategy that first looks at the It is a parsing strategy that first looks at the
highest level of the parse tree and works down lowest level of the parse tree and works up
the parse tree by using the rules of grammar. the
parse tree by using the rules of grammar.
Top-down parsing attempts to find the left Top-down parsing attempts to find the left
most derivations for an input string. most derivations for an input string.
In this parsing technique we start parsing from In this parsing technique we start parsing
the top (start symbol of parse tree) to down from the bottom (leaf node of the parse tree)
(the leaf node of parse tree) in a top-down to up (the start symbol of the parse tree) in a
manner. bottom-up manner.
This parsing technique uses Left Most This parsing technique uses Right Most
Derivation. Derivation.
The main leftmost decision is to select what The main decision is to select when to use a
production rule to use in order to construct the production rule to reduce the string to get the
string. starting symbol.
Example: Recursive Descent parser. Example: ItsShift Reduce parser.
Q1 Draw Flowchart Of A Pass-I Of Two Pass Assembler Design And Explain In Detail.
Two-pass assembler involves breaking down the assembly process into two distinct phases: Pass I
and Pass II. In Pass I, the assembler scans the source code once, building a symbol table and
generating intermediate code or data structures that are needed for Pass II
Start: The assembler begins the Pass I process. Read First Line of Source Code: The
assembler reads the first line of the source code file. Check for Comments or Empty
Lines: It checks if the line is a comment or empty. If so, it skips to the next line. Parse
Label: If there is a label present in the line, it is parsed and added to the symbol
Pass 1
table along with its corresponding address or location counter value. Parse Opcode
Operation: The assembler parses the opcode or operation mnemonic. If it's an
Lc0 assembler directive (like ORG or EQU), it handles it accordingly, updating the
location counter or symbol table entries as necessary. If it's an instruction, the
location counter is incremented. Parse Operands: If there are operands present, they
are parsed. If an operand is a symbol, it is added to the symbol table if it's not
Read already present. Repeat for Next Line: Steps 2-6 are repeated for each subsequent
card line of the source code until the end of the file is reached. End of Pass I: Pass I
Read 1 concludes after scanning entire code,building symbol table,handling assembler
directives.
Found Using
DS/DC EQU END
Search Pseudo op table Drop
potget1 Which
NOT Found
Search machine table Adjust LCto Evaluate Assign storage
Motget 1 proper Alignment operand fleld locationto iterals
EVAL LITASS
LengthL
L length of
Reset oopy
data field
file
Process any literale, DLENGTH
enter into literal table Assign value to
LTSTO symbol in label field
STSTO
On to Pass
2
Is symbol Assign current value
in field? YEs of LCto symbol
no STSTO

LCLC+L

Write copy of Card on Pass2


WRITE 1
Q3 Explain With Flowchart Design Of Two Pass Assembler.
Designing a flowchart for a two-pass assembler involves illustrating the steps taken in each pass to
process the source code and generate the corresponding machine code. Here's a simplified
Start: The assembler begins the two-pass process. Pass I: In Pass I, the
assembler scans the entire source code, building a symbol table and
generating necessary information for Pass II. It parses each line of
code, extracting labels, opcodes, and operands. Labels are added to
Paaa 2
the symbol table along with their corresponding addresses.
Assembler directives are handled, and the location counter is
incremented accordingly. Operands are processed, and symbols
Lc0 encountered are added to the symbol table. Pass II: In Pass II, the
assembler re-scans the source code, generating the final machine code
using the symbol table built in Pass I. It parses each line of code,
resolving symbolic addresses using the symbol table. Labels, opcodes,
and operands are processed similarly to Pass I, but with the addition of
Road oand from file
address resolution for symbols. End of Pass II: Pass II concludes after
oopy
READ2 processing the entire source code and generating the final machine code.

DC/DS USIng DROP END


EQU start
Soarch pseudo-op Which ono
table
POTGET2

Adjust LO to propor Evaluato Indicate


Alignmont oporand base reg
Search machine-op
field no,
tabe
unavaila
MOTGET From
ble
oonatant
and ingert in
Get op-codebyto asoomblod
andtomat oode, Not DCor DS DC
program
found Llength
Enter base
DS reg no and
Type of Instructlon value Into
LLength of data base table

Evaluate both,reglster
expresslons and Inser A
sinto 2nd byte
EVAL Prnt listing
Evaluateregister and PRINT
Indexexpressions and
Punch assambled insert into 2nd byte
Instruction
PUNCH
Caloulate effootlve
address (EA) of
operand
Print assombly tisting line Generate literale
PRINT Detomine appropnate for entries In
dlsplaoement and LIteral Table
base

LCLC+L Put B and D into byte STOP


3 and 4
Q5 Explain Different Assembler Directives With Example.
In the context of Systems Programming and Compiler Construction (SPCC), assembler directives
are commands or instructions embedded within assembly language code that provide guidance to
the assembler on how to process the source code. These directives are not translated into machine
code but rather instruct the assembler on various aspects of the assembly process, such as defining
symbols, allocating memory, or controlling program flow. Here are some common assembler
directives along with examples:
ORG (Origin): The ORG directive specifies the origin or starting address for the subsequent instructions
or data in memory. Syntax: ORG address Example: ORG 1000
This directive instructs the assembler to start placing instructions or data at memory address 1000.
EQU (Equation): The EQU directive assigns a constant value to a symbol or label.
Syntax: symbol EQU value Example: MAX_LENGTH EQU 100
This directive defines the symbol MAX_LENGTH to represent the constant value 100.
DS (Data Storage): The DS directive reserves memory space for data storage.
Syntax: label DS size Example: BUFFER DS 50
This directive reserves 50 bytes of memory space for the buffer named BUFFER.
DC (Data Constant): The DC directive initializes memory with constant data values.
Syntax: label DC value Example: NUMBERS DC 10, 20, 30, 40
This directive initializes memory locations with the values 10, 20, 30, and 40 sequentially starting from
the address labeled NUMBERS.
START: The START directive indicates the starting point of the program.
Syntax: START label Example: START MAIN
This directive specifies that the program execution should begin at the label MAIN.
END: The END directive marks the end of the program.
Syntax: END Example: END
This directive indicates the end of the assembly language source file.
INCLUDE: The INCLUDE directive includes the contents of another file into the current source file.
Syntax: INCLUDE filename Example: INCLUDE constants.asm
This directive includes the contents of the file named constants.asm at the point of declaration.
Q2 Draw A Neat Flowchart Of Two Pass Micro Processor. Explain With The Help Of Example.
The concept of a "two-pass assembler" for a microprocessor involves assembling a program
in two distinct phases or passes. This process is crucial for resolving symbols and addresses
correctly before generating the final machine code. Let's delve into an explanation
supplemented by a simple example to elucidate how a two-pass assembler operates.
Pass 1: Building the Symbol Table
The primary objective of the first pass is to scan the entire source code to build a symbol
table. The symbol table contains all the labels (symbols) used in the program along with their
addresses. This pass does not generate any machine code. Instead, it prepares the assembler
by resolving all the labels and calculating their addresses, which are essential for the second
pass.
Tasks Performed in Pass 1:
Read each line of the source code.
Identify and record labels with their corresponding addresses.
Process directives that might affect addresses (e.g., `ORG` to set the starting address).
Calculate the address of the next instruction or data element by taking into account the size
of the current instruction or data directive.
Pass 2: Generating Machine Code
During the second pass, the assembler reads the source code again, this time using the
symbol table constructed in Pass 1 to generate the final machine code. It resolves all symbol
references to their corresponding addresses and translates assembly instructions into machine
code.
Tasks Performed in Pass 2:
Read each line of the source code again.
Translate instructions into machine code, using the symbol table to resolve addresses of labels.
Handle assembler directives that influence the generation of machine code (e.g., `BYTE`,
`WORD`, `RESB`,
`RESW` for data storage).
Generate data definitions according to the directives encountered.
Output the machine code, along with any necessary relocation information.
Example
Consider a simple assembly program that loads a value into a register and then jumps to a
label based on a condition:
ORG 100H ; Start at address 100H START: MOV AL, 5 ; Load AL with the value 5
CMP AL, 10 ; Compare AL with 10 JL LABEL ; Jump if less to LABEL
MOV AL, 7 ; Otherwise, load AL with 7 LABEL: HLT ; Halt the processor
Pass 1 (Building the Symbol Table):
The assembler scans the program.
It identifies `START` and `LABEL` as labels and assigns them addresses based on the current
location counter, which starts at `100H`.
After Pass 1, the symbol table might look like this:
Label Address
START 100H
LABEL 106H
Pass 2 (Generating Machine Code):
The assembler scans the program again.
For each instruction, it generates the corresponding machine code. For example, `MOV AL, 5` is
translated into its opcode and operand.
When it encounters `JL LABEL`, it uses the symbol table to resolve `LABEL` to its address `106H`
and generates the appropriate jump instruction with this address.
Q3 Explain Different Features Of Macro With Example.
Macros are a powerful feature in programming languages that enable code abstraction and
reusability. They allow you to define a block of code or expressions and then reuse it multiple
times throughout your program. Here are some common features of macros.
Parameterized Macros:
Parameterized macros allow you to define macros with parameters, making them more flexible and
reusable.
Example:
#define MAX(x, y) ((x) > (y) ? (x) : (y))
In this example, `MAX` is a parameterized macro that takes two parameters `x` and `y`. It returns the
maximum of the two values.
Argument Substitution:
Macro parameters can be substituted directly into the macro body, enabling you to create generic
code. Example:
#define SQUARE(x) ((x) * (x))
In this example, the parameter `x` is substituted into the macro body to calculate the square of the
value.
Code Expansion:
When you use a macro in your code, the preprocessor replaces the macro with its corresponding
code body.
Example:
int a = 5; int b = 7;
int max_value = MAX(a, b);
After macro expansion, the code becomes: int max_value = ((a) > (b) ? (a) : (b));
Conditional Compilation:
Macros can be used to conditionally include or exclude code during compilation based on certain
conditions.
Example:
#ifdef DEBUG
#define DEBUG_PRINT(x) printf(x) #else
#define DEBUG_PRINT(x) #endif
In this example, the `DEBUG_PRINT` macro will only expand to `printf(x)` if the `DEBUG` symbol is
defined during compilation.
Stringification:
The `#` operator allows you to convert macro parameters into string literals. Example:
#define STRINGIFY(x) #x
printf("Value of x: %s\n", STRINGIFY(42)); After macro expansion, the code becomes:
printf("Value of x: %s\n", "42");
Concatenation:
The `##` operator allows you to concatenate tokens within a macro. Example:
#define CONCAT(x, y) x ## y
int xy = CONCAT(10, 20); // This will be equivalent to int xy = 1020;
These are some common features of macros in SPCC, each providing a powerful mechanism for
code abstraction, reuse, and conditional compilation. However, it's important to use macros
judiciously to avoid code readability issues and potential pitfalls.
Q4 Explain With Example Conditional Macro Expansion.
Conditional macro expansion refers to the capability of macros to expand differently based on
certain conditions. This feature allows you to selectively include or exclude code during preprocessing,
depending on whether specific conditions are met. Conditional macro expansion is commonly used
for conditional compilation, where different parts of the code are compiled based on compile-time
conditions or flags. There are two primary ways to achieve conditional macro expansion in C and
similar languages: using `#ifdef` and `#ifndef` directives, and using the ternary operator (`?:`) within
the macro definition.
Using `#ifdef` and `#ifndef` Directives:
The `#ifdef` (if defined) and `#ifndef` (if not defined) directives are used to check if a macro is
defined. They allow you to conditionally include or exclude code based on whether a specific
macro is defined. Example:
#ifdef DEBUG
#define DEBUG_PRINT(msg) printf("Debug: %s\n", msg)
#else
#define DEBUG_PRINT(msg) #endif
If the macro `DEBUG` is defined (`#define DEBUG`), the macro `DEBUG_PRINT` will expand to
`printf("Debug: %s\n", msg)`.
If `DEBUG` is not defined, the macro `DEBUG_PRINT` will expand to nothing.
Using Ternary Operator within the Macro Definition: Another approach to achieve conditional macro
expansion is by using the ternary operator (`?:`) within the macro definition. This technique allows
you to conditionally select between two expressions based on a condition.

Q1 Define Loader. Explain Different Functions Of Loaders.


A loader is a program or system utility responsible for loading and executing programs or
executable files into memory for execution. It is an essential component of an operating system,
particularly in systems that support dynamic loading and execution of programs. Loaders perform
several functions to ensure that programs are properly loaded into memory and executed
efficiently.
Functions of Loaders:
Allocation of Memory:
One of the primary functions of a loader is to allocate memory space for the program in the main
memory (RAM). It determines the starting address in memory where the program will be loaded
and ensures that sufficient contiguous memory is available for the program's code, data, and stack
segments.
Loading Program into Memory:
The loader reads the executable file from secondary storage (e.g., disk) and loads it into the allocated
memory space in the main memory. It copies the program's instructions, data, and other necessary
information from the executable file into the appropriate memory locations.
Relocation:
Many modern programming languages and operating systems support dynamic memory allocation
and loading. The loader performs relocation, which involves adjusting the program's internal
references (e.g., addresses of variables, function calls) to reflect the actual memory locations where
the program has been loaded.
Linking and Binding: Loaders may perform linking and binding tasks, especially in systems that
support dynamic linking. Dynamic linking allows multiple programs to share and reuse common
libraries or modules. The loader resolves references to external symbols (functions or variables) by
locating and binding them to their respective addresses in memory.
Q2 Explain Different Types Of Loaders.
Loaders are programs or system utilities responsible for loading executable files into memory for
execution. Depending on the loading mechanism and the features they support, loaders can be
classified into different types. Here are the main types of loaders:
Absolute Loader: An absolute loader is the simplest type of loader. It loads an executable program into
memory starting from a fixed memory location, regardless of the program's actual size or memory
requirements.
Relocating Loader: A relocating loader is more flexible than an absolute loader. It loads an executable
program into memory and performs relocation, adjusting memory addresses within the program to
match the actual memory location where the program is loaded.
Direct Linkage Loader: A direct linkage loader is a type of relocating loader that resolves and links
external symbols (functions or variables) at load time. It searches external symbol definitions in
separate object files or libraries and binds them directly to their respective memory addresses in the
loaded program. This enables modular programming and dynamic linking of libraries.
Dynamic Linking Loader: A dynamic linking loader loads executable programs into memory and
performs dynamic linking of external symbols at runtime, rather than at load time. It resolves
external symbol references by locating and binding them to their respective memory addresses
during program execution. Bootstrap Loader: A bootstrap loader is a special type of loader responsible
for bootstrapping or initializing the operating system during system startup. It is typically stored in
read-only memory (ROM) or firmware and is the first program executed by the computer when
powered on.

Q4 Explain Following Tables - POT, MOT, ST, BT, LT.


POT (Pseudo-operation Table): The POT (Pseudo-operation Table) is a table used by the assembler to
map pseudo-operations or assembler directives to their corresponding actions or behaviors during
the assembly process. Pseudo-operations are instructions that do not directly translate into machine
code but rather provide instructions or directives to the assembler itself. Examples include START, END,
ORG, EQU, etc.
MOT (Machine Operation Table): The MOT (Machine Operation Table) is a table used by the assembler
to map mnemonic instructions (e.g., ADD, SUB, JMP) to their corresponding machine language
opcodes. For each mnemonic instruction recognized by the assembler, the MOT contains entries
specifying the opcode or machine language representation of the instruction.
ST (Symbol Table): The ST (Symbol Table) is a data structure used by the assembler to manage
symbols encountered in the source code. Symbols include labels, variable names, constants, and
other identifiers defined by the programmer. For each symbol encountered during the assembly
process, the ST contains entries storing information such as the symbol name, its address or value,
and any additional attributes.
BT (Literal Table):
The BT (Literal Table) is a table used by the assembler to manage literals or constants defined in
the source code. Literals are fixed values (e.g., numerical constants, character strings) that are directly
used within the program. For each literal encountered in the source code, the BT contains entries
storing information such as the literal value, its address or storage location, and any associated
attributes.
LT (Location Counter Table):
The LT (Location Counter Table) is a table used by the assembler to keep track of the current location
or address within the generated machine code. It maintains the location counter, which represents
the memory address or offset where the next instruction or data item should be placed in memory.
During the assembly process, the LT is updated as instructions and data are processed, ensuring that
each item is assigned a unique and sequential address.
Q3 Explain Dynamic Linking Loader In Details.
Dynamic linking loader is a component of an operating system responsible for loading
executable programs into memory and performing dynamic linking of external symbols at
runtime. Unlike static linking, where external symbols are resolved and linked at compile
time, dynamic linking defers the linking process until the program is loaded into memory
and executed. Dynamic linking loaders provide several advantages, including reduced
memory usage, improved system flexibility, and easier software maintenance.
Benefits of Dynamic Linking:
Reduced memory usage: Multiple programs can share a single instance of a shared library in
memory.
Simplified maintenance: Updates or bug fixes to shared libraries are automatically
propagated to all programs that use them.
Faster program startup: Lazy loading and shared library caching mechanisms improve
program startup times by loading only the required libraries into memory.
Advantages of Dynamic Linking:
Reduced Memory Usage: Dynamic linking allows multiple programs to share and reuse common
libraries, reducing memory usage by avoiding redundant copies of code and data.
Improved System Flexibility: Dynamic linking enables shared libraries to be loaded and linked
on demand, providing flexibility in managing dependencies and updating libraries without
recompiling the entire program.
Easier Software Maintenance: With dynamic linking, updates or patches to shared libraries can be
applied without recompiling or relinking the entire program, simplifying software
maintenance and deployment.

Q4 Explain Direct Linking Loader.


A direct linking loader is a type of loader responsible for loading executable programs into
memory and performing the linking of external symbols (functions or variables) at load time.
Unlike dynamic linking loaders, which defer the linking process until runtime, direct linking
loaders resolve and link external symbols directly during the loading phase. Direct linking
loaders are commonly used in systems where dynamic linking is not supported or not
required, such as embedded systems or statically linked executables.
Advantages of Direct Linking Loader:
Simplicity: Direct linking loaders are relatively simple and efficient since they do not involve
additional relocation or dynamic linking steps.
Efficiency: Direct linking loaders generate executable programs with fixed memory addresses,
reducing runtime overhead and improving execution speed.
Predictability: Since the memory addresses of symbols are fixed and absolute, direct linking
loaders provide predictable program behavior and facilitate debugging and analysis.
Limitations of Direct Linking Loader:
Lack of Flexibility: Direct linking loaders do not support dynamic linking or relocation, limiting
the flexibility of programs to adapt to different memory configurations or runtime
environments.
Dependency Management: Programs linked with direct linking loaders may have larger executable
sizes and increased memory usage since they include all required code and data statically.
Q5 What Is Relocation And Linking Concept In Loaders.
Relocation: Relocation is the process of adjusting memory addresses or references within a program
to reflect the actual memory location where the program is loaded. It is necessary because the
memory location where a program is loaded into memory may vary depending on the execution
environment, system configuration, or other factors. During relocation, the loader identifies
memory references or addresses within the program that are expressed as offsets or relative
addresses. It then calculates the correct absolute memory addresses based on the starting address
where the program is loaded into memory. Relocation is particularly important in systems that
support dynamic loading and execution of programs, where the memory location of a program may
change each time it is loaded. By performing relocation, the loader ensures that the program's
instructions and data can be accessed correctly regardless of its memory location.
Linking: Linking is the process of combining multiple object files or modules into a single
executable program. It involves resolving references to external symbols (functions or variables)
and combining the code and data segments of individual modules into a unified program.
There are two main types of linking:
Static Linking: In static linking, the linking process occurs at compile time. External symbols are
resolved and linked by the linker to produce a single executable file that contains all necessary code
and data. Static linking results in a standalone executable that can be executed independently
without relying on external libraries or modules. Dynamic Linking: In dynamic linking, the linking
process is deferred until runtime. External symbols are resolved and linked dynamically by the loader
when the program is loaded into memory. Shared libraries or modules containing reusable code
and data are loaded and linked on demand, reducing memory usage and allowing multiple
programs to share common code.

Q2 Explain Forward Reference Problem And How It Is Handled In Assembler Design.


The forward reference problem occurs in the context of assembling source code when an
instruction or data declaration references a symbol (such as a label) that has not been defined yet in
the source code. In other words, the assembler encounters a reference to a symbol before it has seen its
definition. This poses a challenge because the assembler needs to resolve the symbol to its
corresponding address or value during the assembly process.
Forward Reference Problem Can Be Explained : Example:
Consider the following assembly code:
JMP Label
...
Label: NOP
Here, the ‘JMP’ instruction references a label ‘Label’, but ‘Label’ is defined later in the source code.
This creates a forward reference problem.
Handling Forward References:
To address the forward reference problem, assemblers typically employ one of the following
techniques: Two-Pass Assembler: One common solution is to use a two-pass assembler, where Pass I scans
the entire source code, building a symbol table and handling forward references by marking symbols as
undefined. In Pass II, the assembler revisits the source code, resolving the previously undefined
symbols using the symbol table generated in Pass I. During Pass I, when a forward reference is
encountered, the assembler assigns a placeholder value (such as 0 or an undefined marker) to the symbol.
Example Handling in Two-Pass Assembler: In the two-pass assembler approach, during Pass I:The
assembler encounters the JMP Label instruction and records Label as an undefined symbol in the
symbol table. It proceeds to the next lines of code, recording other symbols and their addresses. In
Pass II:The assembler revisits the instruction JMP Label and looks up Label in the symbol table. Since
Label is now defined, the assembler replaces it with the actual address of Label.
Q6 Explain Absolute Loader. State It's Advantage And Disadvantages.
An absolute loader is a type of loader used in systems programming to load and execute programs.
It is one of the simplest forms of loaders and is primarily used in systems where the memory
addresses of programs are fixed and predetermined. Let's delve into its explanation, advantages,
and disadvantages:
Explanation of Absolute Loader: The absolute loader loads the entire program into memory starting
from a fixed memory location, regardless of the program's size or memory requirements. It assumes
that the program will always be loaded into the same predetermined memory location, typically
specified by the programmer or system designer. In an absolute loader, the memory addresses used
by the program are fixed and absolute. Any references to memory locations within the program are
based on these predetermined addresses. Since the memory addresses are fixed, absolute loaders do
not perform relocation..
Advantages of Absolute Loader: Absolute loaders are simple and straightforward to implement.
They have minimal complexity compared to other types of loaders. The absence of relocation and
dynamic linking mechanisms simplifies the loading process.
Disadvantages of Absolute Loader: Absolute loaders lack flexibility, as they require programs to be
loaded into specific predetermined memory locations. This lack of flexibility limits the portability
of programs and makes it challenging to accommodate changes in memory configuration or system
setup. Absolute loaders may lead to memory fragmentation, especially in systems with limited
memory resources.

Q6 Enlist The Different Types Of Errors That Are Handled By Pass I and Pass II Of Assembler.
Errors handled by Pass I:
Pass I detects syntax errors such as invalid mnemonics, missing operands, or incorrect usage of
assembler directives. Example: ADD AX, BX, CX (Invalid syntax due to too many operands for the ADD
instruction). Pass I detects references to symbols (labels, variables, constants) that are not defined in the
source code. Example: MOV AX, VAR (Where VAR is not defined anywhere in the source code).
Pass I detects duplicate label definitions within the same scope. Example:
LABEL: ; First occurrence of LABEL
LABEL: ; Second occurrence of LABEL
Incorrect Usage of Assembler Directives:
Pass I verifies the correct usage of assembler directives and flags errors if they are used incorrectly.
Example: ORG A (Where A is not a valid memory address).
Pass I calculates addresses and updates the location counter. It may detect errors related to
incorrect address calculations. Example: Miscalculating the memory address while processing ORG
Errors handled by Pass II:
Pass II revisits the source code and attempts to resolve previously undefined symbols using the symbol
table generated in Pass I. Example: MOV AX, VAR Pass II handles errors related to the processing of
literals, such as undefined or incorrectly formatted literals. Example: Undefined literals referenced in
the source code. Pass II resolves symbolic addresses using the symbol table. It may detect errors related
to incorrect address resolution. Example: Inaccurate address resolution resulting in incorrect machine
code generation. Pass II handles errors related to unresolved external symbols, typically encountered in
programs using external libraries or modules. Example: References to symbols defined in external
modules without proper linkage.
Q3 Short Note On Syntax Directed Translation.
Syntax-directed translation is a technique used in compiler design to associate semantic actions
with the production rules of a grammar. It integrates syntax analysis and semantic processing by
embedding translation rules directly into the grammar definition. These translation rules specify
how to generate intermediate representations or perform computations while parsing the input.
Key Aspects of Syntax-Directed Translation:
Integration of Syntax and Semantics:Syntax-directed translation tightly couples syntax analysis with
semantic actions.
Translation Schemes:Translation schemes are extended context-free grammars (CFGs) augmented
with semantic actions. They define the translation process by associating actions with grammar
productions.
Attributes:Attributes are variables associated with non-terminal symbols in the grammar. They
represent properties or values computed during parsing and used in semantic actions.
Syntax-Directed Definition:A syntax-directed definition (SDD) specifies the translation process using a
set of translation rules associated with grammar productions.
Advantages of Syntax-Directed Translation:
Modularity: Syntax-directed translation promotes modularity by separating semantic actions from the
parsing logic. Each production rule encapsulates a specific translation rule, facilitating code
organization and maintenance.
Flexibility: Semantic actions in syntax-directed translation provide flexibility to perform various
transformations or computations during parsing. This enables the integration of optimization
techniques and the generation of intermediate representations.
Ease of Implementation: Syntax-directed translation simplifies the implementation of compilers by
integrating syntax analysis and semantic processing into a unified framework. It provides a clear and
structured approach to specifying translation rules.
Q5 Compare Between Compiler And Interpreter.
Compiler Interpreter
The compiler saves the Machine Language in The Interpreter does not save the Machine
form of Machine Code on disks. Language.
Compiled codes run faster than Interpreter. Interpreted codes run slower than Compiler.
Linking-Loading Model is the basic working The Interpretation Model is the basic working
model of the Compiler. model of the Interpreter.
The compiler generates an output in the form The interpreter does not generate any output.
of (.exe).
Any change in the source program after the Any change in the source program during the
compilation requires recompiling the entire translation does not require retranslation of the
code. entire code.
Errors are displayed in Compiler after Errors are displayed in every single line.
Compiling together at the current time.
It does not require source code for later It requires source code for later execution.
execution.
CPU utilization is more in the case of a CPU utilization is less in the case of a Interpreter.
Compiler.
Object code is permanently saved for future No object code is saved for future use.
use.
C, C++, C#, etc are programming languages Python, Ruby, Perl, SNOBOL, MATLAB, etc are
that are compiler-based. programming languages that are interpreter-
based.
Q1 What Are The Different Ways Of Representing Intermediate Code, Explain With Example.
Intermediate code serves as an intermediate representation (IR) of a program during the
compilation process. It is a platform-independent representation that facilitates optimization and
code generation. There are several ways of representing intermediate code, each with its own
advantages and use cases. Here are some common methods:
Three-Address Code (TAC):
Description: Three-address code represents each operation with at most three operands. It is a linear
representation of code with explicit instructions for each operation. Example:
t1 = a + b t2 = c * t1
Advantages:
Simple and easy to understand. Supports common optimization techniques.
Quadruples:
Description: Quadruples are similar to TAC but use a tuple-like representation with four fields:
operator, operand1, operand2, and result. Example:
('+', 'a', 'b', 't1')
('*', 'c', 't1', 't2')
Advantages:Compact representation.Enables easy manipulation during optimization.
Static Single Assignment (SSA) Form:
Description: SSA form assigns a unique version number to each variable assignment. It
ensures that each variable is assigned only once per scope. Example:t1 = a + b t2 = c * t1
Advantages:Facilitates certain optimization techniques like common subexpression
elimination and constant propagation. Simplifies data-flow analysis.
Abstract Syntax Tree (AST):
Description: AST represents the hierarchical structure of a program's syntax. Each node
in the tree corresponds to a syntactic construct, and the edges represent the
relationships between them.
Advantages: Preserves the hierarchical structure of the program. Supports semantic
analysis and code generation. Example:

Control Flow Graph (CFG):


Description: CFG represents the control flow of a program using nodes to
represent basic blocks and edges to represent control flow between them.
Advantages: Enables analysis and optimization of control flow structures.
Supports loop optimizations and dead code elimination.

Directed Acyclic Graph (DAG):


Description: DAG represents common subexpressions and their dependencies
using a directed acyclic graph structure. Example:
Q2 Explain Different Issues In Code Generation.
Code generation is a crucial phase in the compilation process where the intermediate
representation of a program is translated into machine code or another target language.
During code generation, various issues arise that need to be addressed to produce efficient
and correct executable code. Here are some of the key issues in code generation:
Register Allocation:Description: Register allocation involves assigning variables and intermediate
values to processor registers efficiently Issues: Limited number of registers: Modern processors
have a limited number of registers available for allocation, leading to register scarcity.
Register pressure: As the number of live variables exceeds the available registers, spill code may
be needed to spill variables to memory. Interference: Variables with overlapping lifetimes
cannot be assigned to the same register simultaneously, leading to interference.
Instruction Selection: Description: Instruction selection involves choosing the appropriate machine
instructions to implement high-level operations efficiently. Issues: Complexity of instruction set:
Target architectures may have complex instruction sets with multiple addressing modes and
operation variations, making instruction selection challenging. Performance considerations:
Different instructions may have different execution times or resource usage, requiring careful
selection to optimize performance.
Addressing Modes: Description: Addressing modes determine how operands are accessed in
machine instructions. Issues:Limited addressing modes: Some architectures may have limited
addressing modes, limiting the flexibility of addressing operations. Efficiency: Choosing the
most efficient addressing mode for each operand can impact performance.
Code Size Optimization: Description: Code size optimization aims to reduce the size of generated
code to improve memory usage and execution speed. Issues:Redundancy: Generated code may
contain redundant or unnecessary instructions, leading to larger code size. Instruction encoding:
The choice of instructions and their encoding can affect the size of generated code.
Control Flow Optimization: Description: Control flow optimization focuses on improving the
efficiency of control flow structures such as loops, conditionals, and function calls. Issues: Loop
optimization: Techniques like loop unrolling, loop fusion, and loop inversion can improve loop
performance but may increase code size. Branch prediction: Branches and conditional jumps
can impact pipeline efficiency, and optimizing branch predictions can improve performance.

Q4 Write Short Note On Peephole Optimization.


Peephole optimization is a local optimization technique used in compilers to improve the
efficiency and quality of generated code by analyzing and optimizing small sections of
assembly or machine code known as "peepholes." These peepholes typically consist of a
small number of contiguous instructions within a program's control flow.
Key Aspects of Peephole Optimization:
Local Optimization:
Peephole optimization operates on a small window or "peephole" of instructions, typically a few
consecutive instructions, rather than analyzing the entire program.
It focuses on identifying and eliminating redundant or inefficient code patterns within this
limited scope.
Pattern Matching:
Peephole optimization relies on pattern matching techniques to identify specific sequences of
instructions that can be replaced or optimized.
Common patterns targeted by peephole optimization include redundant load-store pairs,
unnecessary branches, and inefficient arithmetic operations.
Optimization Rules:
Peephole optimization applies a set of predefined optimization rules or patterns that describe
transformations that can be applied to the instruction sequence.
Q3 Explain Different Code Optimization Techniques.
Code optimization techniques aim to improve the performance, efficiency, and quality of generated
code without changing its functional behavior. These techniques target various aspects of the code,
such as reducing execution time, minimizing memory usage, and enhancing overall program
performance. Here are some common code optimization techniques:
Constant Folding: Evaluate constant expressions at compile-time rather than runtime to reduce
computation overhead.
Dead Code Elimination:Remove unreachable or redundant code that does not contribute to the
program's output, reducing code size and improving readability.
Common Subexpression Elimination (CSE):
Identify and eliminate redundant computations by reusing previously computed results, reducing
computational overhead.
Copy Propagation:Replace uses of a variable with its known value to minimize memory accesses and
improve code efficiency.
Loop Optimization:Improve the efficiency of loops by applying techniques such as loop unrolling, loop
fusion, loop interchange, and loop-invariant code motion.
Replace expensive operations with cheaper equivalents, such as replacing multiplication with shifts
or addition, to reduce computational overhead.
Inline Expansion: Replace function calls with the actual function code to reduce call overhead and
improve execution speed.
Code Motion:Move computations or memory accesses outside loops when possible to minimize
redundant work and improve loop efficiency.

Q6 Short Note On Operator Precedence Parsing.


expressions and construct parse trees according to the precedence and associativity of operators. It
is particularly useful for languages with operators of varying precedence levels, such as arithmetic
expressions in programming languages.
Key Aspects of Operator Precedence Parsing:
Precedence Levels: Operators in the language are assigned precedence levels, indicating their relative
priority in expression evaluation Higher precedence operators are evaluated before lower
precedence operators.
Associativity: Operators may also have associativity, which determines the order of evaluation when
operators of the same precedence level appear in an expression. Common associativities include left-
associative (evaluated left-to-right) and right-associative (evaluated right-to-left).
Operator Precedence Table: Operator precedence parsing uses an operator precedence table to define the
precedence and associativity of operators in the language. The table specifies which operators have
higher precedence than others and how they associate with neighboring operators.
Parsing Algorithm: Operator precedence parsing uses a stack-based parsing algorithm to parse
expressions efficiently. It scans the input expression from left to right, pushing operands onto the
stack and performing operations based on the precedence and associativity of operators. When
encountering an operator, it compares its precedence with the top of the stack. If the precedence of
the current operator is higher, it performs the operation. Otherwise, it continues parsing until a
lower-precedence operator is encountered.
Advantages of Operator Precedence Parsing:
Efficiency: Operator precedence parsing is efficient and requires only a single scan of the input
expression, making it suitable for real-time parsing applications.
Ease of Implementation: The parsing algorithm is relatively simple and straightforward to implement
compared to other parsing techniques. No Ambiguity: Operator precedence parsing resolves
ambiguities in expressions automatically based on the precedence and associativity rules defined in
the operator precedence table.
Q7 Explain The Concept Of Basic Blocks And Flow Graph With Example The Three Address Code.
Basic Blocks: A basic block is a sequence of consecutive instructions in a program's control flow
graph that has a single entry point and a single exit point. Within a basic block, control flows
linearly without any branching or looping. Basic blocks are useful for analyzing and optimizing
control flow structures in a program. Properties of Basic Blocks: Single Entry Point: Every basic block has
exactly one entry point, where control enters the block from a predecessor block or from the beginning
of the program. Single Exit Point: Every basic block has exactly one exit point, where control leaves the
block to a successor block or to the end of the program. No Branching or Looping: Control flows linearly
within a basic block without any branching or looping constructs.
Flow Graph: A flow graph, also known as a control flow graph (CFG), is a directed graph that represents
the control flow of a program. Each node in the flow graph represents a basic block, and edges between
nodes represent control flow between basic blocks. Flow graphs are used for analyzing and
optimizing control flow structures, such as loops, conditionals, and function calls. Properties of Flow
Graphs: Nodes: Nodes in the flow graph represent basic blocks, where each basic block corresponds to a
sequence of consecutive instructions. Edges: Directed edges between nodes represent control flow
between basic blocks. An edge from node A to node B indicates that control can flow from the end of
basic block A to the beginning of basic block B. Entry and Exit Nodes: Special entry and exit nodes may
be added to represent the entry and exit points of the program.
Example Using Three-Address Code:
1: t1 = a + b Basic Blocks:
2: t2 = c - d Basic Block 1: t1 = a + b
3: if t1 < t2 goto 6 Basic Block 2: t2 = c - d
4: t3 = t1 * t2 Basic Block 3: if t1 < t2 goto 6
5: goto 7 Basic Block 4: t3 = t1 * t2
Basic Block 5: goto 7
6: t3 = t2 * t2 Basic Block 6: t3 = t2 * t2
7: t4 = t3 / e Basic Block 7: t4 = t3 / e

Flow Graph:

1 2 3 4 5 6 7
| | | | | | |
V V V V V V V
+----+ +----+ +----+ +----+ +----+ +----+ +----
+

| BB1 | -->| BB2| -->| BB3 | -->| BB4 | -->| BB5 | -->| BB6 | -->| BB7 |

+----+ +----+ +----+ +----+ +----+ +----+ + +

You might also like