0% found this document useful (0 votes)
32 views

Unit 7

Uploaded by

moemakhlouf6
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)
32 views

Unit 7

Uploaded by

moemakhlouf6
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/ 6

CS 1105-01 - AY2025-T1

Assignment Activity Unit 7

Assignment: High-Level Data Structure in Assembly Language

1. Assembly Language Program to Build a Stack for Checking Balanced Parentheses


In this assignment, we implement a stack to check whether parentheses in a given
string are balanced. A stack is a useful data structure for this purpose due to its Last-In-
First-Out (LIFO) nature, which helps track opening and closing parentheses in pairs.
Here's a simplified version of an assembly language program (written for x86
architecture using MASM syntax):
section .data
string db '(()())', 0 ; String with parentheses to check
msg_balanced db 'Balanced parentheses', 0
msg_unbalanced db 'Unbalanced parentheses', 0

section .bss
stack resb 100 ; Stack for storing opening parentheses
top resb 1 ; Top pointer for the stack

section .text
global _start

_start:
mov esi, string ; Point ESI to the string
mov byte [top], 0 ; Initialize the top of the stack to 0

check_parentheses:
mov al, [esi] ; Load the current character
cmp al, 0 ; Check if it's the end of the string
je check_end ; If end, jump to check_end

cmp al, '(' ; Check if it's an opening parenthesis


je push_stack ; Jump to push_stack if true

cmp al, ')' ; Check if it's a closing parenthesis


je pop_stack ; Jump to pop_stack if true

jmp next_char ; Continue to next character if not a parenthesis

push_stack:
mov al, '(' ; Push '(' onto the stack
mov bl, [top] ; Get the current top of the stack
mov [stack+ebx], al ; Store '(' at the top
inc byte [top] ; Increase the top of the stack
jmp next_char

pop_stack:
cmp byte [top], 0 ; Check if the stack is empty
je unbalanced ; If empty, it's unbalanced
dec byte [top] ; Pop the stack
jmp next_char

next_char:
inc esi ; Move to the next character
jmp check_parentheses

check_end:
cmp byte [top], 0 ; If stack is empty, parentheses are balanced
je balanced
jmp unbalanced

balanced:
mov edx, 19 ; Length of balanced message
mov ecx, msg_balanced
jmp print_result

unbalanced:
mov edx, 20 ; Length of unbalanced message
mov ecx, msg_unbalanced

print_result:
; Linux sys_write example (or other suitable output)
mov eax, 4
mov ebx, 1
int 0x80

; Exit the program


mov eax, 1
xor ebx, ebx
int 0x80
??
2. Design and Development Process
Design Choice: A stack is the most efficient data structure to check for balanced
parentheses due to its LIFO property. In this program, we push each opening
parenthesis ( onto the stack and pop it when a closing parenthesis ) is encountered.
Steps in Development:
1. Initialization: The program begins by initializing the stack and setting a pointer
to the start of the string.
2. Push Operation: When an opening parenthesis ( is found, it is pushed onto the
stack.
3. Pop Operation: When a closing parenthesis ) is found, we check if there is a
matching opening parenthesis by popping from the stack.
4. Final Check: After processing the string, if the stack is empty, the parentheses
are balanced. Otherwise, they are not.
Low-Level Programming Understanding: Implementing a stack manually in assembly
enhances the understanding of memory addressing, pointer arithmetic, and how data is
manipulated at the machine level. It forces you to think about how data structures
operate without the abstraction of higher-level languages.
3. Benefits of Using Assembly Language for High-Level Data Structures
Efficiency and Control: Assembly language allows for precise memory and register
control, which can lead to more efficient implementations. By directly manipulating
memory addresses and stack pointers, you optimize the use of resources. This program
highlights how managing memory manually enables a deeper understanding of
performance optimization.
Learning Low-Level Concepts: Writing this program in assembly provides insight into
how the stack is managed at a machine level, reinforcing the concept of stack
operations (push and pop) in memory. This knowledge is critical when developing
efficient software in higher-level languages.
Direct Hardware Interaction: Assembly allows programmers to interact directly with
the CPU, providing insights into how hardware processes instructions. This is especially
valuable in resource-constrained environments like embedded systems, where
managing memory manually is essential for performance.
Conclusion
This project enhanced my understanding of low-level programming by requiring me to
implement and manage memory manually, reinforcing core concepts such as memory
addressing and stack operations. While assembly lacks the abstraction of higher-level
languages, it offers unparalleled efficiency and control, making it a valuable tool for
certain applications, such as real-time systems or embedded software development. By
mastering these concepts, I gained a deeper appreciation for how higher-level
languages manage data structures and memory.
References:
 Irvine, K. R. (2020). Assembly Language for x86 Processors. Pearson Education.
 Null, L., & Lobur, J. (2014). The Essentials of Computer Organization and
