0% found this document useful (0 votes)
10 views17 pages

ASM - Notes 3

Uploaded by

hworld1202
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)
10 views17 pages

ASM - Notes 3

Uploaded by

hworld1202
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/ 17

Govt.

Postgraduate College of Science, Faisalabad BS-CS 3rd & 5th Semesters - ASM

&

M.Rizwan
Computer Lecturer

1
Govt. Postgraduate College of Science, Faisalabad BS-CS 3rd & 5th Semesters - ASM

Computer Organization & Assembly Language

16-Bit
Processor
NASM
64-Bit
&
Processor
DOSBox
Assembly
Language
Programming
MASM
& AFD
VS 2017
32-Bit
Processor

Assembly Language gives you direct control of the system's


resources. The involves setting processor registers, accessing
memory locations, and interfacing with other hardware elements.
This requires a significantly deeper understanding of exactly how
the processor and memory work.

2
Govt. Postgraduate College of Science, Faisalabad BS-CS 3rd & 5th Semesters - ASM

Procedures
These notes introduce you to Procedures, also known Subroutines and Functions. Any
program of reasonable size needs to be divided into parts, and certain parts need to be used
more than once. You will see that parameters can be passed in registers, and you will learn
about the runtime Stack that the CPU uses to track the calling location of procedures.

Stack Operations
If we place ten plates on each other as in the following diagram, the result can be called a
stack. While it might be possible to remove a dish from the middle of the stack, it is much
more common to remove from the top. New plates can be added to the top of the stack, but
never to the bottom or middle.
Stack of Plates

A stack data structure follows the same principle as a stack of plates: New values are added
to the top of the stack, and existing values are removed from the top. Stacks in general are
useful structures for a variety of programming applications, and they can easily be
implemented using object-oriented programming methods. If you have taken a programming
course that used data structures, you have worked with the stack abstract data type. A stack
is also called a LIFO structure (Last-In, First-Out) because the last value put into the stack is
always the first value taken out.
In these notes, we concentrate specifically on the runtime stack. It is supported directly by
hardware in the CPU, and it is an essential part of the mechanism for calling and returning
from procedures. Most of the time, we just call it the stack.

Runtime Stack
The runtime stack (32-bit mode) is a memory array managed directly by the CPU, using the
ESP (extended stack pointer) register, known as the stack pointer register. In 32-bit mode,
ESP register holds a 32-bit offset into some location on the stack. We rarely manipulate ESP
directly; instead, it is indirectly modified by instructions such as CALL, RET, PUSH, and POP.

3
Govt. Postgraduate College of Science, Faisalabad BS-CS 3rd & 5th Semesters - ASM

ESP always points to the last value to be added to, or pushed on, the top of stack. To
demonstrate, let’s begin with a stack containing one value. In below Fig, the ESP contains
hexadecimal 00001000, the offset of the most recently pushed value (00000006). In our
diagrams, the top of the stack moves downward when the stack pointer decreases in value:
A stack containing a single value

Each stack location in this figure contains 32 bits, which is the case when a program is running
in 32-bit mode.
Note: The runtime stack discussed here is not the same as the stack abstract data type (ADT)
discussed in data structures course. The runtime stack works at the system level to handle
subroutine calls. The stack ADT is a programming construct typically written in a high-level
programming language such as C++, Java, Python or C#. It is used when implementing
algorithms that depend on last-in, first-out operations.

Push Operation
A 32-bit push operation decrements the stack pointer by 4 and copies a value into the location
in the stack pointed to by the stack pointer. Figure A shows the effect of pushing 000000A5
on a stack that already contains one value (00000006). Notice that the ESP register always
points to the last item pushed on the stack. The figure shows the stack ordering opposite to
that of the stack of plates we saw earlier, because the runtime stack grows downward in
memory, from higher addresses to lower addresses. Before the push, ESP = 00001000h; after
the push, ESP = 00000FFCh. Figure B shows the same stack after pushing a total of four
integers.
Figure A - Pushing integers on the stack

4
Govt. Postgraduate College of Science, Faisalabad BS-CS 3rd & 5th Semesters - ASM

Figure B - Stack, after pushing 00000001 and 00000002

Pop Operation
A pop operation removes a value from the stack. After the value is popped from the stack,
the stack pointer is incremented (by the stack element size) to point to the next-highest
location in the stack. Figure shows the stack before and after the value 00000002 is popped.
Popping a value from the runtime stack

The area of the stack below ESP is logically empty, and will be overwritten the next time the
current program executes any instruction that pushes a value on the stack.

Runtime Stack Applications


