0% found this document useful (0 votes)
12 views18 pages

SPCC Viva

The document outlines the goals of system software, which include managing hardware and providing a platform for applications. It details various components of system software such as assemblers, linkers, loaders, and compilers, along with their functions and differences from application software. Additionally, it explains concepts related to macro processors, loaders, linkers, and the phases of compilation, including lexical and syntax analysis.

Uploaded by

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

SPCC Viva

The document outlines the goals of system software, which include managing hardware and providing a platform for applications. It details various components of system software such as assemblers, linkers, loaders, and compilers, along with their functions and differences from application software. Additionally, it explains concepts related to macro processors, loaders, linkers, and the phases of compilation, including lexical and syntax analysis.

Uploaded by

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

1. What are the goals of system software?

The main goal of system software is to manage the hardware and create a
platform for running application programs.
It handles memory, processes, and hardware devices so the user and
applications don’t have to.
It ensures the system operates efficiently, securely, and reliably.
Examples include operating systems, compilers, and device drivers.

2. What is an Assembler, Macro Processor, Linker, Loader, Compiler,


Interpreter?

• Assembler:
Converts assembly language (which is human-readable but low-level)
into machine code that the computer can understand and execute.
• Macro Processor:
Processes macros, which are shortcuts or reusable code blocks. It
expands these macros into full code before sending it to the assembler.
• Linker:
After code is compiled, different pieces of code (often from different
files or libraries) need to be connected together. The linker combines
them into a single executable file.
• Loader:
Once a program is ready to run, the loader loads it into memory,
allocates space, and prepares it for execution by the CPU.
• Compiler:
Translates the entire source code (like in C or Java) into machine code
before execution. If there are errors, it reports them all at once.
• Interpreter:
Translates and executes the program line by line. It stops as soon as it
encounters an error. Languages like Python often use interpreters.

3. System software vs Application software


Feature System Software Application Software
Manages computer hardware and
Purpose Performs specific user tasks
provides a platform
User Less direct; runs in the
Direct; user actively uses it
Interaction background
Required for running the Runs on top of system
Dependency
computer software
Operating systems (Windows, MS Word, web browsers,
Examples
Linux), compilers, loaders video games, Zoom

Explanation:
System software is essential for the functioning of a computer—it controls and
coordinates all parts of the system.
Application software helps users do specific tasks like writing documents,
browsing the internet, or editing photos.

1. Forward Reference Problem

A forward reference occurs when a symbol (such as a label or variable) is used


before it is defined later in the program.

In a single-pass assembler, the program is read only once, so it may not know
the address of the symbol when it is first encountered.
This creates a problem because the assembler cannot generate the correct
machine code without knowing the address.

To solve this, two-pass assemblers are used. In the first pass, they collect all
symbol definitions and their addresses. In the second pass, they resolve
forward references using this information.

2. Responsibilities of Pass 1 and Pass 2 in a Two-Pass Assembler

• Pass 1:
o Assigns memory locations to all instructions and data.
o Builds the Symbol Table (ST) with label names and their
corresponding addresses.
o Handles literals and creates the Literal Table (LT).
o Identifies and stores forward references without generating
machine code.
• Pass 2:
o Uses tables created in Pass 1 to generate machine code.
o Resolves forward references using the Symbol Table.
o Produces the final object code ready for execution or linking.

3. What is MOT, POT, LT, BT, ST?

Table Full Form Purpose


Machine Stores actual machine instructions and their binary
MOT
Opcode Table opcodes, sizes, and formats.
Stores assembler directives (like START, END, EQU)
Pseudo
POT which guide the assembler but are not translated into
Opcode Table
machine code.
Stores all constants written using the literal format (e.g.,
LT Literal Table
='5'), and allocates addresses for them.
Used in base-relative addressing to store base register
BT Base Table
values during code generation.
Maintains user-defined labels and symbols along with
ST Symbol Table their memory addresses, crucial for handling jumps and
variables.

4. Different Statements in Assembly Language

Assembly language statements are categorized into the following types:

1. Imperative Statements:
o These are actual instructions that tell the machine what to do
(e.g., move data, add, jump).
o They are converted into machine code.
o Example: MOV, ADD, JMP
2. Declarative Statements:
o Used to declare constants or reserve memory locations.
o These don’t generate machine code but affect memory layout.
o Example: DC (Define Constant), DS (Define Storage)
3. Assembler Directives (Pseudo-ops):
o Special instructions for the assembler, such as where to start the
program or define symbolic values.
o These are not converted into machine code but guide the
assembling process.
o Example: START, END, EQU, ORIGIN
4. Comment Statements:
o Notes for the programmer to improve readability.
o Ignored by the assembler and do not affect code execution.
o Example: Anything following ; or // depending on syntax.

