0% found this document useful (0 votes)
3 views62 pages

Assembly Language Programming

The document provides an overview of assembly language programming, detailing its relationship to machine language and the tools required for development, including assemblers, linkers, debuggers, and editors. It explains the organization of registers in the 8086 and x64 architectures, including general-purpose and special-purpose registers, and discusses assembly instructions and addressing modes. Additionally, it covers data initialization in assembly and the concept of volatile and non-volatile registers in the Microsoft x64 calling convention.

Uploaded by

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

Assembly Language Programming

The document provides an overview of assembly language programming, detailing its relationship to machine language and the tools required for development, including assemblers, linkers, debuggers, and editors. It explains the organization of registers in the 8086 and x64 architectures, including general-purpose and special-purpose registers, and discusses assembly instructions and addressing modes. Additionally, it covers data initialization in assembly and the concept of volatile and non-volatile registers in the Microsoft x64 calling convention.

Uploaded by

sefe
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd

ASSEMBLY LANGUAGE PROGRAMMING

Introduction
Introduction
Introduction
Machine language (computer's native language) is a system of
impartible instructions executed directly by a computer's central
processing unit (CPU).
Instructions consist of binary code: 1s and 0s.
Assembly Language is a programming language that is very similar to
machine language, but uses symbols instead of binary numbers.
It is converted by the assembler (e.g. Tasm and MASM) into
executable machine-language programs.
Assembly language is machine-dependent; an assembly program can
only be executed on a particular machine.
Introduction
Introduction to Assembly Language Tools:
Software tools are used for editing, assembling, linking, and debugging
assembly language programming.
You will need an assembler, a linker, a debugger, and an editor.
Assembler
• An assembler is a program that converts source-code programs written
in assembly language into object files in machine language.
• Popular assemblers have emerged over the years for the Intel family of
processors.
• These include MASM (Macro Assembler from Microsoft), TASM
(Turbo Assembler from Borland), NASM (Netwide Assembler for
both Windows and Linux), and GNU assembler distributed by the free
software foundation.
We will use MASM.
Introduction to Assembly Language Tools:
Linker

• A linker is a program that combines your program's object file


created by the assembler with other object files and link libraries,
and produces a single executable program.
• You need a linker utility to produce executable files.

• Two linkers: [Link] and [Link] are provided with the


MASM distribution to link 16-bit real-address mode and 32-bit
protected-address mode programs respectively.
Introduction to Assembly Language Tools:
Debugger
• A debugger is a program that allows you to trace the execution of a program and
examine the content of registers and memory.
• For 16-bit programs, MASM supplies a 16-bit debugger named CodeView.
• CodeView can be used to debug only 16-bit programs and is already provided
with the MASM distribution. For 32-bit protected-mode programs, you need a
32-bit debugger.
 Editor
• You need a text editor to create assembly language source files.
• You can use NotePad, or any other editor that produces plain ASCII text files.
• You can also use the ConTEXT editor. ConTEXT is a powerful editor that can be
easily customized and can be used as a programming environment to program in
assembly language. I
• t has built-in syntax highlighting feature.
Introduction to Assembly Language Tools:
Register organization of 8086
 8086 has a powerful set of registers containing general purpose and special
purpose registers.
 All the registers of 8086 are 16-bit registers.
 The general purpose registers, can be used either 8-bit registers or 16-bit
registers.
 The general purpose registers are either used for holding the data, variables
and intermediate results temporarily or for other purpose like counter or
for storing offset address for some particular addressing modes etc.
 The special purpose registers are used as segment registers, pointers, index
registers or as offset storage registers for particular addressing modes.
Figure shows register organization of 8086. We will categorize the register
set into four groups as follows:
Introduction to Assembly Language Tools:
Figure shows register organization of 8086. We will categorize the
register set into four groups as follows:
Introduction to Assembly Language Tools:
Figure shows register organization of 8086. We will categorize the
register set into four groups as follows:
• The registers AX, BX, CX, and DX are the general 16-bit registers
Introduction to Assembly Language Tools:
 AX Register:
 Accumulator register consists of two 8-bit registers AL and AH, which can be combined
together and used as a 16- bit register AX.
 AL in this case contains the low-order byte of the word, and AH contains the high-order
byte.
 Accumulator can be used for I/O operations, rotate and string manipulation.
 BX Register:
 This register is mainly used as a base register. It holds the starting base location of a
memory region within a data segment.
 It is used as offset storage for forming physical address in case of certain addressing mode.
 CX Register:
 It is used as default counter or count register in case of string and loop instructions.
 DX Register:
 Data register can be used as a port number in I/O operations and implicit operand or
destination in case of few instructions.
 In integer 32-bit multiply and divide instruction the DX register contains high-order word of
the initial or resulting number.
Introduction to Assembly Language Tools:
Segment registers:
To complete 1Mbyte memory is divided into 16 logical segments.
The complete 1Mbyte memory segmentation is as shown in figure. Each
segment contains 64Kbyte of memory.
There are four segment registers.
 Code segment (CS): is a 16-bit register containing address of 64 KB
segment with processor instructions.
 The processor uses CS segment for all accesses to instructions
referenced by instruction pointer (IP) register.
 CS register cannot be changed directly.
 The CS register is automatically updated during far jump, far call and
far return instructions.
 It is used for addressing a memory location in the code segment of the
memory, where the executable program is stored.
Introduction to Assembly Language Tools:
Segment registers:
 Stack segment (SS): is a 16-bit register containing address of
64KB segment with program stack.
 By default, the processor assumes that all data referenced by the
stack pointer (SP) and base pointer (BP) registers is located in the
stack segment.
 SS register can be changed directly using POP instruction.
 It is used for addressing stack segment of memory. The stack
segment is that segment of memory, which is used to store stack
data.
MASM (MICROSOFT MACRO ASSEMBLER):
A program called assembler is used to convert the mnemonics of the instructions
along with the data into equivalent object code modules, these object code
modules may further be converted into executable code using the linker and
loader programs.
This type of programming is called assembly level programming.
The assembler is a program that converts an assembly input file also called source
file to object file that can be converted into machine codes or an executable file
using linker.
The assembly level programming is done using MASM and TASM ,which along
with it uses a link program to structure the codes operated by MASM in the form
of an executable file.
It reads source program as an input and provides an object file.
The LINK file accepts the .obj file produced by MASM as an input and produces
an .exe file.
MASM (MICROSOFT MACRO ASSEMBLER):
For every assembly language program .asm extension must be there.
The MASM accepts the file name only with extension of .asm. Even if the file
name is without the extension it provides an extension of .asm to it.
SYNTAX: MASM [Link];
General-Purpose Registers (64-bit wide)
These are the main 16 registers available in x64:
 RAX, RBX, RCX, RDX, RSI, RDI, RBP, RSP, R8, R9, R10,
R11, R12, R13, R14, R15

 Each one can also be accessed in smaller chunks:


 64-bit: RAX
 32-bit: EAX
 16-bit: AX
 8-bit: AL (low) and AH (high, for some regs)
Special roles (by convention, not by
hardware)
RAX – accumulator, often used for return values (functions return integers here).
RBX – base register, preserved across function calls (call-saved).
RCX – used for the 1st argument in Windows x64 calling convention.
RDX – used for the 2nd argument.
R8, R9 – 3rd and 4th arguments.
R10, R11 – scratch registers (caller-saved, can be clobbered).
R12–R15 – general purpose but callee-saved (must be preserved by a function).
RBP – traditionally “frame pointer” (optional in modern compilers).
RSP – stack pointer. Always points to the top of the stack.
To write an assembly language programs to evaluate the expressions
A= B+C-D*E
.code ; Example of using a stack register (RSP)
main PROC push rax ;Push RAX onto the stack
; Load immediate values into pop rbx ; Pop from stack into RBX
general-purpose registers
mov rax, 10h
cmp rax, 5 ; Compares RAX with 5,
mov rbx, 20h
mov rcx, 30h jz EqualLabel
mov rax, rdx; ..code if not
; Perform an addition operation equal
add rax, rbx EqualLabel:
; ... code if equal
; Use a different register for
a different purpose ; Return from the procedure
mov rdx, 40h
ret
main ENDP
END
Summery for registers in CPU
64 bit register
What are they? Simply put, they're storage locations on the CPU that
are incredibly fast.

In fact, they're the fastest type of memory that you have access to on
all your hardware available.

The x64 registers evolved from the x86 registers, which in turn
evolved from the 8086 architecture, which in turn evolved from the
8080 microprocessor.
64 bit register cont. ..
There are 16 GPRs on the x64 instruction set; they are referred to as
rax, rbx, rcx, rdx, rbp, rsi, rdi, rsp, r8, r9, r10, r11 r12, r13, r14 and r15.

The prefix “general-purpose” is a little misleading; while they are


technically general-purpose in the sense that the CPU itself doesn't
govern how they should be used.

Some of these registers have specific purposes and need to treated in


specific ways according to what is known as the OS calling conventions.
64 bit register cont. ..

 Where a can be substituted with any of


the other registers.

Figure : Example of a single 64-bit GPR extended from the 8080 ISA.
64 bit register cont. ..
 There is an exception to how these
prefixes/suffixes work, which applies to the
r8 through r15 registers.
 To access the lower 32 bits of these registers,
you add the d suffix to the end.
 We see a difference here compared to the rax
register; there is no way to address the higher
8 bits of the r8 register.
 This is because the registers r8 through r15
were introduced in the x64 ISA and were not
part of the original x86 ISA.

Figure :Example of a 64-bit GPR introduced in the x64 ISA.


Floating point registers
Floating point registers are used for storing actual floating point numbers.

In the x64 instruction set, there are 16 floating point registers, known as the
xmm registers.

These are 128-bit wide, and unlike the GPRs, their lower bits cannot be
addressed separately.

They number xmm0 through xmm15, and as you might expect, are generally
used for SIMD operations as well.
64 bit register cont. ..
 It's important to note here that the diagram
above does not mean that a SIMD register
has separate lanes for xmm, ymm and zmm
instructions; they all form part of the same
register; the names just allow you to access
different parts of it.

Figure :Illustration of a SIMD register in the x64 ISA.


Special purpose registers
These are registers that are reserved for special uses, or part of the evolution
of the ISA and left behind for compatibility reasons.
Instruction pointer (rip). This 64-bit register holds the address of where
the next instruction to be executed is at in the assembly.
Stack pointer (rsp). This is meant to point to the bottom of the stack.
Base pointer (rbp) register. This is usually used to refer to the original
value of rsp, which points to the current position of the last item pushed
onto the stack.
Flags register, also referred to as the FLAGS/EFLAGS/RFLAGS/efl/rfl
register. Unlike the other GPRs, this register stores bit flags that are set
after certain assembly instructions have executed.
64 bit register cont. ..
 While this is a register that you normally
would not be setting values in yourself, it is
useful for referring to in order to infer the
result of a previous operation.
 For example, if you notice that the sign flag
is set, it means that the previous instruction
was probably a test or cmp instruction.
 Instructions like jl (Jump short if Less) rely
on checking the bits set in this register in
Figure :Illustration of the bit flags in the FLAGS register. order to know which branch that they should
execute.
Program segments

 .Data segment:
This segment of memory contains constants or data ( a = 5).

 .code segment:
This contains the actual assembly instructions.
Volatile and non-volatile
In the Microsoft x64 calling convention, certain registers are treated as volatile,
meaning that they are subject to change and are not guaranteed to be preserved
between function calls or scope changes.

The rax, rcx, rdx, r8, r9, r10 and r11 registers are considered volatile.

However, some registers are what's known as non-volatile, which means that
we are potentially responsible for preserving the state of the registers and
restoring their states after our function call is complete.

The rbx, rbp, rdi, rsi, rsp, and r12 through r15 registers are considered
non-volatile and must have their states saved and preserved through
function calls.
Assembly instructions
In this example, the directive/pseudo-op mov is issued with the rbx register as
the source operand, and the rax register as the destination operand.
Thus, when this instruction is executed by the CPU, the contents of the rbx
register will be copied to the rax register.

Figure: Illustration of what happens after an assembly mov instruction.


Assembly instructions cont. …
Some assembly directives have more than two operands, especially specialized
instructions that are designed for SIMD.
Such a directive is the mulss instruction, which can take 2 or 3 operands. Let's take a
look at the latter:
 As we can see, this allows us to do work on 3
registers using only one single instruction,
which, depending on the number of CPU
cycles it costs, might be faster than using
separate instructions for multiplying the xmm2
and xmm1 registers first, before moving the
result to the xmm0 register.

Figure: Illustration of what happens after an assembly mulss instruction.


Addressing modes
Addressing modes, put simply, are the different conventions available by
which an assembly instruction can access registers or other memory.
For example, the instruction:
mov rax, 0
• Is what's known as an immediate addressing mode. This is because the
operand has a constant value.

In contrast, the instruction:


mov rax, rbx
• Is simply known as register addressing.
Initializing data in assembly

Directive Size per value Common use

Characters, strings,
db 1 byte (8-bit)
small numbers

dw 2 bytes (16-bit) Words, short integers

dd 4 bytes (32-bit) Integers, pointers, floats

dq 8 bytes (64-bit) Long integers, doubles


Initializing data in assembly
.data
myText db "Hello world!", 0xd, 0xa, 0
Basically, we define a variable called myText of type byte that is a string of “Hello
world!”,
Terminator characters using their hexadecimal ASCII code equivalents, and finally a null
terminator to indicate the end of the string.

 Making a stack
push rbp
mov rbp, rsp
sub rsp, 32
 The push psuedo-op takes the operand passed to it, decrements the stack pointer, and then stores the operand on top of
the stack.
 We then move the stack pointer to the current base pointer's position, which is currently pointing to the top of the stack,
and then subtract 32 from it, giving us the shadow space necessary to follow the Microsoft x64 calling convention.
Calling functions in assembly
lea rdx, myText
call MessageBoxA

 LEA actually stands for Load Effective Address.


 In this case, we use lea to load the address of the myText variable (which is a pointer to our “Hello, world!” string) into
the rdx register.

Shutting down the program

main ENDP
END
ExitProcess PROTO  1,2,Declares prototypes for two external Win32 API functions so
MessageBoxA PROTO MASM knows they’re procedures you’ll call.

 3,4,5, Defines two null-terminated ASCII strings in the data segment.


.data
The trailing 0 is the C-style terminator expected by MessageBoxA.
myText db "Hello World", 0
myCaption db "Message Box Testing", 0  7, Windows x64 requires the stack to be 16-byte aligned at each
CALL.
.code
main PROC
rcx = 0 → hWnd = NULL (no owner window).
sub rsp, 28h ; reserved shadow area
rdx = &myText → address of the message text. (lea = “load
effective address”.)
mov rcx, 0
lea rdx, myText r8 = &myCaption → address of the window caption.
lea r8, myCaption
mov r9, 0 r9 = 0 → MB_OK (default OK button).
call MessageBoxA call MessageBoxA shows the message box.
mov rcx, 12345678 ; the exit code call
call ExitProcess

main ENDP
END
Export Project Templet
Project Templet
Export Project Templet
Project Templet
Export Project Templet
Project Templet
Export Project Templet
Project Templet
Export Project Templet
Project Templet
Dependence variables
 [Link]
legacy_stdio_definitions.lib
[Link]

How to link:
Right-click your project → Properties
Go to Linker → Input → Additional Dependencies
Include some library and global functions
 [Link] and legacy_stdio_definitions.lib
Those two libraries are part of Visual Studio’s Windows SDK / MSVC toolchain.

[Link] → This is the Universal C Runtime (UCRT) import library.


It ships with Visual Studio 2015 and later.

legacy_stdio_definitions.lib → This provides compatibility for old-style printf, scanf.


Needed when you call printf from MASM, otherwise you’ll get the unresolved external symbol
crt_printf error.

EXTERN printf: PROC→ Declares printf as an external procedure so MASM knows you’ll be calling
it,
Data section
str1 → A null-terminated string with "Hello World!\n" (10 = newline, 0 =
null terminator).

str2 → A format string: expects a %s (string) and two %d (integers).

str3 → A format string: expects a %s and four integers.

string → Just the text "The numbers", null-terminated.


Main Procedure
Calls three helper functions (printStr1, printStr2, printStr3).
Returns 0 in RAX.

On Windows x64, the first four arguments are passed in: RCX, RDX, R8, R9 (in that
order).
Shadow space (sub rsp, 20h) is required before calling any function.
printStr1 (simple hello world)
• Only one argument here → RCX points to "Hello World!".
printStr2 (with %s %d %d)
RCX → format string
RDX → first %s
R8 → first %d
R9 → second %d
Cont. ..
printStr2 (with %s %d %d)
• RCX → format string
• RDX → first %s
• R8 → first %d
• R9 → second %d

printStr3 (with %s %d %d %d %d)


• First 4 arguments go into registers (RCX, RDX, R8, R9).
• Extra arguments (5th, 6th, …) go on the stack (right to left).
• That’s why it push 4 then push 3 (reverse order).
• After the call, it restores the stack (add rsp, 30h).
Add/SUB/INC/DEC registers

1. Initialize RAX
2. add/sub with immediates
3. add/sub register ←→ register
4. Memory arithmetic
5. Memory arithmetic
6. Overflow / carry demo with 8-bit and 16-bit registers
x64 MASM: Add two user-input numbers and
print sum
1. extrn ... : PROC → tells MASM that these are external functions provided by Windows (in [Link]
or [Link]).
extrn GetStdHandle : PROC→ gets a handle to the console’s input or output.
extrn ReadConsoleA : PROC→ reads text from the console (ANSI version).
extrn WriteConsoleA : PROC→ writes text to the console.
extrn ExitProcess : PROC→ ends the program.
extrn wsprintfA : PROC→ formats text like sprintf in C.
2. const
STD_INPUT_HANDLE equ -10, STD_OUTPUT_HANDLE equ -11
 Define constants for standard input (-10) and standard output (-11) → these values are passed to
GetStdHandle.
x64 MASM: Add two user-input numbers and print sum

.data
inputBuffer db 128 dup(0) ; buffer for user input (128 bytes, zeroed)
outputBuffer db 128 dup(0) ; buffer for formatted output
fmtStr db "sum = %d",0 ; format string for wsprintfA
prompt1 db "Enter first number: ",0
prompt2 db "Enter second number: ",0

num1 dq 0
num2 dq 0
sum dq 0
written dq 0 ; used to store number of characters written

• db → define bytes.
• dq → define 8-byte integers (64-bit).
• Strings are null-terminated (0 at the end).
x64 MASM: Add two user-input numbers and print sum

.code
main PROC
sub rsp, 40 ; shadow space + stack alignment
 Allocate 40 bytes on the stack. In Windows x64 calling convention, functions must reserve “shadow
space” and keep stack aligned.

mov ecx, STD_OUTPUT_HANDLE


call GetStdHandle
mov rbx, rax ; save stdout handle in RBX
mov ecx, STD_INPUT_HANDLE
call GetStdHandle
mov rdi, rax ; save stdin handle in RDI

 Call GetStdHandle(-11) → gets output handle → save to rbx.


 Call GetStdHandle(-10) → gets input handle → save to rdi.
x64 MASM: Add two user-input numbers and print sum

 Prompt and read first numbermain PROC


mov rcx, rbx ; RCX = stdout handle
lea rdx, prompt1 ; RDX = pointer to "Enter first number:"
mov r8d, LENGTHOF prompt1-1 ; R8D = length of string
lea r9, written ; R9 = pointer to DWORD for chars written
xor rax, rax
call WriteConsoleA
 Writes the prompt to the console.
mov rcx, rdi ; RCX = stdin handle
lea rdx, inputBuffer ; RDX = pointer to buffer
mov r8d, 128 ; R8D = buffer size
lea r9, written ; R9 = pointer to chars read
xor rax, rax
call ReadConsoleA
x64 MASM: Add two user-input numbers and print sum

mov rcx, rbx mov rcx, rdi


lea rdx, prompt2 lea rdx, inputBuffer
mov r8d, LENGTHOF prompt2-1 mov r8d, 128
lea r9, written
lea r9, written
xor rax, rax
xor rax, rax call ReadConsoleA
call WriteConsoleA ; Convert ASCII →
; Read second input integer
lea rcx, inputBuffer
call atod
mov num2, rax
x64 MASM: Add two user-input numbers and print sum

 Reads user input into inputBuffer.


lea rcx, inputBuffer
call atod ; convert ASCII → integer
mov num1, rax
 Compute sum
mov rax, num1
add rax, num2
mov sum, rax
 Print result
lea rcx, outputBuffer
lea rdx, fmtStr
mov r8, sum
call wsprintfA
x64 MASM: Add two user-input numbers and print sum

 atod (ASCII to integer)


atod PROC sub dl, '0' ; convert char → digit
xor rax, rax ; result = 0 cmp dl, 9
xor rdx, rdx ja convert_done ; if not 0–9, stop
next_char: imul rax, rax, 10 ; result *= 10
mov dl, byte ptr [rcx] ; load next character add rax, rdx ; result += digit
cmp dl, 13 ; CR? inc rcx ; move to next char
je convert_done jmp next_char
cmp dl, 10 ; LF? convert_done:
je convert_done ret
cmp dl, 0 ; null terminator? atod ENDP
je convert_done
 Write an x64 MASM Assembly program to read two binary
numbers from the user and perform the four basic arithmetic
operations: addition, subtraction, multiplication, and division.

 Reads two binary strings (e.g., 101, 11),

 Converts them to 64-bit integers,

 performs addition, subtraction, multiplication, and division (unsigned),

 prints each result in binary (and for mul also warns on overflow, for
div prints quotient & remainder).
Practice on Shift and Rotate Operations

 This x64 Assembly program demonstrates how binary shift and rotate operations work at the bit level
using MASM (Microsoft Macro Assembler) under Visual Studio 2022.
 It performs six different operations on the same 8-bit binary value (10100110₂) with a 3-bit shift:

• Logical Right Shift (SHR).


• Logical Left Shift (SHL).
• Arithmetic Right Shift (SAR).
• Arithmetic Left Shift (SHL).
• Right Rotate (ROR).
• Left Rotate (ROL)

 Uses Windows API console functions to handle input/output:

• GetStdHandle – gets the console handle.


• WriteConsoleA – writes ASCII strings directly to the console.
• ExitProcess – exits cleanly.
Shift and Rotate Operations

 Each operation:

• Loads the value from InitVal into a register (e.g., BL or AL).


• Applies a shift or rotate instruction (e.g., shl, shr, sar, ror, rol).
• Converts the result to binary using MakeBin8.
• Prints both a label and the result.

Operation Instruction Description


Logical Left SHL Moves bits left; fills right side with 0.
Logical Right SHR Moves bits right; fills left side with 0.
Arithmetic Right SAR Moves bits right; preserves sign bit (MSB).
Arithmetic Left SHL Same as logical left; may cause overflow.
Rotate Left ROL Shifts bits left; wraps MSB into LSB.
Rotate Right ROR Shifts bits right; wraps LSB into MSB.
Output Example
Input: 10100110

Logical right shift (3 bits): 00010100


Logical left shift (3 bits): 00110000
Arithmetic right shift (3 bits): 11110100
Arithmetic left shift (3 bits): 00110000
Right rotate (3 bits): 11010100
Left rotate (3 bits): 00110101

Exercise for the students

• Modify InitVal to test other binary inputs.

• Change the shift count (e.g., 1, 2, or 4 bits).

• Add user input (using ReadConsoleA) to make it interactive.


Instruction Addressing Modes
• 3-Address: dest = src1 + src2 (simulated in x64).

• 2-Address: ADD dest, src → dest = dest + src.

• 1-Address: Accumulator-based (LDA, ADD, STA).

• 0-Address: Stack-based (push operands, ADD pops two


values)

Example: N = I + J + K
Instruction Addressing Modes
Example: N = I + J + K
3-Address: dest = src1 + src2 2-Address: ADD dest, src →
dest = dest + src
mov r9, I
mov r10, J mov rax, I
mov r11, K add rax, J
add rax, K
mov r8, r9 mov N, rax
add r8, r10
add r8, r11
mov N, r8
Instruction Addressing Modes
Example: N = I + J + K
0-Address: Stack-based (push operands,
1-Address: Accumulator- ADD pops two values)
based (LDA, ADD, STA).
mov rax, I mov rax, K
load I // AC =M[I] push rax
add J push rax
mov rax, J pop rbx
add K push rax
store N pop rax
pop rbx add rax, rbx
pop rax mov N, rax
add rax, rbx
push rax

You might also like