There are several important uses of runtime stacks in programs:
▪ A stack makes a convenient temporary save area for registers when they are used for
more than one purpose. After they are modified, they can be restored to their original
values.
▪ When the CALL instruction executes, the CPU saves the current subroutine’s return
address on the stack.
▪ When calling a subroutine, you pass input values called arguments by pushing them
on the stack.
▪ The stack provides temporary storage for local variables inside subroutines.

5
Govt. Postgraduate College of Science, Faisalabad BS-CS 3rd & 5th Semesters - ASM

PUSH and POP Instructions


PUSH Instruction
The PUSH instruction first decrements ESP and then copies a source operand into the stack.
A 16-bit operand causes ESP to be decremented by 2. A 32-bit operand causes ESP to be
decremented by 4. There are three instruction formats:
PUSH reg/mem16
PUSH reg/mem32
PUSH imm32

POP Instruction
The POP instruction first copies the contents of the stack element pointed to by ESP into a 16-
bit or 32-bit destination operand and then increments ESP. If the operand is 16 bits, ESP is
incremented by 2; if the operand is 32 bits, ESP is incremented by 4:
POP reg/mem16
POP reg/mem32

PUSHFD and POPFD Instructions


The PUSHFD instruction pushes the 32-bit EFLAGS register on the stack, and POPFD pops the
stack into EFLAGS.
Self-Research (Optionally)

PUSHAD, PUSHA, POPAD, and POPA Instructions


The PUSHAD instruction pushes all of the 32-bit general-purpose registers on the stack in the
following order: EAX, ECX, EDX, EBX, ESP (value before executing PUSHAD), EBP, ESI, and EDI.
The POPAD instruction pops the same registers off the stack in reverse order. Similarly, the
PUSHA instruction, pushes the 16-bit general-purpose registers (AX, CX, DX, BX, SP, BP, SI, DI)
on the stack in the order listed. The POPA instruction pops the same registers in reverse. You
should only use PUSHA and POPA when programming in 16-bit mode.
Self-Research (Optionally)

6
Govt. Postgraduate College of Science, Faisalabad BS-CS 3rd & 5th Semesters - ASM

Example: Reversing a String (Optional)


Let’s look at a program named RevStr that loops through a string and pushes each character
on the stack. It then pops the letters from the stack (in reverse order) and stores them back
into the same string variable. Because the stack is a LIFO (last-in, first-out) structure, the
letters in the string are reversed:

7
Govt. Postgraduate College of Science, Faisalabad BS-CS 3rd & 5th Semesters - ASM

Defining and Using Procedures


If you’ve already studied a high-level programming language, you know how useful it can be
to divide programs into subroutines. A complicated problem is usually divided into separate
tasks before it can be understood, implemented, and tested effectively. In assembly language,
we typically use the term procedure to mean a subroutine. In other languages, subroutines
are called methods or functions.
In terms of object-oriented programming, the functions or methods in a single class are
roughly equivalent to the collection of procedures and data encapsulated in an assembly
language module. Assembly language was created long before object-oriented programming,
so it doesn’t have the formal structure found in object-oriented languages. Assembly
programmers must impose their own formal structure on programs.

PROC Directive
Defining a Procedure
Informally, we can define a procedure as a named block of statements that ends in a return
statement. A procedure is declared using the PROC and ENDP directives. It must be assigned
a name (a valid identifier). Each program we’ve written so far contains a procedure named
main, for example,
main PROC
.
.
main ENDP
When you create a procedure other than your program’s start-up procedure, end it with a
RET instruction. RET forces the CPU to return to the location from where the procedure was
called:
sample PROC
.
.
ret
sample ENDP

Example: SumOf Three Integers


Let’s create a procedure named SumOf that calculates the sum of three 32-bit integers. We
will assume that relevant integers are assigned to EAX, EBX, and ECX before the procedure is
called. The procedure returns the sum in EAX:

8
Govt. Postgraduate College of Science, Faisalabad BS-CS 3rd & 5th Semesters - ASM

;-------------------------------------------------------------------
; SumOf
;
; Calculates and returns the sum of three 32-bit integers.
; Receives: EAX, EBX, ECX, the three integers. May be
; signed or unsigned.
; Returns: EAX = sum
--------------------------------------------------------------------
SumOf PROC
add eax, ebx
add eax, ecx
ret
SumOf ENDP
Functions written in high-level languages like C++ and C# typically return 8-bit values in AL,
16-bit values in AX, 32-bit values in EAX and 64-bit values in RAX.

Example: 64-bit High-Level Language Interfacing with C++