1. What is a Macro & Macro Processor? Why is a Macro Processor needed?

• A macro is a single instruction that expands into a set of instructions. It


is used to avoid writing repetitive code.
• A macro processor handles macros — it expands macro definitions
wherever they are used in the program.

✅ Need for a macro processor:

• Increases code reusability and maintainability.


• Reduces manual effort and errors in repetitive coding.
• Saves time and space during development.

2. What is the difference between Macro Definition Table (MDT) and Macro
Name Table (MNT)?

Feature MDT (Macro Definition Table) MNT (Macro Name Table)


Stores body of the macro Stores macro names and starting
Purpose
(expanded code) index in MDT
Role Used during expansion Used during lookup
Example Instructions inside the macro Macro name, pointer to MDT

3. What is MDT, MNT, ALA in Macro Processor?


Table Full Form Purpose
Macro Definition
MDT Stores actual instructions inside macros.
Table
Stores macro names with pointers to their MDT
MNT Macro Name Table
location.
Argument List Maps formal parameters to actual arguments used
ALA
Array in macro calls.

Together, these help expand macros accurately by matching names and


replacing parameters.

4. Design of Two-Pass Macro Processor

Pass 1 (Macro Definition Phase):

• Detects macro definitions and stores them in MDT.


• Adds macro names to MNT.
• Constructs ALA for parameter mapping.
• Ignores macro calls for now.

Pass 2 (Macro Expansion Phase):

• Replaces macro calls with the actual instructions from MDT.


• Uses ALA to substitute parameters.
• Produces expanded source code with no macros.

5. Design of Single-Pass Macro Processor

• In a single pass, macro definitions and macro calls are processed


simultaneously.
• When a macro call is found:
o The macro body is fetched directly from MDT.
o Parameters are substituted using ALA.
o Expansion happens immediately during the scan.
• Suitable for simple macro handling but less flexible than two-pass
design.
6. Features of Macros

• Code Reusability: Write once, use many times.


• Parameterization: Use arguments for flexibility.
• Nested Macros: One macro can call another.
• Conditional Expansion: Expand only under certain conditions.
• Compactness: Reduces length of source code.

7. Parameterized Macros vs Conditional Macros

• Parameterized Macros:
Accept arguments (parameters) which are replaced during macro
expansion.
Example: A macro to add two numbers where numbers are passed as
parameters.
• Conditional Macros:
Use conditions (like IF-ELSE) inside the macro to control which code gets
expanded.
Useful for customizing behavior based on the input.

8. Difference between Macros and Functions

Criteria Macros Functions


Execution Expanded at compile-time Invoked at runtime
Speed Faster (no call overhead) Slower due to function call
Flexibility Simple text substitution Supports recursion, scope, etc.
Use Case Repetitive, small code blocks Complex logic or repeated use
Parameters Handled via ALA Handled via function call stack

Here are the detailed explanations for Chapter 4: Loader and Linker, with key concepts
clarified:
1. What is a Loader & Linker?

• Loader:
A loader is a system program that loads an executable file into memory
for execution. It prepares the program by loading machine code from
storage into memory and setting it up for execution.
• Linker:
A linker is a system program that combines object files into a single
executable file. It resolves references between object files, replacing
symbolic addresses with actual memory addresses.

2. Functions of Loader

A loader performs several key tasks:

1. Loading:
It loads the executable program from storage (disk) into the computer's
main memory.
2. Memory Allocation:
It allocates memory space for the program in the memory and assigns
addresses to variables and code.
3. Address Binding:
It assigns logical addresses to instructions and data, converting them
into physical addresses in memory.
4. Relocation:
The loader may adjust the addresses if the program is loaded into a
different memory location than originally planned.
5. Execution Start:
The loader finally passes control to the program’s entry point, allowing
execution to begin.

3. What is an Absolute Loader? Design of Absolute Loader

• Absolute Loader:
An absolute loader directly loads the machine code into the memory at
predefined addresses, as the program's memory locations are fixed.
There is no need for address translation or relocation.
• Design of Absolute Loader:
1. Input: Takes an object file with fixed addresses.
2. Loading Process: Reads the object file and places the code at the
specified memory addresses.
3. Starting Execution: Once loaded, the program is ready to execute
at the specified starting address.

