x86 Assembly Language
x86 Assembly Language
1
2nd version
www.basiccomparch.com
Download the pdf of the book
videos
Print version
The pdf version of the book and
(Publisher: WhiteFalcon, 2021)
all the learning resources can be
Available on e-commerce sites.
freely downloaded from the
website: www.basiccomparch.com
Overview of the x86 ISA
It is not one ISA
It is a family of ISAs
The great-grandfather in the family
Is the 8-bit 8080 microprocessor used in the mid-seventies
The grandfather is the 16-bit 8086 microprocessor
released in 1978
The parents are the 32 bit processors : 80386, 80486,
Pentium, and Pentium IV
The current generation of processors are 64 bit
processors : Intel Core i3, i5, i7
3
Main Features of the x86 ISA
It is a CISC ISA
Has more than 300+ instructions
Instructions can have a source/
destination memory operand
Uses the stack for passing arguments, and
return addresses
Uses segmented memory
4
Outline
5
View of Registers
6
View of Registers – II
Consider the 16 bit x86 ISA – It has 8 registers: ax, bx,
cx, dx, sp, bp, si, di
7
View of Registers – III
64 bits
32 bits
16 bits
rax eax ax
rbx ebx bx
rcx ecx cx
rdx edx dx 8 registers
rsp esp sp 64, 32, 16
bp
bit variants
rbp ebp
rsi esi si
rdi edi di
r8
The 64 bit ISA has
r9
8 extra registers
r8 - r15
r15
8
x86 can even Support 8 bit Registers
ax ah al
bx bh bl
cx ch cl
dx dh dl
9
x86 Flags Registers and PC
64 bits
32 bits Field Condition Semantics
16 bits OF Overflow Set on an overflow
CF Carry flag Set on a carry or borrow
rflags eflags flags ZF Zero flag Set when the result is a 0,or the
comparison leads to an equality
rip eip ip
SF Sign flag Sign bit of the result
10
Floating-point Registers
FP register
st0 st1 st0
st2 st0
st3 st4 st5 st6 st7
stack
11
View of Memory
x86 follows a segmented memory model
Each address in x86 is actually an offset from the start of the
segment.
For example, an instruction address is an offset in the code
segment
The starting address of the code segment is maintained in a
code segment (CS) register
CS Register Address
memory
Conceptual View
12
Segmentation in x86
16 bit segment registers
cs es
ss fs
ds gs
13
Segmented vs Linear Memory Model
In a linear memory model (e.g. SimpleRisc, ARM) the address
specified in the instruction is sent to the memory system
There are no segment registers
14
How does Segmentation Work
The segment registers nowadays contain an offset into a
segment descriptor table
Because, 16 bits are not sufficient to store a memory
address
Modern x86 processors have two kinds of segment
descriptor tables
LDT (Local Descriptor Table), 1 per process, typically not used
nowadays
GDT (Global Descriptor Table), contains 8191 entries
Each entry in these tables contains the starting address of the
segment
15
Segment Descriptor Cache
16
Memory Addressing Mode
𝑒𝑎𝑥
𝑐𝑠: 𝑒𝑎𝑥
𝑒𝑏𝑥
𝑑𝑠: 𝑒𝑏𝑥
𝑒𝑐𝑥 1
𝑠𝑠: 𝑒𝑐𝑥
𝑒𝑑𝑥
𝑎𝑑𝑑𝑟𝑒𝑠𝑠 = 𝑒𝑠: + 𝑒𝑑𝑥 ∗ 2 + 𝑑𝑖𝑠𝑝𝑙𝑎𝑐𝑒𝑚𝑒𝑛𝑡
𝑒𝑠𝑝 4
𝑓𝑠: 𝑒𝑏𝑝 𝑜𝑓𝑓𝑠𝑒𝑡
𝑒𝑏𝑝 ด8
𝑔𝑠: 𝑒𝑠𝑖
𝑒𝑠𝑖 𝑠𝑐𝑎𝑙𝑒
𝑒𝑑𝑖
𝑒𝑑𝑖 𝑖𝑛𝑑𝑒𝑥
𝑏𝑎𝑠𝑒
19
Basic x86 Assembly
We shall use the NASM assembler in this book
Available at : http://www.nasm.us
Generic structure of an assembly statement
<label> : <assembly instruction> ; <comment>
Comments are preceded by a ;
x86 assembly instructions
Typically in the 1 and 2 address format
2 address format : <instruction> <operand 1> <operand 2>
<operand 1> is typically both the source and destination
20
Basic x86 Assembly – II
Rules for operands (for most instructions)
Both the operands can be a register
At most one of them can be an immediate
At most one of them can be a memory location
A memory operand is encapsulated in []
Rules for immediates
The size of an immediate is equal to the size of the
memory address
For example, for a 32 bit machine, the maximum size of
an immediate is 32 bits
21
Basic x86 Assembly – III
Simply use the registers : ax, bx, cx, dx, sp, bp, si, di
22
The mov instruction
23
movsx and movzx instructions
Semantics Example Explanation
movsx reg, (reg/mem) movsx eax,bx eax ← sign extend(bx), the second
operand is either 8 or 16 bits
movzx reg, (reg/mem) movsx eax,bx eax ← zero extend(bx), the second
operand is either 8 or 16 bits
24
Exchange Instruction
25
Stack push and pop Instructions
27
Modifiers
Modifier Size
byte 8 bits
word 16 bits
dword 32 bits
qword 64 bits
mov eax, 10
mov [esp], eax
push dword [esp]
mov ebx, [esp]
Answer: 10
28
ALU Instructions
Semantics Example Explanation
add (reg/mem), (reg/mem/imm) add eax, ebx eax ← eax + ebx
sub (reg/mem), (reg/mem/imm) sub eax, ebx eax ← eax - ebx
adc (reg/mem), (reg/mem/imm) adc eax, ebx eax ← eax + ebx + (carry bit)
sbb (reg/mem), (reg/mem/imm) sbb eax, ebx eax ← eax - ebx - (carry bit)
29
Single Operand ALU Instructions
inc eax
neg eax
30
Compare Instruction
31
Multiplication and Division Instructions
32
imul Instruction - II
Semantics Example Explanation
imul (reg/mem) imul ecx edx:eax ← eax * ecx
imul reg, (reg/mem) imul ecx, [eax + 4] ecx ← ecx * [eax + 4]
imul reg, (reg/mem), imm imul ecx, [eax + 4], 5 ecx ← [eax + 4] * 5
idiv (reg/mem) idiv ebx Divide (edx:eax) by the contents
of ebx; eax contains the quotient,
and edx contains the remainder.
2 operand form
The first operand (source and destination) has to be a
register
The second operand can either be a register or
memory location
33
imul Instruction - III
Semantics Example Explanation
imul (reg/mem) imul ecx edx:eax ← eax * ecx
imul reg, (reg/mem) imul ecx, [eax + 4] ecx ← ecx * [eax + 4]
imul reg, (reg/mem), imm imul ecx, [eax + 4], 5 ecx ← [eax + 4] * 5
idiv (reg/mem) idiv ebx Divide (edx:eax) by the contents
of ebx; eax contains the quotient,
and edx contains the remainder.
3 operand form
First operand (destination) → register
First source operand (register or memory)
Second source operand (immediate)
34
idiv Instruction
Semantics Example Explanation
Divide (edx:eax) by the contents
idiv (reg/mem) idiv ebx
of ebx; eax contains the quotient,
and edx contains the remainder.
Answer:
mov edx, -1
mov eax, -50
mov ebx, 3
idiv ebx
36
Logical Instructions
37
Shift Instructions
Semantics Example Explanation
sar (reg/mem), imm sar eax, 3 eax ← eax >> 3
shr (reg/mem), imm shr eax, 3 eax ← eax >>> 3
sal/shl (reg/mem), imm sal eax, 2 eax ← eax << 2
Answer: 0xfdeadfee
Answer: 0xdeadfee
39
Outline
40
Simple Branch Instructions
41
Condition Codes in x86
42
Example : Test if a number in eax is
prime. Put the result in eax
x86 assembly code
mov ebx, 2 ; starting index
mov ecx, eax ; ecx contains the original number
.loop:
mov edx, 0 ; required for correct division
idiv ebx
cmp edx, 0 ; compare the remainder
je .notprime ; number is composite
inc ebx
mov eax, ecx ; set the value of eax again
cmp ebx, eax ; compare the index and the number
jl .loop
43
Function Call and Return
Instructions
Semantics Example Explanation
call < label > call .foo Push the return address on the stack.
Jump to the label .foo.
ret ret Return to the address saved on the top
of the stack, and pop the entry
44
What does a typical function do ?
; recursive step
push eax ; save input on the stack
dec eax ; num--
call factorial ; recursive call
pop eax ; retrieve input
imul ebx, eax ; prod = prod * num
.return:
ret ; return
46
Implementing a Function
Using push and pop instructions is fine for small
functions
For large functions that have a lot of internal variables,
it might be necessary to push and pop a lot of values
from the stack
For languages like C++ that dynamically declare local
variables, it might be difficult to keep track of the size
of the activation block.
x86 processors thus save the starting value of esp in
the ebp register. At the end they set esp to ebp.
47
Recursive function for factorial :
without push/pop instructions
x86 assembly code
factorial:
mov eax, [esp+4]; get the value of eax from the stack
; recursive step
sub esp, 8 ; create space on the stack
mov [esp+4], eax ; save input on the stack
dec eax ; num--
mov [esp], eax ; push the argument
call factorial ; recursive call
mov eax, [esp+4] ; retrieve input
imul ebx, eax ; prod = prod * num
.return:
mov esp, ebp ; *** restore the stack pointer
pop ebp ; *** restore ebp
ret ; return
48
Enter and Leave Instructions
Semantics Example Explanation
enter imm, 0 enter 32, 0 push ebp (push the value of ebp on the
stack); mov ebp, esp (save the stack
pointer in ebp); esp ← esp - 32
leave leave mov esp, ebp (restore the value of esp);
pop ebp (restore the value of ebp)
; recursive step
mov [esp+4], eax ; save input on the stack
dec eax ; num--
mov [esp], eax ; push the argument
call factorial ; recursive call
mov eax, [esp+4] ; retrieve input
imul ebx, eax ; prod = prod * num
.return:
leave ; *** load esp and ebp
ret ; return
50
Outline
51
Advanced Memory Instructions
These instructions are useful in moving a large
sequence of bytes from one location to another
Also known as string instructions
They make special use of the edi and esi
registers
edi contains the default destination
esi contains the default source
52
The lea instruction
53
stosd instruction
The stosd instruction does not have any
operands
It saves the value in eax to [edi] (memory location in
edi)
If the value of the DF flag in the flags register is 1
edi ← edi – 4
If the value in the DF flag in the flags register is 0
edi ← edi + 4
Answer: The movsd instruction transfer 4 bytes from the memory address
specified in esi to the memory address specified in edi. Since we write
192 to the memory address specified in esi, we shall read back the same
value in the last line.
57
Power of String Instructions
cld ; DF = 0
mov ebx, 0 ; initialisation of the loop index
.loop:
movsd ; [edi] <-- [esi]
inc ebx ; increment the index
cmp ebx, 10 ; loop condition
jne .loop
58
The rep prefix
cld ; DF = 0
mov ecx, 10 ; Set the count to 10
rep movsd ; Execute movsd 10 times
59
Outline
60
FP Machine Model
Constants
Integer FP
registers registers
Memory
61
FP Load Instructions
Semantics Example Explanation
fld mem fld dword [eax] Pushes an FP number stored in [eax] to
the FP stack
fld reg fld st1 Pushes the contents of st1 to the top of
the stack
fild mem fild dword [eax] Pushes an integer stored in [eax] to the
FP stack after converting it to a 32 bit
floating point number
section .data
num: dd 2.392
63
Assembler Directives – II
64
FP Exchange
65
FP Store Instruction
Semantics Example Explanation
fst mem fst dword [eax] [eax] ← st0
fst reg fst st4 st4 ← st0
fstp mem fstp dword [eax] [eax] ← st0; pop the FP stack
fist mem fist dword [eax] [eax] ← int(st0)
fistp mem fistp dword [eax] [eax] ← int(st0); pop the FP stack
With the 'p' suffix, the inst. also pops the FP stack
66
Example
Answer:
67
Variants of the FP add instruction
Semantics Example Explanation
fadd mem fadd dword [eax] st0 ← st0 + [eax]
fadd reg, reg fadd st0, st1 st0 ← st0 + st1 (one of the registers has
to be st0)
faddp reg, reg faddp st1, st0 st1 ← st0 + st1; pop the FP stack
fiadd mem fiadd dword [eax] st0 ← st0 + float([eax])
69
Example: Arithmetic Mean
Compute the arithmetic mean of two integers stored in eax and ebx. Save the
result (in 64 bits) in esp+4. Assume that the memory address, two, contains the
constant 2.
Answer:
71
Example: Geometric Mean
Compute the geometric mean of two integers stored in eax and ebx. Save the
result (in 64 bits) in esp+4.
Answer:
72
Compare Instructions
Semantics Example Explanation
fcomi reg, reg fcomi st0, st1 compare st0 and st1, and set the eflags
register (first register has to be st0)
fcomip reg, reg fcomi st0, st1 compare st0 and st1, and set the eflags
register; pop the FP stack
73
Example
Compare sin(2θ) and 2sin(θ)cos(θ). Verify that they have the same value for any
given value of θ. Assume that θ is stored in the data section at the label theta, and
the threshold for floating point comparison is stored at label threshold. Save the
result in eax (1 if equal, and 0 if unequal).
Answer:
; compute (2*sin(theta)*cos(theta))
fld dword [theta]
fst st1 ; st1 = st0 = theta
fsin ; st0 = sin(theta)
fxch ; swap st0 and st1 (st1=sin(theta))
fcos ; st0 = cos(theta)
fmul st0, st1 ; st0 = sin(theta) * cos (theta)
fadd st0, st0 ; st0 = st0 + st0
74
Example – II
; compute the modulus of the difference
fld dword [esp] ; load (sin(2*theta))
fsub st0, st1 ; st0 = sin(2*theta)- 2*sin(theta)cos(theta)
fabs
; compare
fld dword [threshold]
fcomi st0, st1 ; compare
ja .equal ; threshold > difference (a for above)
mov eax, 0 ; else not equal
jmp .exit
.equal:
mov eax, 1 ; values are equal
.exit:
75
Stack Cleanup Instructions
76
Outline
x86 Machine Model
Simple Integer Instructions
Branch Instructions
Advanced Memory Instructions
Floating Point Instructions
Encoding the x86 ISA
77
Overview of Instruction Encoding
78
The ModR/M Byte
2 3 3
80
Scale Index Base
2 3 3
** If the R/M bits are 100 , then we use the SIB byte
** If Mod = 00, and R/M = 101 (ebp), we use memory direct addressing
The 32 bit displacement is used as the memory address
82
Example
Encode the instruction: add ebx, [edx + ecx*2 + 32]. Assume that the opcode
for the add instruction is 0x03.
Answer:
Let us calculate the value of the ModR/M byte. In this case, our displacement
fits within 8 bits. Hence, we can set the Mod bits equal to 01 (corresponding to
an 8 bit displacement). We need to use the SIB byte because we have a scale
and an index. Thus, we set the R/M bits to 100. The destination register is ebx.
Its code is 011. Thus, the ModR/M byte is : 01 011 100 (0x5C)
Now, let us calculate the value of the SIB byte. The scale is equal to 2 (01). The
index is ecx(001), and the base is edx (010). Hence, the SIB byte is: 01 001 010
= 0x4A.
83
THE END
84