SPCC App: Understanding Org Code
SPCC App: Understanding Org Code
2. Explain with flow chart the design of two pass assembler (ls-2)
SPCC Page 1
SPCC Page 2
In Pass 1 of the assembly process, the assembler goes through the
source program to assign locations to instructions and data, as well
as define values for symbols (labels). Here's a breakdown of the
steps involved:
1. Initialize Location Counter (LC): Set LC to the first location in the
program (usually 0).
2. Read Source Statement: Read a source statement from the input.
3. Check Operation Code: Examine the operation code field to
determine if it's a machine instruction or a pseudo-operation (pseudo-
op).
4. Process Machine Instructions: If it's a machine instruction, search the
Machine Op-Codes Table (MOT) to find a match for the op-code field.
Determine the length of the instruction and update the LC accordingly.
If a literal is found in the operand field, add it to the Literal Table (LT).
If there's a symbol in the label field, save it in the Symbol Table (ST)
with the current value of LC.
5. Process Pseudo-Operations: For pseudo-ops like USING and DROP,
simply save the cards for pass 2. For EQU, evaluate the expression in
the operand field to define the symbol.
6. Handle OS and DC Pseudo-Ops: These pseudo-ops can affect both
the location counter and symbol definition. Examine the operand field
to determine storage requirements. Adjust the LC if necessary due to
alignment conditions.
7. Terminate Pass 1: When encountering the END pseudo-op, terminate
Pass 1. Perform housekeeping operations like assigning locations to
collected literals and reinitialize conditions for Pass 2.
Pass 1 primarily focuses on assigning locations, defining symbols,
and collecting information needed for Pass 2, such as literals and
pseudo-ops.
SPCC Page 3
Pass 2 of the assembly process finalizes the assembly by generating
code based on the symbols defined in Pass 1. Here's how it works:
Read Source Card: Read a card from the source file left by Pass 1.
_________________________________________________________
_________________________________________
ANS:-
Pass 1:
ADD AREG, B: Check MOT for ADD, increment LC by the size of ADD
instruction.
Pass 2:
Database Tables:
A: 501
B: 505
C: 509
Machine Op-Codes Table (MOT):
MOVER: Size
ADD: Size
MOVEM: Size
Literal Table (LT):
SPCC Page 6
ADD: Size
MOVEM: Size
Literal Table (LT):
_________________________________________________________
____________________
The MOT contains a list of all the machine instructions recognized by the
assembler along with their op-codes and formats.
Example:
ADD 01 3
SUB 02 3
MOVER 04 2
ST (Symbol Table):
The LT contains a list of all the literals (constants) used in the program
along with their addresses.
Example:
'HELLO' 201
1234 205
BT (Base Table):
_________________________________________________________
____________________
1. First Pass:
During the first pass of the assembler, the assembler performs the
following tasks:
• Symbol Table Initialization: The assembler initializes an empty symbol
table to store information about symbols encountered in the source
code.
• Scan Source Code: The assembler scans through the entire source
code line by line, analyzing each line to identify symbols, instructions,
and directives.
• Symbol Table Entry: When the assembler encounters a symbol (label
or variable), it creates an entry in the symbol table for that symbol.
The entry includes the symbol's name, its associated address (initially
set to zero or an arbitrary value), and any other relevant information.
• Forward References: If the assembler encounters a symbol that is
referenced before it is defined, it marks it as a forward reference. The
assembler continues processing, temporarily leaving the address
unresolved.
2. Second Pass:
After completing the first pass, the assembler revisits the source code in
a second pass to resolve forward references. During the second pass:
• Revisit Source Code: The assembler reprocesses each line of the
source code, including those with forward references.
• Resolve Forward References: When the assembler encounters a
forward reference, it looks up the symbol in the symbol table to find its
address, which should have been resolved during the first pass.
• Update Symbol Address: The assembler updates the address of the
symbol with its correct value obtained from the first pass.
• Generate Object Code: As the assembler processes each instruction,
it generates the corresponding machine code and stores it in memory
or generates an object file.
Error Handling:
• If a symbol is referenced but not defined anywhere in the source
code, it leads to an unresolved external symbol error.
• Assemblers typically detect such errors and report them to the user,
indicating the line number and context where the error occurred.
• Resolving unresolved external symbols might require modifications to
SPCC Page 8
code, it leads to an unresolved external symbol error.
• Assemblers typically detect such errors and report them to the user,
indicating the line number and context where the error occurred.
• Resolving unresolved external symbols might require modifications to
the source code to define the missing symbols or correct the
references.
Example:
Consider the following assembly code:
START 100
LOOP ADD A, B
SUB C, A
JMP LOOP
A DS 1
B DS 1
C DS 1
END
_________________________________________________________
____________________
SPCC Page 9
• USING: Establishes a base register for addressing.
USING *, 12 ; Set base register to register 12
_________________________________________________________
____________________
7. Enlist different types of error that are handle by pass 1 and pass
2 assemblers (LS-2)
ANS:-
In a two-pass assembler, both pass 1 and pass 2 handle different types
of errors during the assembly process. Here are the different types of
errors that are typically handled by each pass:
Errors Handled by Pass 1:
• Syntax Errors: Pass 1 checks for syntax errors in the assembly code,
such as missing commas, incorrect operand formats, or invalid
mnemonics.
• Undefined Symbols: Pass 1 identifies undefined symbols used in the
code by checking the symbol table. If a symbol is used before being
defined, it is flagged as an error.
• Forward Referencing: Pass 1 handles forward references by
allocating temporary addresses or placeholders for symbols that are
referenced before being defined. These addresses are later resolved
in pass 2.
• Invalid Instructions: Pass 1 verifies the validity of machine instructions
by checking against the opcode table. If an instruction is not
recognized or supported, it is reported as an error.
• Literal Pool Management: Pass 1 manages literal pools by identifying
literals in the code and assigning them temporary addresses. These
literals are later processed in pass 2.
• Base Register Management: If base-relative addressing is used, pass
1 manages the base register assignments and ensures that base-
relative instructions are properly handled.
Errors Handled by Pass 2:
• Address Calculation Errors: Pass 2 calculates the final addresses for
instructions and data, resolving any forward references encountered
SPCC Page 10
relative instructions are properly handled.
Errors Handled by Pass 2:
• Address Calculation Errors: Pass 2 calculates the final addresses for
instructions and data, resolving any forward references encountered
in pass 1. If there are errors in address calculation, such as overflow
or underflow, they are reported in pass 2.
• Symbol Resolution: Pass 2 resolves symbols to their final addresses
based on the symbol table generated in pass 1. If a symbol cannot be
resolved or conflicts with existing symbols, it is flagged as an error.
• Literal Pool Processing: Pass 2 processes literal pools generated in
pass 1 by assigning them final addresses and generating machine
code instructions or data for them.
• Base Register Resolution: Pass 2 resolves base-relative addressing
by substituting base register values and computing displacement
values for instructions referencing memory locations relative to a base
register.
• Output Code Generation: Pass 2 generates the final machine code
instructions or object code based on the resolved addresses and
assembled instructions. If there are errors in generating the output
code, they are reported in pass 2.
_________________________________________________________
____________________
ANS:-
SPCC Page 11
PASS 1- MACRO DEFINITION
In pass 1 of the assembler, the focus is on processing macro
definitions. Here's how it works:
• Identification of Macro Definitions: Pass 1 scans each input line to
identify if it contains a macro definition. This is typically done by
checking for the presence of a specific pseudo-opcode, such as
"MACRO."
• Saving Macro Definitions: When a macro definition is encountered,
the entire definition is saved in the Macro Definition Table (MDT). This
table stores all the lines of code that constitute the macro, including
any parameters and their replacements.
• Macro Name Table (MNT): The name of the macro is extracted from
the definition and stored in the Macro Name Table (MNT). This table
maintains a list of all defined macros along with pointers to their
corresponding entries in the MDT.
• Processing Macro Definitions: Pass 1 continues processing
subsequent lines of code until it reaches the END pseudo-op,
indicating the end of the source program or assembly file. During this
process, all macro definitions encountered are saved in the MDT and
their names are recorded in the MNT.
• Transfer to Pass 2: Once all macro definitions have been processed,
SPCC Page 12
indicating the end of the source program or assembly file. During this
process, all macro definitions encountered are saved in the MDT and
their names are recorded in the MNT.
• Transfer to Pass 2: Once all macro definitions have been processed,
control is transferred to pass 2 of the assembler. Pass 2 will handle
the processing of macro calls, where macros are invoked in the
source code.
SPCC Page 13
PASS 2-MACRO CALLS AND EXPANSION:
In pass 2 of the assembler, the focus is on processing macro calls and
expanding them. Here's how it works:
1. Identification of Macro Calls: Pass 2 examines the operation mnemonic
of each input line to determine if it matches a macro name stored in the
Macro Name Table (MNT). If a macro call is found, further processing is
initiated.
2. Setting the Macro Definition Table Pointer (MDTP): When a macro call is
detected, the call processor sets a pointer, known as the Macro
Definition Table Pointer (MDTP), to the corresponding macro definition
stored in the Macro Definition Table (MDT). The initial value of the
MDTP is obtained from the "MDT index" field of the MNT entry.
3. Preparing the Argument List Array (ALA): The macro expander prepares
the Argument List Array (ALA), which consists of a table of dummy
argument indices and corresponding arguments to the macro call. Each
argument is matched to its corresponding dummy argument in the macro
definition.
4. Substituting Arguments in Macro Definition: As the macro definition is
read from the MDT, the values from the argument list are substituted for
the dummy argument indices in the macro definition. This process
continues until the MEND line in the MDT is encountered, indicating the
end of the macro definition.
5. Handling Argument References: Arguments can be referenced either by
position or by name. For positional references, the substitution process
is straightforward. For references by name, the macro processor locates
the dummy argument on the macro name line to determine the proper
index.
6. Expansion of Macro Calls: The expansion of the macro call involves
substituting the arguments into the macro definition and generating the
corresponding lines of code. This expanded code becomes part of the
source deck and is further processed by the assembler.
7. Completion of Expansion: Once all macro calls have been expanded and
the END pseudo-op is encountered, the expanded source deck is
transferred to the assembler for further processing. This includes
handling any remaining instructions or data in the source program.
SPCC Page 14
_________________________________________________________
____________________
• Scope: Macros have their own scope, and their definitions are valid
within the scope where they are defined.
Example:
MACRO EXAMPLE_MACRO
; Macro definition
MEND
; Code outside the macro definition
_________________________________________________________
_________________________
After the comparison, if VALUE1 is greater than VALUE2, the values are
swapped. Otherwise, no swapping occurs.
(defmacro hello-world ()
`(format t "Hello, World!"))
(macroexpand '(hello-world))
; Output: (format t "Hello, World!")
In this example, the hello-world macro is defined to expand to the
form (format t "Hello, World!"). When the macroexpand function is called
with the form (hello-world), it returns the expansion of the form, which
is (format t "Hello, World!").
In summary, Macros are a way to repeat frequently-used lines of code,
and macro expansion is the process of substituting a macro call with the
appropriate macro definition.
12. What is loader and explain the function of loader with an example
(ls-4)
ANS:-
A loader is a program that loads an executable program from disk into
memory for execution. Its primary function is to place the program into
memory in such a way that it can be executed by the CPU. The loader
performs several tasks to accomplish this, including allocating memory,
relocating the program, resolving external references, and setting up the
program's execution environment.
_________________________________________________________
____________________
Explanation of Flowchart:
• Start:
The process begins.
• Read object program into memory:
The object program is read into memory.
• Initialize memory pointer:
A memory pointer is initialized to point to the specified memory
address where the program is to be loaded.
• Repeat until end of object program:
This loop continues until the end of the object program is reached.
• Read one block of the object program:
Each block of the object program is read.
• Copy block into memory at memory pointer:
The block of the object program is copied into memory at the
SPCC Page 20
• Read one block of the object program:
Each block of the object program is read.
• Copy block into memory at memory pointer:
The block of the object program is copied into memory at the
memory pointer.
• Increment memory pointer:
The memory pointer is incremented to point to the next memory
location.
• End loop:
The loop continues until the entire object program is loaded into
memory.
• Perform error checking:
After loading the object program, error checking is performed.
• If errors found, display error message and abort:
If errors are found during error checking, an error message is
displayed, and the loading process is aborted.
• Else, display success message:
If no errors are found, a success message is displayed.
• End:
The process ends.
_________________________________________________________
____________________
14. Explain the working of Direct Linking Loader with an example and
also show entry in different built by DLL (ls-4)
ANS:-
• A Direct Linking Loader is a type of loader used in computer systems to
load a program into memory for execution. Unlike other loaders, such as
the relocatable loader or the linkage editor, the direct linking loader
performs both linking and loading in a single step. Here's how a Direct
Linking Loader works, along with an example and an illustration of the
entry in different built by DLL:
• Working of Direct Linking Loader:
• Input:
The input to the Direct Linking Loader is an object program in relocatable
format. This object program contains machine instructions and data with
relative addresses.
• Memory Allocation:
The Direct Linking Loader loads the object program into memory,
starting at a specified base address.
• Linking and Loading Process:
During the loading process, the loader adjusts the addresses in the
object program to reflect the actual memory locations where the program
will be loaded.
It performs this adjustment by adding the base address to the relative
addresses in the program code.
• Error Handling:
The Direct Linking Loader performs error checking to ensure that the
object program is loaded correctly into memory.
It checks for errors such as memory overflow, invalid format, or any
other inconsistencies in the object program.
Example:
Suppose we have an object program with the following instructions:
SPCC Page 21
other inconsistencies in the object program.
Example:
Suppose we have an object program with the following instructions:
Address Instruction
----------------------
100 ADD 200
101 SUB 300
102 JMP 400
And suppose we want to load this program into memory starting at
address 500. The Direct Linking Loader would perform the following
steps:
1. Adjust Addresses:
Since the program is relocatable, the loader adjusts the addresses in
the program code to reflect the actual memory locations where the
program will be loaded.
The addresses are adjusted by adding the base address (500) to the
relative addresses in the program code.
_______________________________________________________
______________________
Example:
Consider a program that uses functions from a shared library [Link].
Instead of including the entire [Link] library in the executable file, the
program only contains references to the functions it needs. At runtime,
the dynamic linker loads [Link] into memory, resolves the
references, and updates the program's symbol table, allowing the
program to call the functions from [Link] as needed.
_________________________________________________________
____________________
Dynamic Linking:
1. Linking Process:
Dynamic linking is a technique in which the linking of libraries to an
executable program is deferred until runtime.
2. Deferred Linking:
Libraries are linked to the program at runtime rather than at compile
time.
3. Memory Usage:
Reduces memory usage as libraries are shared among multiple
programs.
4. Program Startup:
Slightly slower program startup compared to dynamic loading
because of the linking process at runtime.
5. Example:
A text editor application may use a shared library for spell checking.
Instead of statically linking the spell checking library at compile time,
the text editor is dynamically linked to the spell checking library at
runtime.
6. Runtime Overhead:
There is a slight overhead associated with dynamic linking because
the linking process occurs at runtime.
7. Dependency Management:
Introduces dependencies between the executable program and the
shared libraries it uses.
8. Simplified Updates:
Updates to shared libraries automatically apply to all programs that
use them.
9. Flexibility:
Provides flexibility in terms of memory usage and library updates.
10. Example Scenario: - Consider a Linux system where multiple
applications use the same C standard library (libc). Instead of each
application having its own copy of libc, the system dynamically links
each application to the shared libc library, reducing memory usage and
simplifying updates.
_________________________________________________________
____________________
Linking:
Definition: Linking is the process of combining multiple object files and
libraries into a single executable file.
Purpose: The purpose of linking is to resolve symbolic references
between different object files and libraries and create a single executable
file that can be loaded into memory and executed.
Process: During linking, the linker combines the object files and libraries,
resolves symbolic references, performs relocation, and generates an
executable file.
Example: Suppose a program consists of multiple source files main.c,
util.c, and math.c. After compiling these source files into object files
(main.o, util.o, math.o), the linker combines them, resolves the
references between them, performs relocation, and generates a single
executable file ([Link]).
_________________________________________________________
____________________
• Functionality:
Absolute loaders load an executable file into memory at a specific
location and execute it.
• Process:
SPCC Page 26
• Functionality:
Absolute loaders load an executable file into memory at a specific
location and execute it.
• Process:
Reads the absolute machine code and loads it into memory at a
predetermined memory location specified in the program.
• Relocation:
No relocation is performed as the program is loaded at a fixed
memory location.
• Advantages:
Simple and fast loading process.
• Disadvantages:
Lack of flexibility as the program is always loaded at the same
memory location.
• Example:
Older systems that used absolute loading methods.
2. Relocating Loader:
• Functionality:
Relocating loaders load an executable file into memory and perform
relocation, adjusting the addresses of the program's symbols based
on the load location.
• Process:
Scans the object file, identifies the memory addresses that need to be
adjusted, and calculates the correct addresses based on the
program's load location.
• Types of Relocation:
Static Relocation: Relocation is performed at compile time.
Dynamic Relocation: Relocation is performed at runtime.
• Advantages:
Provides flexibility as the program can be loaded at different memory
locations.
• Disadvantages:
Requires additional processing to perform relocation.
• Example:
Modern operating systems use relocating loaders to load and execute
programs.
3. Compile and Go Loader:
• Functionality:
Compile and Go loaders compile the source code into machine code
and then load and execute it.
• Process:
Reads the source code, compiles it into machine code, loads the
machine code into memory, and executes it.
• Advantages:
Simplifies the loading process by combining compilation and loading
into a single step.
• Disadvantages:
SPCC Page 27
Simplifies the loading process by combining compilation and loading
into a single step.
• Disadvantages:
Requires the entire program to be compiled before execution.
• Example:
Early systems where programs were compiled and executed
immediately.
4. Direct Linking Loader:
• Functionality:
Direct linking loaders link the object program with library routines by
placing library code directly into the object code.
• Process:
Combines the object program with library routines before loading it
into memory.
• Advantages:
Faster execution as library routines are directly integrated into the
object code.
• Disadvantages:
Increased memory usage as library routines are duplicated in each
object program.
• Example:
Early systems where library routines were linked directly into the
object code.
5. Dynamic Linking:
• Functionality:
Dynamic linking loaders load and link shared libraries or modules into
memory during runtime.
• Process:
Dynamically loads shared libraries or modules into memory when they
are needed during program execution.
• Advantages:
Saves memory by loading only the necessary modules.
Allows for the use of shared libraries, reducing disk space and
memory usage.
• Disadvantages:
Slight overhead associated with dynamic linking.
• Example:
Dynamic loading of libraries in modern operating systems and
applications.
6. Dynamic Loading:
• Functionality:
Dynamic loading loaders load executable modules into memory and
link them dynamically during runtime.
• Process:
Dynamically loads shared libraries or modules into memory when they
are needed during program execution.
• Advantages:
Saves memory by loading only the necessary modules.
• Disadvantages:
Requires additional code to handle the loading and unloading of
modules.
• Example:
Dynamic loading of modules in modern operating systems and
applications.
_________________________________________________________
SPCC Page 28
• Example:
Dynamic loading of modules in modern operating systems and
applications.
_________________________________________________________
____________________
SPCC Page 30
20. Compare Bottom up and top down parser (LS 5)
ANS:
_________________________________________________________
____________________
Example :
E -> E+T | T
T -> T*F | F
F -> INTLIT
_________________________________________________________
____________________
_________________________________________________________
____________________
Compiler:
A compiler is a program that translates source code written in a high-
level programming language into machine code.
The compiled machine code is then stored in an object file, which can be
linked with other object files to create an executable file. The executable
file can be run directly on the computer.
Interpreter:
An interpreter, on the other hand, is a program that translates source
SPCC Page 33
Interpreter:
An interpreter, on the other hand, is a program that translates source
code written in a high-level programming language into machine code
line by line, as it is executed. The interpreter does not generate machine
code ahead of time; instead, it translates the source code into machine
code as it is executed. This means that the interpreter does not require a
compilation step, and the source code is executed directly.
Key differences:
• Compilation vs. Interpretation: Compilers translate the entire source
code into machine code ahead of time, while interpreters translate the
source code line by line as it is executed.
• Code generation: Compilers generate machine code, while interpreters
do not generate machine code; instead, they translate the source code
into machine code as it is executed.
• Code optimization: Compilers can optimize the generated machine code
to improve performance, while interpreters do not have the opportunity to
optimize the code.
• Error handling: Compilers can detect and report errors at compile-time,
while interpreters detect and report errors at runtime.
• Execution speed: Compiled code is generally faster than interpreted
code, as the machine code has already been generated and optimized.
Interpreted code, on the other hand, is slower, as the interpreter
translates the source code into machine code line by line.
_________________________________________________________
____________________
- Algorithm:
- The algorithm scans the input expression from left to right,
maintaining two stacks: one for operands and one for operators.
- It compares the precedence of the current operator with the
precedence of the operator on the top of the operator stack.
- If the precedence of the current operator is higher, it pushes the
operator onto the operator stack.
- If the precedence of the current operator is lower or equal, it performs
the necessary operations using the top elements of the operand stack
until the precedence is satisfied, and then pushes the current operator
onto the operator stack.
- Example:
```plaintext
Expression: 2 + 3 * 4
SPCC Page 34
- Example:
```plaintext
Expression: 2 + 3 * 4
Stack: [2] []
Stack: [2] [+]
Stack: [2, 3] [+]
Stack: [2, 3] [+, *]
Stack: [2, 3, 4] [+, *]
```
- Advantages:
- Simple and efficient parsing technique for expressions.
- Requires minimal memory and processing power.
- Disadvantages:
- Limited to expressions with unary and binary operators.
- May require additional rules to handle associativity.
_________________________________________________________
____________________
Three-Address Code:
• A three address statement involves a maximum of three references,
consisting of two for operands and one for the result.
• A sequence of three address statements collectively forms a three
address code.
• The typical form of a three address statement is expressed as x = y op z,
where x, y, and z represent memory addresses.
• Each variable (x, y, z) in a three address statement is associated with a
specific memory location.
• While a standard three address statement includes three references,
there are instances where a statement may contain fewer than three
references, yet it is still categorized as a three address statement.
Example: The three address code for the expression a + b * c + d : T1 =
b * c T2 = a + T1 T3 = T2 + d; T 1 , T2 , T3 are temporary variables.
There are 3 ways to represent a Three-Address Code in compiler
design:
i) Quadruples
ii) Triples
SPCC Page 36
There are 3 ways to represent a Three-Address Code in compiler
design:
i) Quadruples
ii) Triples
iii) Indirect Triples
Syntax Tree:
• A syntax tree serves as a condensed representation of a parse tree.
• The operator and keyword nodes present in the parse tree undergo a
relocation process to become part of their respective parent nodes in the
syntax tree. the internal nodes are operators and child nodes are
operands.
• Creating a syntax tree involves strategically placing parentheses within
the expression. This technique contributes to a more intuitive
representation, making it easier to discern the sequence in which
operands should be processed.
• The syntax tree not only condenses the parse tree but also offers an
improved visual representation of the program’s syntactic structure,
Example: x = (a + b * c) / (a – b * c)
• _________________________________________________________
____________________
2. Target program:
The target program is the output of the code generator. The output can
be:
a) Assembly language: It allows subprogram to be separately compiled.
b) Relocatable machine language: It makes the process of code
generation easier.
c) Absolute machine language: It can be placed in a fixed location in
memory and can be executed immediately.
3. Memory management
• During code generation process the symbol table entries have to be
mapped to actual p addresses and levels have to be mapped to
instruction address.
• Mapping name in the source program to address of data is co-
operating done by the front end and code generator.
• Local variables are stack allocation in the activation record while
global variables are in static area.
4. Instruction selection:
• Nature of instruction set of the target machine should be complete
and uniform.
• When you consider the efficiency of target machine then the
instruction speed and machine idioms are important factors.
• The quality of the generated code can be determined by its speed and
size.
5. Register allocation
• Register can be accessed faster than memory. The instructions
involving operands in register are shorter and faster than those
involving in memory operand.
• The following sub problems arise when we use registers:
• Register allocation: In register allocation, we select the set of
variables that will reside in register.
• Register assignment: In Register assignment, we pick the register that
contains variable.
• Certain machine requires even-odd pairs of registers for some
operands and result.
6. Evaluation order
• The efficiency of the target code can be affected by the order in which
the computations are performed. Some computation orders need
fewer registers to hold results of intermediate than others.
_________________________________________________________
____________________
_________________________________________________________
____________________
Advantages:
Simple and easy to implement.
Can result in significant improvements in code size and execution speed.
Complements other optimization techniques and can be applied
repeatedly in different phases of the compiler.
Disadvantages:
Limited to local optimizations and may not capture global optimization
opportunities.
Requires careful tuning of the peephole size and optimization rules to
avoid excessive compilation time.
_________________________________________________________
____________________
2. Constant Folding :
Constant Folding is a technique where the expression which is
computed at compile time is replaced by its value. Generally, such
expressions are evaluated at runtime, but if we replace them with their
values they need not be evaluated at runtime, saving time.
4. Copy Propagation :
Copy Propagation suggests to use one variable instead of other, in
cases where assignments of the form x=y are used. These assignments
are copy statements. We can efficiently use y at all required place
instead of assign it to x. In short, elimination of copies in the code is
Copy Propagation.
Loop Optimizations :
The program spends most of its time inside the loops. Thus the loops
determine the time complexity of the program. So, in order to get an
optimal and efficient code, loop optimization is required. In order to apply
loop optimization, we first need to detect the loop using control flow
analysis with the help of program flow graph. A cycle in a program flow
graph will indicate presence of a loop. Note that, the code from
Intermediate code Generation phase which is in three-address format is
given as input to the optimization phase. It is difficult to identify loops in
such a format, thus a program flow graph is required.
The program flow graph consists of basic blocks, which is nothing but
the code divided into parts or blocks and show the execution flow of the
code,
1. Frequency Reduction :
It applies to the concept that a loop runs for least possible lines of code.
It can be achieved by following methods:
a. Code Motion :
Many times, in a loop, statements that remain unchanged for every
iteration are included in the loop. Such statements are loop invariants
and only result in the program spending more time inside the loop. Code
motion simply moves loop invariant code outside the loop, reducing the
time spent inside the loop.
b. Loop Unrolling :
If a loop runs doing the same operation for every iteration, we can
perform that same operation inside the loop more than once. This is
called loop unrolling. Such unrolled loop will perform the evaluation more
than once in a single loop iteration.
c. Loop Jamming :
Combining the loops that carry out the same operations is called as loop
jamming.
Thus, instead of executing same loops twice, that operation can be done
by executing the loop only once.
3. Strength Reduction :
It suggests replacing a costly operation like multiplication with a cheaper
one.
Example:
a*4
after reduction
a<<2
It is an important optimization for programs where array accesses occur
within loops and should be used with integer operands only.
4. Redundancy Elimination :
It may happen, that a specific expression is repeated in a code many
times. This expression is redundant to code because we may evaluate it
once and substitute its next occurrence with its evaluated value. This
substitution is nothing but redundancy elimination. Redundancy
elimination avoids evaluating the same expressions multiple times
resulting in faster execution.
SPCC Page 43
substitution is nothing but redundancy elimination. Redundancy
elimination avoids evaluating the same expressions multiple times
resulting in faster execution.
_________________________________________________________
____________________
32. Explain the concept of basic blocks and flow graph with example
the three address code (LS 6)
Three-Address Code:
1. t1 = a + b
2. t2 = c * d
3. t3 = t1 - t2
4. t4 = t1 * t3
5. e = t4 + t3
6. f = e - t1
Basic Blocks:
A basic block is a sequence of consecutive statements with the following
properties:
• Flow of control enters at the beginning.
• Flow of control leaves at the end.
• No branch or jump except at the end.
Basic Block 1:
t1 = a + b
t2 = c * d
In this block, control enters at statement 1 and leaves at statement 2.
There are no branches or jumps within this block.
Basic Block 2:
t3 = t1 - t2
t4 = t1 * t3
Control enters at statement 3 and leaves at statement 4. There are no
branches or jumps within this block.
Basic Block 3:
e = t4 + t3
Control enters at statement 5 and leaves at statement 5. There is only
one statement in this block.
Basic Block 4:
f = e - t1
Control enters at statement 6 and leaves at statement 6. There is only
one statement in this block.
Flow Graph:
SPCC Page 44
one statement in this block.
Flow Graph:
A flow graph is a graphical representation of a program's control flow.
Each basic block is represented as a node in the graph, and directed
edges represent the flow of control between the basic blocks.
+-------+
| Block 1|
+---+---+
|
v
+---+---+
| Block 2|
+---+---+
|
v
+---+---+
| Block 3|
+---+---+
|
v
+---+---+
| Block 4|
+-------+
SPCC Page 45
SPCC Page 46
Macro attributes like parameter substitution, nesting, and scope greatly enhance their applicability in complex assembly projects. Parameter substitution allows dynamic input variations, tailoring macro behavior based on context. Nesting enables hierarchical abstraction, promoting cleaner, modular designs through organized, encapsulated operations. The scope controls accessibility and lifetime within code regions, preventing conflicts and maintaining clarity. Together, these attributes allow for adaptable, maintainable, and scalable macro applications in intricate assembly tasks, enabling efficient handling of repetitive, parameter-driven, and complex logic sequences .
Dynamic linking incorporates shared libraries into a program during runtime rather than at compile time. This offers several benefits, such as reduced memory usage since libraries are shared among programs, simplified updates due to shared library modifications affecting all dependent programs, and increased flexibility. However, it introduces runtime overhead and dependency management challenges because programs rely on the availability of shared libraries. Static linking, while faster in execution due to direct library integration, increases memory consumption and lacks the flexibility dynamic linking provides .
The second pass of a two-pass macro processor focuses on expanding macro calls. It checks each operation mnemonic against the Macro Name Table (MNT) to identify macro calls. Upon identification, the Macro Definition Table Pointer (MDTP) is set according to the macro's entry in the MNT. An Argument List Array (ALA) is then created to map dummy arguments to actual parameters. As the macro definition is read from the MDT, arguments are substituted, and the expanded code is integrated into the source deck. This expansion completes once all macro calls are processed and the "END" pseudo-op is encountered, allowing the assembler to handle any remaining program instructions .
Absolute loaders place programs at a predefined memory location without performing address relocation, leading to a straightforward and fast loading process. However, they lack flexibility, are inefficient in memory use, and are not suitable for large programs due to fixed addressing. In contrast, relocating loaders adjust program addresses based on the load location, allowing for flexibility in memory allocation. They enable loading at various memory locations but require additional processing to handle address adjustments, which can complicate loading in some environments .
Macros are especially beneficial in assembly language for tasks requiring code reuse and efficiency, such as repeated operations in hardware manipulation and performance-critical segments. Their features, including parameterization, conditional assembly, reusability, expansion, and scope, allow programmers to create adaptable, efficient code blocks. Macros can simplify complex sequences and enable modification through conditional expansions, significantly enhancing their utility in repetitive and varied assembly tasks .
Conditional assembly directives enable macros to produce varied code based on specific conditions. Using directives like IF, ELSE, and ENDIF within a macro allows for generating different sequences of code depending on conditional expressions. For example, in the COMPARE_AND_SWAP macro, a parameter specifies whether a comparison should be signed or unsigned. The macro expands differently based on the SIGNED parameter, using CMP for signed and CMPU for unsigned comparisons. This flexibility enhances the macro's functionality and reuse by adapting to different contexts .
In the first pass of a two-pass macro processor, the process begins with the identification of macro definitions by scanning each input line for a specific pseudo-opcode, like "MACRO". When a macro definition is encountered, it is saved in the Macro Definition Table (MDT), which stores all lines of code constituting the macro. Concurrently, the macro's name is extracted and stored in the Macro Name Table (MNT) along with pointers to its MDT entries. The process continues by processing subsequent lines of code until an "END" pseudo-op marks the conclusion of the source program or assembly file, at which point all encountered macro definitions are documented. This pass focuses solely on defining macros and not on their expansion .
Relocation in loaders adjusts symbolic references within a compiled program to actual memory addresses, ensuring correct execution irrespective of the loading position in memory. Upon loading, the loader scans the object file, identifies addresses needing adjustment, and computes the correct addresses based on the program's load location. This step is crucial for resolving discrepancies between compile-time and load-time addresses, allowing programs to run correctly from any memory location, thereby enabling memory efficiency and flexibility .
A compiler transforms high-level source code into machine code through several phases: Lexical Analysis tokenizes source code into symbols and identifiers; Syntax Analysis checks the token sequence against grammatical rules; Semantic Analysis verifies program meaning against language rules and specifications; Intermediate Code Generation transforms syntax representations into intermediate code; Code Optimization refines the intermediate code for efficiency; and Code Generation translates it into machine code. These phases collectively ensure syntactic correctness, semantic integrity, and optimized execution of the compiled program .
The Macro Name Table (MNT) in a two-pass macro processor holds macro names and entry pointers to their respective definitions in the Macro Definition Table (MDT). During pass 1, macro names are identified and logged in the MNT as their definitions are recorded in the MDT. In pass 2, the processor uses the MNT to locate and expand macro calls by directing to relevant MDT entries, ensuring proper integration between name identification and definition storage for accurate macro expansion .