4. What is Direct Linking Loader? Design of DLL

• Direct Linking Loader (DLL):


A direct linking loader loads and links object code files in one step,
allowing for dynamic linking at runtime. It combines object files and
adjusts addresses without needing separate linkers.
• Design of Direct Linking Loader:
1. Input: Receives a set of object files (with external references).
2. Linking: It resolves references between the object files (e.g.,
resolving function calls across files).
3. Relocation: The loader adjusts all addresses and assigns final
addresses.
4. Loading: Finally, the object code is loaded into memory, and
execution begins.

5. Types of Loader

There are several types of loaders, each suited for different environments and
needs:

1. Absolute Loader:
Loads programs at fixed memory addresses with no address
modification.
2. Relocating Loader:
Adjusts the memory locations at runtime, allowing the program to be
loaded at any address.
3. Dynamic Loader:
Loads and links programs while they are being executed. This allows on-
demand loading of modules or libraries.
4. Bootstrap Loader:
The first program loaded when a computer starts. It loads the operating
system into memory.
5. Incremental Loader:
Loads the program incrementally in multiple parts, allowing the program
to start execution even if not fully loaded.

1. Phases of Compiler, Explain Each Phase

A compiler translates high-level source code into machine code or


intermediate code. The process involves several phases:

1. Lexical Analysis (Scanner):


o Converts the raw source code into tokens (smallest meaningful
units like keywords, identifiers, and operators).
o Example: "int x = 10;" is broken into tokens: int, x, =, 10, ;.
2. Syntax Analysis (Parser):
o Analyzes the token sequence for syntax correctness based on the
grammar of the language.
o Constructs a parse tree that represents the syntactic structure of
the program.
3. Semantic Analysis:
o Ensures the program makes logical sense by checking variable
types, scope, and function calls.
o Example: Checks for mismatched types, undeclared variables, etc.
4. Intermediate Code Generation:
o Converts the syntax tree into an intermediate form, often a
simpler representation like three-address code or bytecode.
o This step is language-independent, making the code easier to
optimize.
5. Optimization:
o Refines the intermediate code to make it more efficient (e.g.,
reducing computation time, memory usage).
6. Code Generation:
o Converts the intermediate code into machine code or a low-level
language specific to the target machine.
7. Code Optimization (Final Optimization):
o Performs last-minute optimizations on the final code to improve
performance and efficiency.
8. Code Linking and Assembly:
o Combines the machine code with libraries or external functions
and prepares it for execution.

2. What is Lexical Analysis? What is Syntax Analysis?

• Lexical Analysis:
o Lexical analysis is the first phase of compilation where the source
code is split into tokens. It checks for valid characters and
identifies keywords, operators, identifiers, constants, and
punctuation marks.
o Example: The line int x = 10; is converted into tokens like int, x, =,
10, ;.
• Syntax Analysis:
o Syntax analysis (or parsing) takes the sequence of tokens
produced by the lexical analysis and builds a syntax tree or parse
tree based on the grammar rules of the programming language.
o It ensures that the program follows the correct syntax (structure)
of the language.

3. Types of Parsers:

• Top-Down Parsers:
o LL(1) Parser:
§ LL(1) stands for Left-to-right scan of the input and Leftmost
derivation using 1 token of lookahead. It is used for
predictive parsing.
§ It constructs a parse tree from the top to the bottom of the
grammar.
o Bottom-Up Parsers:
§ Shift-Reduce (SR) Parser:
§ Uses a stack to hold intermediate results and a set of
shift and reduce operations.
§ Shift means moving a symbol from the input to the
stack, and Reduce means applying a production rule
to reduce the stack's contents.
§ Operator Precedence Parser:
§ A type of bottom-up parser used for handling
operators and their precedence (e.g., * before +).
§ It uses precedence rules to decide when to shift or
reduce.
§ SLR Parser (Simple LR Parser):
§ A bottom-up parser that uses LR parsing with a
simpler lookahead mechanism.
§ It handles conflicts by using SLR parsing tables.
§ LR Parser (Left-to-right, Rightmost derivation):
§ A more powerful parser than SLR. It processes the
input left-to-right and generates the rightmost
derivation.
§ It has more detailed state transitions and is capable
of parsing a larger set of grammars.

4. What is First & Follow?

