machine-level programming ii: control flobadri/211dir/notes/w7-one.pdf · machine-level programming...
TRANSCRIPT
Machine-Level Programming II: Control Flow
l Topics
l Condition Codes l Setting l Testing
l Control Flow l If-then-else l While, for loop
Assembly programmer view
l ALU: Arithmetic Logic Unit l IR: Instruction register l GPR: General Purpose Registers l PC: Program Counter l SP: Stack Pointer l BR: Base Register
ALU
GPR
Status Flags
SP
PC Memory
Object Code Instructions & Data
IR
BR
Status flags l There are 1 bit flags or condition codes that are
set in a status register l ZF stands for zero flag l SF stands for sign flag l CF stands for carry flag (when borrow or
overflow occurs) – detect unsigned overflow l OF stands for overflow flag (when MSB change
occurs) – detect signed overflow l PF parity flag l AF auxiliary flag
Status flags (ZF or zero flag) l Status flags or condition codes are set when the
processor executes Arithmetic operations l ZF: Zero Flag is set to 1 if an operation results
in a zero l Example 1
l mov 0xFFFFFFFF %eax l add 1 %eax
l Example 2 l mov 1 %eax l dec %eax (decrements register by 1)
l Operations that set zero flag are: l cmp, inc, dec, sub, add etc
cmp operation l cmp Src, Dst
l Compares by subtracting Src from Dst l cmp op1, op2 l Compares two operands by subtracting op1 from op2 (op2-op1) l Sets the status flags based on the result l Does not alter op2 l Subtract operation or sub instruction stores the result in op2 l sub Src, Dst l Dst ß Dst- Src l sub op1, op2 op2-op1 result stored in op2
l move $5 %eax l cmp $5 %eax l %eax will still contain 5 but ZF will be set to 1 l move $5 %eax l sub $5 %eax l %eax will have 0 and ZF is set to 1
SF (Sign Flag) l As a result of arithmetic operation, the copy of
the sign bit is in SF l mov $5 %eax l sub $6 %eax l SF is set to 1
l If the number is positive, MSB is 0 then SF is set to 0 l mov $15 %eax l add $10 %eax l SF is set to 0
Carry flag (CF) l CF is set when a carry out or borrow in occurs
l mov ff,%al l add 00000001, %al
l Unsigned numbers l For 8 bits the range is 0 to 255 l For 16 bits the range is 0 to 65, 535 l For 32 bits the range is 32 bits 0 to 4, 294, 967, 295
l Result of an operation on unsigned numbers result in an overflow l mov $5, %eax l sub $6 %eax
l also sets CF – operation generates a borrow into MSB l Number is too small to be represented using signed numbers
Overflow flag (OF) l When a carry-in to or carry-out of “MSB” occurs– for signed
numbers l When signed numbers get out of range
l mov 0x72 %al l add 0x60 %al
l MSB in %al will be 1 a carry in has occurred l When you add two signed numbers, MSB will change if the result is out
of range l OF is set if there is a carry-in to MSB or carry-out of MSB l OF is set if MSB differs l OF is used to detect overflow for signed numbers
l Recall 2’s complement addition l Based on carry-in (OF) and carry out (CF) decide if the operation was in
error
How does the processor know?
l unsigned vs signed is not distinguished l Any number is just a binary number l Sets CF and OF based on carry in and carry
out l Left to implementation to interpret flags
accordingly
Compare instruction
l cmp o1, o2 or cmp Src, Dst l Sets flag based on the result of o2-o1 or Dst-
Src l Unlike sub operation, cmp does not change
the value of o2 or Dst
Setting Condition Codes
l Explicit setting by Compare Instruction cmpl Src, Dst l cmpl b,a like computing a-b without setting
destination l CF set if carry out from most significant bit or borrow into
MSB l Used for unsigned comparisons
l ZF set if a == b l SF set if (a-b) < 0 l OF set if two’s complement overflow
(a>0 && b<0 && (a-b)<0) || (a<0 && b>0 && (a-b)>0)
OF is used for signed comparisons
Setting Condition Codes (cont.)
l Explicit Setting by Test instruction testl Src2,Src1 (testb, testw for different word
sizes) l Sets condition codes based on value of Src1 &
Src2 l Useful to have one of the operands be a mask
l testl b,a like computing a&b without setting destination
l ZF set when a&b == 0 l SF set when a&b < 0 and ~SF a&b >0
Flags and operations l Assume x > y l cmp y,x is equivalent to checking result of x-y l Since x > y , x-y has to be positive and non-zero l Hence, SF=0 and ZF=0 and OF=0 l However, if SF=1 then overflow has occurred, i.e., OF=1 l If X > Y, then cmp y, x will result in ZF=0 and SF=OF l If X > Y, then ~ZF & ~(SF^OF) must be true l ^ symbol is for XOR , ~ is NOT, and & is AND … bitwise l jg needs to check if ~ZF & ~(SF^OF) is true
OF/CF for subtract operation l CF and OF are set l Borrow-in to MSB
l CF l OF because MSB changes
l Only OF flag is set l Borrow-out of MSB
l OF because MSB changes l Only CF is set l Borrow-in to MSB, borrow-out
of MSB l MSB does not change
MSB
MSB
MSB
OF/CF for add operation l CF and OF are set l carry-out of MSB
l CF l OF because MSB changes
l Only OF flag is set l carry-in to MSB
l OF because MSB changes l Only CF is set l Carry-out of MSB, carry-in to
MSB l MSB does not change
MSB
MSB
MSB
Example 8-bit numbers
l cmp 55, 56 l cmp -58, -56
l cmp -75, 56
Sub 00111000 00110111 ------------- 00000001
add 00111000 01001011 ------------- 10000011
SF=0 ZF=0 OF=0 CF=0
SF=0 ZF=0 OF=0 CF=0
sub 00111000 10110101 ------------- 10000011
SF=1 ZF=0 OF=1 CF=0
sub 11001000 11000110 ------------- 00000010
add 11001000 00111010 ------------- 00000010
S D0 to 255 unsigned -128 to 127 signed
Flags and operations l Assume x < y l cmp y,x is equivalent to checking result of x-y l Since x < y , x-y has to be negative and non-zero
l Hence, SF=1 and ZF=0 and OF=0 l However, if SF=0 then overflow has occurred, i.e.,
OF=1 l If x < y , then cmp y,x will result in ZF=0 and SF OF l Note: if X=Y, then ZF=1 and OF=SF=0
l Hence, we only need to check SF OF l If X < Y, then (SF^OF) must be true l ^ is XOR , … bitwise l Jl needs to check if (SF^OF) is true
≠≠
Example 8-bit numbers
l cmp 56, 55 l cmp -56, -58
l cmp 56, -75
Sub 00110111 00111000 ------------- 11111111
11000110 11001000 ------------- 11111110
SF=1 ZF=0 OF=0 CF=1
SF=1 ZF=0 OF=0 CF=1
10110101 00111000 ------------- 01111101
SF=0 ZF=0 OF=1 CF=1
Exercise: fill the entries cmp SF ZF CF OF
57,56
101, 200
200,101
100, 100
-‐124, -‐125
-‐125, -‐124
Reading Condition Codes
SetX Condition Description Sete D ZF Equal / Zero Setne D ~ZF Not Equal / Not Zero Sets D SF Negative Setns D ~SF Nonnegative Setg D ~(SF^OF)&~ZF Greater (Signed) Setge D ~(SF^OF) Greater or Equal (Signed) Setl D (SF^OF) Less (Signed) Setle D (SF^OF)|ZF Less or Equal (Signed) Seta D ~CF&~ZF Above (unsigned) Setb D CF Below (unsigned)
l SetX Instructions l Set single byte to (0 OR 1) based on combinations of condition
codes
Jmp Instruction l A JMP instruction forces the program counter to
point to the address specified in the instruction l jmp target l jmp (%edx) l edx contains 0080H
l After execution of jmp instruction the program counter or %eip points to contents of edx
l In other words, the program starts executing from that address
Jump Instructions
jX Condition Descriptionjmp 1 Unconditionalje ZF Equal / Zerojne ~ZF Not Equal / Not Zerojs SF Negativejns ~SF Nonnegativejg ~(SF^OF)&~ZF Greater (Signed)jge ~(SF^OF) Greater or Equal (Signed)jl (SF^OF) Less (Signed)jle (SF^OF)|ZF Less or Equal (Signed)ja ~CF&~ZF Above (unsigned)jb CF Below (unsigned)
l jX Instructions l Jump to different part of code depending on condition codes
Conditional jumps l Jcondition target l Can be used to implement control structures l Compare the while loop condition l While (something <>0 ) { statements} l Here we can use l beginwhile: cmp something, 0 l je endwhile l statements l jmp beginwhile l endwhile:
l If temp = 0 l Printf (“freezing \n”) We can use jne l Else l Printf (“notbad \n”);
cmp temp 0 jne elsepart Print freezing Jmp endif Elsepart: Print notbad Endif:
Conditional Branch Example
int max(int x, int y) { if (x > y) return x; else return y; }
_max: pushl %ebp movl %esp,%ebp
movl 8(%ebp),%edx movl 12(%ebp),%eax cmpl %eax,%edx jle L8 movl %edx,%eax
L8: movl %ebp,%esp popl %ebp ret
Body!
Set!Up!
Finish!
y x
x-y?
Return value in %eax
Conditional Branch Example II
int min(int x, int y) { if (x < y) return x; else return y; }
_min: pushl %ebp movl %esp,%ebp
movl 8(%ebp),%edx movl 12(%ebp),%eax cmpl %eax,%edx jge L8 movl %edx,%eax
L8: movl %ebp,%esp popl %ebp ret
Body!
Set!Up!
Finish!
y x
x-y?
Return value in %eax
Actual assembly code on x86 machine min: pushl %ebp movl %esp, %ebp subl $4, %esp movl 8(%ebp), %eax cmpl 12(%ebp), %eax jge .L2 movl 8(%ebp), %eax movl %eax, -4(%ebp) jmp .L3 .L2: movl 12(%ebp), %eax movl %eax, -4(%ebp) .L3: movl -4(%ebp), %eax leave ret
max: pushl %ebp movl %esp, %ebp subl $4, %esp movl 8(%ebp), %eax cmpl 12(%ebp), %eax jle .L2 movl 8(%ebp), %eax movl %eax, -4(%ebp) jmp .L3 .L2: movl 12(%ebp), %eax movl %eax, -4(%ebp) .L3: movl -4(%ebp), %eax leave ret
For loop
l Test l If test is true execute l For loop body l Update loop variable l Else exit
for (Init; Test; Update ) Body!
for (I=0; I < 211; i++ ){
Body}
mov $0 , %esi
startfor: cmp $211, %esi
jge exitfor
body
inc %esi
jmp startfor
Exitfor:
!
!
For loop: another implementation
l Jmp to Test l For loop l body l Update loop variable l Test: if true jmp to body
for (Init; Test; Update ) Body!
for (I=0; I < 211; i++ ){
Body} mov $0 , %esi
jmp fortest
startfor:
body
inc %esi
fortest: cmp $211, %esi
jl startfor
!!
Implementing for loop for (Init; Test; Update ) Body!
Init; while (Test ) { Body! Update ;!}
Goto Version!!
Init; if (!Test) goto done; loop: Body Update ; if (Test) goto loop; done:
While Version!!
For Version!!
Do-While Version!!
Init; if (!Test) goto done; do { Body! Update ; } while (Test)!done:
30
Machine-Level Programming III: Control Flow, Stack frame
l Topic
l Stack frames
31
Programs & Memory l The Von Neumann:
l programs & data are stored in memory
l Recall assembly code
converted to object code (Assembler)
l Labels are nothing more then address locations of instructions
l Here: mov %eax, %edx l … l jmp Here
instructions
global data
run-time heap
0x0000
0xFFFF Stack
32
IA32 Stack
l Region of memory managed with stack discipline
l Grows toward lower addresses
l Register %esp indicates lowest stack address l address of top element
l Push element on to stack l Pop the top most element
Stack!Pointer!%esp
Stack Grows!Towards heap!
Decreasing!Addresses!
Stack “Bottom”!
Stack “TOP”!
33
Use of stack l For storing return address of
calling procedure l When a procedure is called l Program needs to jump to the
starting address of the procedure
l After execution of the procedure, return to the next statement following the call statement
l CALL .. Push 0102 l RET … POP %eip
… main(){ …. 100: CALL myfunc() 102 …. } 500: void myfunc() { … }
102
… …. 100: push 102 jmp 500 102 …. } 500: { … RET }
%esp 996
34
%esp
%eip
%esp
%eip 0x804854e
0x108
0x108
0x104
0x100
0x804854e
123
Procedure Call Example
0x108
0x104
0x100
123
0x108
call 8048b90
804854e: e8 3d 06 00 00 call 8048b90 <main> 8048553: 03 add …
0x8048b90
0x104
%eip is program counter
0x8048553
35
Procedure Control Flow
l Use stack to support procedure call and return l Procedure call:
call label Push return address on stack; Jump to label l Return address value
l Address of instruction beyond call l Example from disassembly 804854e: e8 3d 06 00 00 call 8048b90 <main> 8048553: 08 add …
l Return address = 0x8048553 l Procedure return:
l ret Pop address from stack; Jump to address
36
Nested procedures l On each call, push the return
address on stack l On RET, pop the address to
return from the innermost procedure call
l RET à pop %eip
… main(){ …. 100: myfunc() 102 …. } 500: void myfunc() { 580: otherfunc() } 800: void otherfunc() 104
… …. 100: push 104 jmp 500 104 …. } 500: { push 584 jmp 800 584: … RET } 800: { }…RET
584
STACK
Stack!Pointer!%esp
-4!1028
1020
X
1024
37
Passing parameters l What if the procedure has
parameters? l Use stack to store the values l First,
l Push parameters onto stack l Where are the parameters? l %esp + 4, %esp + 8 l %esp points to top of stack l Second, Push return address l Top of stack still contains the
return address
… main(){ …. 100: myfunc(3,5) 102 …. } 500: void myfunc(int x, int y) { … }
108
… …. 100: push $3 push $5 104 jmp 500 108 …. } 500: { … RET }
$5 $3
Stack!Pointer!%esp
92
96
100
38
Locating Parameters? … main(){ …. 100: myfunc(3,5) 108 …. } 500: void myfunc(int x, int y) { 700 otherfunc(8) 702 …. RET } 800: void otherfunc(int z) { …. RET }
108
$3 $5
Stack!Pointer!%esp
92
96
100
What happens on RET from the innermost procedure? Pop decrements stack pointer Because of parameters on stack, one POP does not point to the right location for the next level of the call sequence!! %esp +4, %esp +8 Need to remember where the last call stack was
? $8
84
88
702
39
Stack frames l To preserve the offset for parameters for every
called procedure l maintain another register called frame pointer
l %ebp is the frame pointer l Every time a procedure is entered
l push %ebp old frame pointer on to stack l mov %esp, %ebp l %ebp points to current SP
l When executing within myfunc l %ebp? %esp? l %ebp+8?, %ebp+12?
$3 $5
Stack!Pointer!%esp
92
96
100
104 88
84
80 Frame!Pointer!%ebp!
76
108
40
Stack frames l When myfunc calls otherfunc() l Push parameters and return
address on stack l Before entering otherfunc()
l push %ebp old frame pointer l mov %esp ,%ebp l %ebp points to current SP
l When executing within otherfunc() l %ebp? %esp? l %ebp+8?
l On RET (clean up) l mov %ebp, %esp l pop %ebp
$5 $3
%esp %ebp
92
96
100
104
702
88
84
80
$8
88 76
108
%esp %ebp
}
%esp
41
What about local variables within procedures?
l Also goes on stack! l The called procedure pushes local
variables onto stack l Where are the parameters? l %ebp + 8, %ebp + 12 l Where are the local variables? l %ebp-4, %ebp-8, … l z is a local variable in myfunc()
108
$5 $3
Stack!Pointer!%esp
92
96
100
104
Frame!Pointer!%ebp!
88
48
… main(){ …. 100: myfunc(3,5) 102 …. } 500: void myfunc(int x, int y) {int z[9]; z[0]=x+y; … }
z[0] z[1]
z[9]
42
Stack is used for local variables l z[0] is stored in -40(%ebp) l On RET from myfunc l Clean up or LEAVE l On RET (clean up)
l mov %ebp, %esp l pop %ebp
… main(){ …. 100: myfunc(3,5) 102 …. } 500: void myfunc(int x, int y) {int z[9]; z[0]=x+y; … }
… …. 100: push $3 push $5 104 jmp 500 108 …. } 500: { mov 8 (%ebp), %eax add 12 (%ebp), %eax mov %eax, -40 (%ebp) … RET }
Stack Frame
l Stack has one stack frame per activation l ESP points to top of current stack frame l EBP points to bottom of current stack frame l Stack Frame stores
l Return address l Old call frame pointer l Parameters l Local variables
43
44
Cleaning the stack of arguments l After mov %ebp, %esp l pop %ebp l RET instruction l pop %eip l %eip will point to the return
address l %esp is still pointing to the
arument stack of the previous frame
l Two ways to clean up 108
$5 $3
92
96
100
104 88
48
%esp!
%ebp!
45
Cleaning the stack of arguments
l Cleaning done by the called procedure l Use RET n instructions l RET n è pop %eip, and add %esp, $n l Called procedure needs to know the size of the
argument l Cleaning done by the calling procedure l After returning from the procedure l addl sizeofargument, %esp
46
main() { int x=1; int y=2; int z; z=f(x,y); } int f(int arg1, int arg2) { return arg1+ arg2; }
Sample program, call stack main: leal 4(%esp), %ecx andl $-16, %esp pushl -4(%ecx) pushl %ebp movl %esp, %ebp pushl %ecx subl $36, %esp movl $1, -16(%ebp) movl $2, -12(%ebp) movl -12(%ebp), %eax movl %eax, 4(%esp) movl -16(%ebp), %eax movl %eax, (%esp) call f movl %eax, -8(%ebp) addl $36, %esp popl %ecx popl %ebp leal -4(%ecx), %esp ret
47
Procedure call stack
f: pushl %ebp movl %esp, %ebp movl 12(%ebp), %eax addl 8(%ebp), %eax popl %ebp ret