9
Govt. Postgraduate College of Science, Faisalabad BS-CS 3rd & 5th Semesters - ASM

CALL and RET Instructions


The CALL instruction calls a procedure by directing the processor to begin execution at a new
memory location. The procedure uses a RET (return from procedure) instruction to bring the
processor back to the point in the program where the procedure was called. Mechanically
speaking, the CALL instruction pushes its return address on the stack and copies the called
procedure’s address into the instruction pointer. When the procedure is ready to return, its
RET instruction pops the return address from the stack into the instruction pointer. In 32-bit
mode, the CPU executes the instruction in memory pointed to by EIP (instruction pointer
register).
In 64-bit mode, RIP points to the instruction. In 16-bit mode, IP points to the instruction.

Call and Return Example


Suppose that in main, a CALL statement is located at offset 00000020. Typically, this
instruction requires 5 bytes of machine code, so the next statement (a MOV in this case) is
located at offset 00000025:
main PROC
00000020 call MySub
00000025 mov eax, ebx
Next, suppose that the first executable instruction in MySub is located at offset 00000040:

10
Govt. Postgraduate College of Science, Faisalabad BS-CS 3rd & 5th Semesters - ASM

MySub PROC
00000040 mov eax, edx
.
.
ret
MySub ENDP
When the CALL instruction executes (Fig. A), the address following the call (00000025) is
pushed on the stack and the address of MySub is loaded into EIP. All instructions in MySub
execute up to its RET instruction. When the RET instruction executes, the value in the stack
pointed to by ESP is popped into EIP (step 1 in Fig. B). In step 2, ESP is incremented so it points
to the previous value on the stack (step 2).
Fig. A - Executing a CALL instruction

Fig. B - Executing the RET instruction

Nested Procedure Calls


A nested procedure call occurs when a called procedure calls another procedure before the
first procedure returns. Suppose that main calls a procedure named Sub1. While Sub1 is
executing, it calls the Sub2 procedure. While Sub2 is executing, it calls the Sub3 procedure.
The process is shown in Fig.

11
Govt. Postgraduate College of Science, Faisalabad BS-CS 3rd & 5th Semesters - ASM

When the RET instruction at the end of Sub3 executes, it pops the value at stack[ESP] into the
instruction pointer. This causes execution to resume at the instruction following the call Sub3
instruction. The following diagram shows the stack just before the return from Sub3 is
executed:

Nested procedure calls

After the return, ESP points to the next-highest stack entry. When the RET instruction at the
end of Sub2 is about to execute, the stack appears as follows:

12
Govt. Postgraduate College of Science, Faisalabad BS-CS 3rd & 5th Semesters - ASM

Finally, when Sub1 returns, stack[ESP] is popped into the instruction pointer, and execution
resumes in main:

Clearly, the stack proves itself a useful device for remembering information, including nested
procedure calls. Stack structures, in general, are used in situations where programs must
retrace their steps in a specific order.

Passing Register Arguments to Procedures


If you write a procedure that performs some standard operation such as calculating the sum
of an integer array, it’s not a good idea to include references to specific variable names inside
the procedure. If you did, the procedure could only be used with one array. A better approach
is to pass the offset of an array to the procedure and pass an integer specifying the number
of array elements. We call these arguments (or input parameters). In assembly language, it
is common to pass arguments inside general-purpose registers.
In the previous section we created a simple procedure named SumOf that added the integers
in the EAX, EBX, and ECX registers. In main, before calling SumOf, we assign values to EAX,
EBX, and ECX:
.data
theSum DWORD ?
.code
main PROC
mov eax, 10000h ; argument
mov ebx, 20000h ; argument
mov ecx, 30000h ; argument
call SumOf ; EAX = (EAX + EBX + ECX)
mov theSum, eax ; save the sum
After the CALL statement, we have the option of copying the sum in EAX to a variable.

13
Govt. Postgraduate College of Science, Faisalabad BS-CS 3rd & 5th Semesters - ASM

14
Govt. Postgraduate College of Science, Faisalabad BS-CS 3rd & 5th Semesters - ASM

15
Govt. Postgraduate College of Science, Faisalabad BS-CS 3rd & 5th Semesters - ASM

16
Govt. Postgraduate College of Science, Faisalabad BS-CS 3rd & 5th Semesters - ASM

Example: 32-bit High-Level Language Interfacing with C++

Advanced Procedures
▪ Stack Frames
▪ Recursion
▪ INVOKE, ADDR, PROC and PROTO
▪ Creating Multimodule Programs
▪ Advanced use of Parameters
Self-Research (Optionally)

Best of Luck 😊

17

You might also like