• First:
o The First set for a non-terminal is a set of terminals that begin the
strings derivable from that non-terminal.
o Example: For the non-terminal A → aB | b, First(A) is {a, b}
because both a and b can start strings derivable from A.
• Follow:
o The Follow set for a non-terminal is the set of terminals that can
appear immediately after that non-terminal in some derivation.
o Example: If A → Bc, then Follow(B) includes First(c) (which is {c}).

5. Top-Down Parser vs Bottom-Up Parser

Criteria Top-Down Parser Bottom-Up Parser


Builds the parse tree from root Builds the parse tree from
Approach
to leaves (top to bottom). leaves to root (bottom to top).
Parsing Predictive, often uses recursive Uses shift-reduce or reduce-
Technique descent. reduce methods.
Grammar
Works with LL grammars. Works with LR grammars.
Type
Criteria Top-Down Parser Bottom-Up Parser
Easier to implement but less More powerful and efficient
Efficiency
efficient for certain grammars. for complex grammars.
Typically uses a 1-token Uses more lookahead (e.g.,
Lookahead
lookahead (LL(1)). LR(1) or SLR).

6. What is Semantic Analysis?

• Semantic Analysis is the phase of the compiler that checks the program
for logical correctness after syntax analysis. It ensures that the program
is semantically valid and follows the rules of the programming
language’s logic.
o Example: Ensuring that:
§ A variable is declared before use.
§ Type checking is done (e.g., cannot add an integer to a
string).
§ Functions are called with the correct number and type of
arguments.

1. What is Intermediate Code Generation?

Intermediate code generation is a phase in the compilation process where a


compiler translates the high-level source code into an intermediate
representation (IR). This intermediate code is not machine-specific, allowing
the compiler to generate code for different target machines while maintaining
optimization flexibility. It acts as a bridge between the front-end (syntax
analysis) and back-end (code generation) of the compiler.

• Purpose:
o It helps in separating concerns, as optimization can be performed
on this intermediate form, making the process more modular and
platform-independent.
o It simplifies the task of generating machine code for multiple
target architectures.

2. What is Three Address Code (TAC)?


Three Address Code (TAC) is an intermediate code representation used by
compilers to represent program instructions in a simple and understandable
format. It is composed of a sequence of instructions, each having at most three
operands.

• Format:
A typical TAC instruction follows the form:
• x = y op z

Where x, y, and z are operands, and op is an operator (like +, -, *, etc.).


For example:

t1 = a + b
t2 = t1 * c

Each instruction represents a simple operation and helps in easy analysis


and optimization of the code.

3. What is a Directed Acyclic Graph (DAG)?

A Directed Acyclic Graph (DAG) is a graph with directed edges and no cycles. In
the context of compilers, a DAG is used to represent the flow of data and
operations in a program. Each node in the graph represents an operation or a
value, and the edges represent dependencies between them.

• Purpose:
o A DAG can represent expressions, helping to eliminate redundant
calculations by identifying common subexpressions.
o It allows for efficient code generation by simplifying the execution
order of operations.
• Example:
If an expression is a + b * c + a, a DAG will represent the addition and
multiplication operations, showing how values are reused and how
redundant computations are avoided.

4. What is Code Optimization?


Code optimization is the process of improving the intermediate or final code
generated by the compiler to make it run more efficiently. The goal is to
reduce execution time, memory usage, and other system resources while
maintaining the program's correctness.

• Types of Optimization:
o Machine-independent optimization: Applies to the intermediate
code and improves performance across platforms (e.g.,
eliminating redundant computations).
o Machine-dependent optimization: Targets specific features of the
target machine architecture (e.g., optimizing register usage).
• Benefits:
o Faster program execution.
o Reduced memory consumption.
o More efficient use of system resources.

5. Issues in Code Generation

Some common issues faced during the code generation phase of a compiler
are:

1. Register Allocation:
Deciding which variables should be stored in registers and which should
be in memory to minimize the time spent accessing memory.
2. Instruction Selection:
Mapping high-level operations (like addition or multiplication) to
machine-specific instructions efficiently.
3. Addressing Modes:
Choosing the most efficient addressing mode (like direct, indirect, or
indexed) to access memory locations.
4. Control Flow Representation:
Representing the program's control flow (loops, conditionals) in the
generated machine code while maintaining efficiency.
5. Handling Complex Expressions:
Dealing with complex expressions and choosing efficient ways to
evaluate them without redundancy.

6. Code Optimization Techniques


Several techniques can be used for optimizing the intermediate or final code:

