Asm03 AsmIntro
Asm03 AsmIntro
1
Basic Elements: Labels and Names Types of Assembler “Statements”
• Names identify labels, variables, symbols, or keywords • Assembler "statements" fall into three broad classes:
• May contain: 1. Directives
A..Z,a..z limit EQU 100 ; defines a symbol limit
0..9 %define limit 100 ; like C #define
? _ @ $ . ~ CPU P4 ; Use Pentium 4 instruction set
• NASM is case-sensitive (unlike most x86 assemblers) 2. Data Definitions
• First character must be a letter, _ or “.” (which has a msg db 'Welcome to Assembler!'
special meaning in NASM as a “local label” which can be db 0Dh, 0Ah
redefined) count dd 0
mydat dd 1,2,3,4,5
• Names cannot match a reserved word (and there are
resd 100 ; reserves 400 bytes of
many!)
; uninitialized data
3. Instructions
mov eax, ebx
add ecx, 10
2
Keywords Hello World (MASM MS-DOS)!
• Keywords can be register names , instruction dosseg
.model small
mnemonics, assembler pseudo-ops and directives .stack 100H
• Examples .data
eax mov proc db hello_message db 'Hello, World!',0dh,0ah,'$'
.code
ah add sub .IF
main proc
ASSUME END .WHILE SHLD mov ax, @data
mov ds,ax
• If you accidentally use a keyword as a variable name mov ah,09
mov dx,offset hello_message
you may get a misleading error message
int 21H
mov ax,4c00h
int 21h
main endp
end main
Hello World (NASM Linked with C - Windows) Hello World (NASM Linked with C - Linux)
global _main global main
extern _printf extern printf
3
Object Code, Load Images, Linkage Overview and Grouping of x86 Instructions
• In a high-level language, the process of producing an executable • Assembler Instructions can be categorized by
program looks like this: function:
Source code object code executable program 1. Data Movement
Compile Link
2. Arithmetic and Comparison
• Object code modules are language-independent linker inputs
• An executable program may not contain "pure machine
3. Bit and Logical Operations
language" : it may have unresolved memory references, 4. Character Operations
function calls, etc. 5. Control Flow
6. Miscellaneous
Executable Program Load Image Run
7. Semaphore and Process Sync (486+)
OS program loader Load IP
8. System Programming Instructions
• In the list below, 16/32 bit instructions are in all
• The operating system supplies a "program loader" that resolves
these references and creates a "load image"
uppercase while 32-bit only instructions are
lowercase
• The load image is pure machine language
• Assembler mnemonics are NOT case-sensitive;
either can be used
4
Control Flow Miscellaneous
• Unconditional Jump: • External Synchronization:
JMP ESC, HLT, LOCK, WAIT
• Subroutine Call: • Space Filling/Time Wasting:
CALL, RET NOP (No OPeration)
• Conditional Jumps:
• Stack frame:
JA, JAE, JB, JBE, JC, JCXZ, JE, JG, JGE, JL,
JLE, JNA, JNAE, JNB, JNBE, JNC, JNE, JNG, ENTER, LEAVE
JNGE, JNL, JNLE, JNO, JNP, JNS, JNZ, JO, JP, • Array bound testing:
JPE, JPO, JS, JZ BOUND
The above conditionals are not all distinct
• Endian reversal
• Loops:
bswap 486+
LOOP, LOOPE, LOOPNE, loopd, loopdne, loopde
• Interrupts:
• Misc Pentium:
INT, INTO, IRET rdmsr, wrmsr, rdtsc, cpuid, rsm
• Flag Control: • Semaphore and Process Sync (486+)
CLC, CLD, CLI, CMC, STC, STD, STI xadd, cmpxchg, cmpxchg8b
5
Data Definition Syntax Uninitialized Data
• NASM has different syntax for initialized and • NASM uses different syntax for uninitialized
uninitialized values data, which goes into the “bss” segment
• INITIALIZED VALUES: segment .bss
• [name] Dx initialvalue [,initialvalue]
• Just like Dxx but use resXX with the number
where Dx is
db byte
of objects needed
buffer resb 64 ; reserve 64 bytes
dw word wordvar resw 1 ; reserve a word
dd double word realarray resd 10 ; array of ten dwords
df far pointer (6-byte) qval resq 1 ; 1 qword
dq quad word
dt ten-byte
• Displayed by debug:
0EB4:0100 41 53 4D 20 69 73 20 66 ASM is f
0EB4:0108 75 6E 21 0D 0A 28 66 6F un!..(fo
0EB4:0110 72 20 6D 61 73 6F 63 68 r masoch
0EB4:0118 69 73 74 73 29 12 34 56 ists).4V
0EB4:0120 78 34 12 78 56 78 56 34 x4.xVxV4
0EB4:0128 12 78 56 34 12 00 00 00 .xV4....
0EB4:0130 00 00 00 80 3F 72 6F 6D ....?rom
6
The TIMES prefix Basic Instructions
• The TIMES prefix causes the data definition or • We will start taking a tour through the basic parts of
instruction to be assembled multiple times. Ex: the x86 instruction set
zerobuf TIMES 2048 db 0 • For each instruction, we need to look at the syntax,
Initializes a 2048 byte variables call zerobuf semantics (effects on operands and flags) and what
• The argument to TIMES is an expression legal operands may be used
buffer: db ’hello, world’ • Operand abbreviations:
times 64−$+buffer db ’ ’ reg 8,16, or 32-bit register except segment regs
• TIMES can also be applied to instructions to provide imm immediate operand
trivially unrolled loops mem 8,16, or 32-bit memory cell
TIMES 32 add eax, edx segreg segment register
• In .bss (uninitialized data) these are equivalent: reg16 16-bit register except segreg
TIMES 1000 resd 1 mem16 16-bit word in memory
resd 1000 reg8, mem8 8-bit register/memory
But the latter assembles 1000 times faster reg32, mem32 32-bit register/memory
7
Values and Addresses MOV examples
• In NASM a variable name is an address •Includes some indirect addressing
mov ebx, count ; load address of count mov eax,ebx eax <- contents of ebx
mov ebx, [count] ; load value of count mov eax,[ebx] eax <- contents of word at address ds:ebx
• Note that while value arithmetic in a statement is mov eax,[ebx+4] eax <- contents of word at address ds:ebx+4
NOT legal, address arithmetic often IS legal mov ax,[ebx] ax <- contents of word at address DS:EBX
mov eax,1234ffeeh eax <- 1234ffeeH
(remember the function of the bus interface unit)
mov ah,[ebx+esi] AH <- contents of byte at
mov ebx, count+2 ; OK, load addr of count+2
address ds:ebx+esi
mov ebx, [count]+2 ; ILLEGAL
mov ds,ax ds <- contents of ax
mov ebx, [count+2] ; OK, Load 32-bit located mov [edx],0100h Word at address ds:edx <- 100H
; at address of count + 2 mov ebx, 0100h BX <- 100h
mov [0122h],es Word at addr DS:0122H <- contents of es
mov es,ax ES <- Contents of ax
MOV [SavEAX],eax Stores contents of eax into SavEAX
MOV SaveEAX,eax Not legal in NASM
8
Assembler is not C or Java A First Program
• In C or Java indexes in an array are compiled to • This program prompts the user to enter two numbers
correct element size: and then displays the sum
%include "asm_io.inc"
• C/Java Asm equivalent
;
int x,y; x dd 0
; initialized data is put in the .data segment
int a [5]; y dd 0 ;
... a TIMES 5 dd 0 segment .data
x = 5; mov [x],5 ;
y = a[1]; mov ebx, a ; These labels refer to strings used for output
a[2] = x+y; mov edx,[ebx+4] ;
mov [y], edx prompt1 DB "Enter a number: ", 0 ; don't
forget nul terminator
add edx, [x]
prompt2 db "Enter another number: ", 0
mov [ebx+8], edx
outmsg1 db "You entered ", 0
• In assembler we have offsets not indices (in example outmsg2 db " and ", 0
above an int is 4 bytes) outmsg3 db ", the sum of these is ", 0
; code is put in the .text segment mov eax, [input1] ; eax = dword at input1
; add eax, [input2] ; eax += dword at input2
mov ebx, eax ; ebx = eax
dump_regs 1 ; dump out register values
dump_mem 2, outmsg1, 1 ; dump out memory
9
PUSH and POP POP
• Used to store and retrieve data from the stack • POP Syntax:
• PUSH and POP work with words or dwords only (not bytes POP dest POPD Dest
• To PUSH a byte it has to be extended to a word • Semantics:
• PUSH Syntax: (1) dest <- [SS:SP] | dest <- [SS:ESP]
PUSH source PUSHD source (2) SP <- SP + 2 | ESP <- ESP+4
• Semantics: (16|32) Flags: ODITSZAPC unchanged
(1) SP <- SP-2 | ESP <- ESP-4 • Operands:
(2) [SS:SP] <- source | [SS:ESP] <- source reg16 mem16 segreg reg32 mem32
Flags: ODITSZAPC unchanged
• Operands: • Notes:
reg16 mem16 segreg reg32 mem32 imm esp is decremented as stack grows
• Notes: esp always points to last item on stack, not to the next available
word (except when stack is empty)
1. In 32-bit code, PUSHD is necessary for imm operands only; push
eax is unambiguous POPD syntax only necessary when dest is not a register
• Other instructions that affect the stack (CALL and RET) will be
discussed later
10
Operand Size Specification Operand Size Specifiers
• With many instructions size of operand can be inferred from • Register references can be resolved by size of register
instruction itself. Examples: • Some memory references can be resolved by known size of other
PUSH AX operand
pop ecx
mov ah, [edx]
• Memory-immediate references are usually ambiguous
• Operand size specifiers byte, word, dword etc are used to
• With other instructions size of one operand can be inferred from
resolve ambiguous references
size of the other operand.
add dword [esi],1
• Examples: (ebx = 007Ah)
add byte [esi],1
MOV ah,[ebx] refers to a byte at address [ebx]
MOV ax,[ebx] refers to a word at address [ebx] add word [esi],1
ADD [ebx],FFFFFFFFh adds to dword at [ebx] • Because NASM does not associate declared size with variables, you
ADD [ebx],1 ??
must specify operand size when adding imm to memory
AND [ebx],0DFh ??
myvar dd 0
• What if memory at [ebx] = FF 00 00 00?
ADD [ebx],1 results in 00 10 00 00 for a 16 or 32-bit add add dword [myvar],1
ADD [ebx],1 results in 00 10 for a 16-bit add
ADD [ebx],1 results in 00 00 for a 16-bit add
(remember little-endian ordering: FF 00 is 00 FF)
11
ADC Example Compare (CMP)
• Example: Unsigned 32-bit addition in 16-bit machine • Compare (CMP) is subtraction without storage of the
vars dd 2 dup (?) ; two 32-bit vars
. . . ; var[0] = 0000fffe (65,534) var[1]=00000003 = 3
result. Only the flags are affected
mov si, vars • Syntax:
mov ax, [si] ; low-order word
mov dx, [si+2]; high-order word CMP dest, source
add [si+4],ax ; add ax into low order word
adc [si+6],dx ; add dx into h.o. word with CF
• Semantics:
compute dest - source and modify flags
FE FF 00 00 03 00 00 00
Flags: O...SZAPC modified
SI
.DIT..... unchanged
mov ax, [si] ; AX = FFFE • Operands:
mov dx, [si+2]; DX = 0000 reg,reg mem,reg reg,mem
add [si+4],ax ; FFFE + 0003 = 0001 CF Set reg,immed mem,immed
adc [si+6],dx ; 0000 + 0000 + 1(cf) = 1
• Notes:
;result: 00010001h = 65536 + 1 = 65537
Operands same as SUB; can compare immed to mem
FE FF 00 00 01 00 01 00 We will discuss in more detail with conditional jumps
12
Multiplication & Division MUL (unsigned MULtiply)
• x86 multiplication and division instructions are much • Syntax: MUL source
more restricted than addition or subtraction • Semantics:
AX <-- AL * source8
• Both require the use of the accumulator register (al, DX:AX <-- AX * source16
ax, or eax) edx:eax <-- eax * source32
Flags: O.......C modified
....SZAP. undefined
• Unlike addition and subtraction, multiplication and .DIT..... unchanged
division have separate instructions for unsigned and
signed operands • Operands:
regmem NOTE: No Immediate
• Overflow and Carry flags are identical after a
• Unsigned: MUL, DIV multiplication
• Signed: IMUL, IDIV 0 = entire product is available in low-order part (AL, AX or
eax)
1 = product occupies both parts (AX, DX:AX or eax:edx)
3) MOV BL,5
MUL BL O = 0 C = 0; AX = 210 (AL = 210)
4) MOV BL,7
IMUL BL O = 1 C = 1; AX = 294 (AL = 38)
13
Division: DIV and IDIV DIV and IDIV
• DIV for (unsigned) numbers and IDIV (signed) • Syntax:
DIV source
• 8-bit division requires a 16-bit dividend in AX and an 8- IDIV source
bit divisor in an 8-bit location. • Semantics:
If the quotient requires more than 8 bits, then a divide overflow AL <-- quotient of AX / source8
error is generated. AH <-- remainder of AX / source8
OR:
This causes an INT 0 exception; the default INT 0 handler
AX <-- quotient of DX:AX / source16
terminates the program, displays a "Divide Overflow" message and
DX <-- remainder of DX:AX / source16
returns to the OS
OR:
• In 8-bit division the quotient goes into AL and the eax <-- quotient of edx:eax / source32
remainder into AH. edx <-- remainder of edx:eax / source32
Processor generates INT 0 exception if quotient too large or attempt to
• 16-bit division requires a 32-bit dividend in DX:AX and a divide by 0
16-bit divisor in a 16-bit location. Flags: O...SZAPC undefined
.DIT..... unchanged
• 32-bit division requires a 64-bit dividend in edx:eax and • Operands:
a 32-bit divisor in a 32-bit location. reg mem NOTE: No Immediate
• Note that all status flags are undefined after DIV or IDIV
14
math.asm:2 math.asm:3
mov eax, prompt mov ebx, eax
call print_string imul ebx, [input] ; ebx *= [input]
mov eax, cube_msg
call read_int call print_string
mov [input], eax mov eax, ebx
call print_int
imul eax ; edx:eax = eax * eax call print_nl
mov ebx, eax ; save answer in ebx
mov eax, square_msg imul ecx, ebx, 25 ; ecx = ebx*25
call print_string mov eax, cube25_msg
mov eax, ebx call print_string
call print_int mov eax, ecx
call print_nl call print_int
call print_nl
math.asm:4 math.asm:5
neg edx ; negate the remainder
mov eax, ebx mov eax, neg_msg
; initialize edx by sign extension call print_string
cdq mov eax, edx
mov ecx, 100 ; can't divide by immediate value call print_int
idiv ecx ; edx:eax / ecx call print_nl
mov ecx, eax ; save quotient into ecx
mov eax, quot_msg popa
call print_string mov eax, 0 ; return back to C
mov eax, ecx leave
call print_int ret
call print_nl
mov eax, rem_msg
call print_string
mov eax, edx
call print_int
call print_nl
15
Short, Near, Far The JMP Instruction
• Before we examine jumps we need to look at "distances" in • Syntax:
memory
JMP dest
• The segmented architecture of 8086 allows two types of addresses:
JMP NEAR dest
NEAR specified by 16 bit offset relative to CS
FAR specified by 32 bit segment:offset; anywhere within 1MB physical JMP FAR destJMP SHORT dest
memory
• Semantics
• For 32 machines we still have NEAR or FAR
EIP <- dest
NEAR specified by 32 bit offset relative to CS
FAR specified by 48 bit segment:offset; anywhere within 4GB physical Flags: ODITSZAPC unchanged
memory
• Operands:
• Machine encoding of jumps adds another type of address:
index reg mem label
SHORT specified by 8-bit signed address; range is -128 to +127 bytes
• On 386+ processors, conditional jumps (Jxx) can be: • Note: under operands we have added two new types:
SHORT +127 to -128 bytes index register and label
NEAR +32,767 to -32,768 (if not flat model) A "label" is a symbolic name for an address
NEAR +2G to -2G (flat model)
• Note that SHORT jumps are require only one byte for the jump
offset
16
Overview of Conditional Mnemonics CMP Revisited
• Remember that CMP performs a subtraction and sets the flags
• Unsigned arithmetic: JB, JNAE, JBE, JNA, JA, • Consider what happens with CMP AL,2
Signed Unsigned
JNBE, JAE, JNB AL Meaning Meaning O S Z C Flags
• Signed Arithmetic: JL, JNGE, JLE, JNG, JG, 1 00-01 0 - 1 0 - 1 0 1 0 1
2 02 2 2 0 0 1 0
JNLE, JGE, JNL 3 03-7F 3 - 127 3 - 127 0 0 0 0
• Single Flag: 4 80-81 < -126 128 – 129 1 0 0 0
5 82-FF -126 - -1 130 - 255 0 1 0 0
Zero: JE, JZ, JNE, JNZ
Overflow: JO, JNO • If AL < 2 in a signed interpretation look at rows 1, 4, and 5.
Carry: JC, JNC Here SF <> OF, otherwise if AL >= 2 SF=OF
Sign: JS, JNS • If AL < 2 in an unsigned interpretation look at row 1. Here CF is
Parity JP, JPE, JNP, JPO set, otherwise it is clear
• Test for CX = 0: JCXZ jecxz • Semantics can be precisely expressed in terms of flags but we
will see that English mnemonics make a lot more sense
17
Zero Flag / Equality CF and OF
• These are the most common conditionals used Carry: JC (Jump if Carry)
JNC (Jump if no Carry)
JE (Jump if Equal) Semantics:
JC: IP <- dest if CF = 1
JZ (Jump if Zero)
JNC: IP <- dest if CF = 0
Semantics: IP <- dest if ZF = 1
18
Notes on isalpha function Min-Max Values in Array
ARRAYCOUNT EQU 500
• This function returns a boolean in the zero flag array resd ARRAYCOUNT
ZF = 1 function => True, ZF = 0 => false largest resd 1
smallest resd 1
• Note the AND Mask so that we have to check upper-
MinMax:
case range only mov edi, array ; base address of array
mov eax, [edi] ; get first element
• eax is pushed so that we can restore AL mov [largest], eax ; initialize largest
• Note use of unsigned conditional jumps mov [smallest], eax
mov ecx, ARRAYCOUNT
;
;
initialize smallest
number of elements in array
• If either cmp is true, we know that zf is clear L1:
mov eax, [edi] ; get an element
• If neither is true, sub ax, ax will set zf cmp eax, [smallest] ; is eax < smallest?
jge L2 ; no, skip
mov [smallest], eax ; yes, save it
L2:
cmp eax, [largest] ; is eax > largest?
jle L3 ; no, skip
mov [largest], eax ; yes, save it
L3:
add edi, 4 ; advance pointer
loop L1
19
Sum an Array of Integers Alternate code with displacement addressing
asize EQU 100 • Different addressing mode, same effect:
array TIMES asize dd 0 asize EQU 100
... array TIMES asize dd 0
sub eax, eax ; initialize sum ...
mov ebx, array ; pointer to array sub eax, eax ; initialize sum
mov ecx, asize ; number of elements sub ebx, ebx ; initial offset = 0
L1: mov ecx, asize ; number of elements
add eax,[ebx] L1:
add ebx, 4 add eax,[ebx+array]
loop L1 add ebx,4
loop L1
20
LOOPE/LOOPZ Example: Find First Non-Zero Element
• Notes: hits TIMES 256 dd 0
1. Because the test for loop continuation is an AND, loop will ....
terminate when either ZF = 0 OR ecx = 0 mov ecx, 256 ; number of values
2. This loop is typically used when “searching for a mov ebx, hits-4 ; one element before first val
mismatch” L1:
3. Just as JZ/JE are synonyms, LOOPE and LOOPZ are the add ebx,4
same machine instruction cmp dword [ebx], 0 ; compare immediate to mem
4. It may be more convenient to read the mnemonics as loope L1
“loop while equal” and “loop while zero” because they are
L2:
more similar to a WHILE loop than a count-controlled FOR
loop • How do we know at L2 why the loop terminated?
• We may have found a non-zero value, or we may
have failed to find one after inspecting all 256
elements
21
Example: First Negative Integer The TEST Instruction
• This example finds the first negative int in an array, • TEST is AND without storing results (affects flags
using a TEST instruction (AND operands and modify only) For now consider:
flags) to inspect top bit B0FF = 1011 0000 1111 1111
nums resd vectorsize AND 8000 = 1000 0000 0000 0000
..... Result: 8000 = 1000 0000 0000 0000
FindNeg:
mov esi, nums - 4
mov cx, vectorsize 70FF = 0111 0000 1111 1111
L1: AND 8000 = 1000 0000 0000 0000
add esi, 4 Result: 0000 = 0000 0000 0000 0000
test byte [esi+3], 80h; check top bit
loopz L1
; Find reason why loop terminated
jnz FoundNeg
jmp NoNeg
22
prime.asm:2 prime.asm:3
mov eax, Message while_limit: ; while ( Guess <= Limit )
mov eax,[Guess]
call print_string cmp eax, [Limit]
call read_int ; scanf("%u", & limit ); jnbe end_while_limit ; use jnbe b/c data are unsigned
mov [Limit], eax
mov ebx, 3 ; ebx is factor = 3;
while_factor:
mov eax, 2 ; printf("2\n"); mov eax,ebx
call print_int mul eax ; edx:eax = eax*eax
jo end_while_factor ; if answer won't fit in eax
call print_nl alone
mov eax, 3 ; printf("3\n"); cmp eax, [Guess]
jnb end_while_factor ; if !(factor*factor < guess)
call print_int mov eax,[Guess]
call print_nl mov edx,0
div ebx ; edx = edx:eax % ebx
cmp edx, 0
mov dword [Guess], 5 ; Guess = 5; je end_while_factor ; if !(guess % factor != 0)
23
While and Do Loops Quiz Mar 22
• DO loop (test at bottom) • Which of the following instructions do not affect the
do { flags. (Circle your answers)?
body of loop; MUL JMP MOV DEC PUSH JNAE
} while( condition )
segment .bss
24