Architecture. Jones & Bartlett Learning.

Explanation:
1. Design and Development Process
In this assignment, I designed a program to check if a sequence of parentheses (e.g.,
(()())) is balanced using a stack. A stack is a simple and highly effective data structure to
solve problems involving pairs of symbols, such as parentheses. The stack operates on
a Last-In-First-Out (LIFO) basis, meaning the last item pushed onto the stack is the first
one to be removed, making it ideal for keeping track of paired symbols in a sequence.
The process of solving the problem can be broken down into the following steps:
Step 1: String Traversal
The program starts by reading each character in the string, which contains parentheses
like (()()). It processes one character at a time, determining if it's an opening parenthesis
( or a closing parenthesis ).
Step 2: Push Operation (for opening parentheses)
When the program encounters an opening parenthesis (, it pushes it onto the stack.
This means that the program "remembers" the presence of an unmatched opening
parenthesis. The position of this opening parenthesis is stored in memory by adding it to
the stack.
Step 3: Pop Operation (for closing parentheses)
When the program encounters a closing parenthesis ), it checks the stack. If the stack is
not empty, it means there's an unmatched opening parenthesis that can pair with the
closing parenthesis. The program removes the last pushed opening parenthesis from
the stack (this operation is called "popping" from the stack). If the stack is empty at this
point, it indicates that there's no matching opening parenthesis for the closing
parenthesis, meaning the sequence is unbalanced.
Step 4: End of the String Check
Once the entire string has been processed, the program checks the stack one last time.
If the stack is empty, it means all opening parentheses had corresponding closing
parentheses, and the sequence is balanced. However, if there are still unmatched
opening parentheses left in the stack, the sequence is unbalanced.
2. Understanding Gained from Low-Level Programming
This project reinforced my understanding of several important low-level programming
concepts:
Memory Management: Unlike high-level languages where data structures such as
stacks are abstracted away, assembly programming forces the programmer to manually
manage memory. The stack in this project is implemented by directly manipulating
memory locations and tracking the "top" of the stack.
Control Over Execution: Assembly language offers direct control over how data is
processed and stored. This level of control helps build a deeper understanding of how
high-level operations, like pushing and popping from a stack, are implemented at the
hardware level.
Efficient Use of Resources: Writing the program in assembly requires careful
management of CPU registers and memory, leading to more efficient programs. While
high-level languages handle memory allocation automatically, assembly programming
forces the programmer to think about how much memory is being used and how to
optimize the code.
By writing this program, I gained a clearer understanding of how data structures like
stacks operate at a low level and how these structures can be manually controlled to
solve real-world problems.
3. Benefits of Using Assembly Language for High-Level Data Structures
Using assembly language for high-level data structures, like a stack, offers several
advantages:
Efficiency
Assembly language provides direct access to memory and CPU registers, allowing the
programmer to write highly efficient code. This is especially important in performance-
critical applications, such as embedded systems or real-time applications, where even
small inefficiencies can lead to slower execution times.
For example, pushing an element onto the stack or popping it off the stack in assembly
language is done by directly manipulating memory addresses, avoiding the overhead
associated with function calls or dynamic memory management in high-level languages.
This makes assembly language suitable for scenarios where efficiency is paramount.
Understanding of System Architecture
Programming in assembly gives a deeper understanding of the underlying hardware. It
makes the programmer more aware of how memory is allocated and managed and how
the CPU processes instructions. This knowledge is valuable not only for assembly
language programming but also when writing high-performance code in higher-level
languages like C or C++.
By implementing a stack manually, I learned how to manage memory manually and
gained an appreciation for how high-level languages abstract away these details.
Fine-Grained Control
In assembly language, the programmer has complete control over how data is stored,
processed, and retrieved. This control allows for optimizations that would not be
possible in higher-level languages. For instance, managing the exact position of the
stack pointer and controlling when data is pushed or popped from the stack gives the
programmer the ability to optimize memory usage.
For a problem like checking balanced parentheses, the control over how memory is
used and how data flows through the system can lead to highly optimized, efficient
code.
Relevance in Embedded Systems
In embedded systems, where resources are limited and performance is critical,
assembly language is often used for tasks that require fine control over the hardware.
Implementing a stack in assembly would be a common task in embedded programming
for managing interrupt routines or tracking nested function calls.
Conclusion
This project provided a valuable learning experience in low-level programming by
demonstrating how high-level data structures like stacks can be implemented directly
using assembly language. It helped me understand how to manage memory, control the
flow of data, and optimize performance. While assembly language is more complex and
time-consuming compared to higher-level languages, the efficiency, control, and
understanding it provides make it a valuable tool, especially in performance-critical and
resource-constrained environments.

You might also like