1. Constant Folding:
Evaluate constant expressions at compile time instead of runtime. For
example, replace 3 + 4 with 7 during compilation.
2. Constant Propagation:
Propagate constant values throughout the code. If a variable is assigned
a constant value, replace its occurrences with that constant.
3. Loop Optimization:
Improve loops by techniques such as:
o Loop unrolling: Reducing the overhead of loop control.
o Loop invariant code motion: Moving calculations that don’t
change inside the loop to outside the loop.
4. Dead Code Elimination:
Remove code that does not affect the program’s output. For example, if
a variable is assigned a value but never used, it can be eliminated.
5. Strength Reduction:
Replace expensive operations with cheaper ones, such as replacing
multiplication with addition. For example, x * 2 can be replaced with x +
x.
6. Common Subexpression Elimination:
Identify and eliminate redundant expressions by storing intermediate
results. For instance, if an expression a + b is computed multiple times,
compute it once and reuse the result.
7. Inlining Functions:
Replace function calls with the actual code of the function when the
function is small and called frequently, reducing the overhead of
function calls.
8. Register Allocation Optimization:
Use registers efficiently by minimizing memory accesses, reducing
register spilling (storing values in memory when registers are full), and
reusing registers.
1. Explain LEX & YACC

LEX and YACC are tools commonly used for building language processors, like
compilers or interpreters.

• LEX:
o LEX is a tool for lexical analysis, which converts a stream of
characters into tokens. It is used to generate the lexer (also called
lexical analyzer), which breaks down the source code into
meaningful units (tokens like keywords, identifiers, numbers, etc.).
o How it works:
§ LEX uses regular expressions to define patterns for different
tokens. When given a source program, it matches the input
against these patterns and identifies the tokens accordingly.
• YACC:
o YACC (Yet Another Compiler Compiler) is used for syntax analysis,
which takes the tokens produced by LEX and arranges them in a
grammatical structure defined by a context-free grammar.
o How it works:
§ YACC creates a parser, typically using LR parsing, that
processes the token stream produced by LEX and checks if
the syntax follows the grammar rules. If the program is
syntactically correct, YACC constructs a parse tree;
otherwise, it reports syntax errors.

Workflow Example:

• Step 1: LEX breaks the input into tokens.


• Step 2: YACC takes those tokens and applies grammar rules to parse the
code.

In combination, LEX and YACC help in the process of converting source code
into executable machine code by performing lexical and syntax analysis.

2. What does the Precedence Table Contain?

A precedence table is used to define the precedence and associativity of


operators in a grammar, helping parsers determine how expressions are
grouped and evaluated. It is typically used by parsers like LR parsers and
operator-precedence parsers to handle the precedence of operators and avoid
ambiguity in expressions.

• Contents of a Precedence Table:


o Operator Precedence: The table defines the precedence of
different operators (e.g., multiplication has higher precedence
than addition).
o Associativity of Operators: The table also specifies whether an
operator is left-associative or right-associative, which defines how
operators of the same precedence are evaluated (e.g., left-to-right
for + and *).
o Conflict Resolution: In case of conflicting operator precedence
(e.g., for expressions like a - b - c), the table resolves how to
evaluate the expression based on predefined rules.
• Example:
o The precedence table might specify that * and / have higher
precedence than + and -, and both * and / are left-associative.

Use:
A parser uses the precedence table to determine the correct grouping of
operators and operands in an expression.

3. What is yylex?

yylex is a function generated by the LEX tool, which is responsible for


performing lexical analysis. It takes an input stream (the source code) and
breaks it into tokens. Each time yylex is called, it scans the input for a pattern
that matches one of the defined lexical rules (regular expressions) and returns
the corresponding token.

• Functionality:
o yylex is called by the parser (like one generated by YACC) to
retrieve the next token from the input stream.
o It returns an integer representing the token type (e.g., a keyword,
identifier, number, or operator).
o yylex may also set additional data, such as the value of the token
(e.g., the actual string for an identifier or number), which is
typically stored in a global variable or returned in a special
structure.
• Role in the Compiler:
o It plays a critical role in the compilation process by providing the
parser with the tokens it needs for syntax analysis.

Example:

• If yylex is called with the input int x = 10;, it would return tokens like
KEYWORD_INT, IDENTIFIER_X, OPERATOR_ASSIGN, and NUMBER_10,
and each token would correspond to a specific value that the parser will
later use to check the syntax.

You might also like