lecture 8: control, procedures, and the stack cs 2011 fall 2014, dr. rozier
TRANSCRIPT
Lecture 8: Control, Procedures, and the Stack
CS 2011
Fall 2014, Dr. Rozier
MIDTERM I
Midterm I
Median: C-
Midterm I
Median: B-
GDB: THE GNU DEBUGGER
gdb: The GNU Debugger
• Standard and portable debugger for Unix and Unix-like systems.– Originally written in 1986– Very active tool. Three software releases in 2013.– Still the gold-standard for debugging
• Enables users to trace, alter, and execute computer programs in a controlled environment.
gdb: The GNU Debugger
• Most useful features– Step through program execution, line by line, or
instruction by instruction.– Examine the values of variables and registers.– Trap system signals.– Set breakpoints to halt execution at any point.– Watch variables to see when they change.
gdb: The GNU Debugger
• Some commands– run – executes the program– break <NAME> - sets a breakpoint at label
<NAME>– break *<ADDRESS> - sets a breakpoint at the
address <ADDRESS>– print <REGISTER> - prints the register’s value– stepi – step through one assembly instruction
gdb: The GNU Debugger
• Some commands– disas <NAME> - disassemble the code at label <NAME>.– continue – continue execution after halting at a
breakpoint.– info [break|<REGISTER>] - give information about
breakpoints or registers– info r – display the value of all registers– x/<FMT> <ADDRESS|REGISTER> - display the value
stored at <ADDRESS|REGISTER> in the format specified by <FMT>
gdb: The GNU Debugger
We will show an example next Tuesday of the debugger in action.
CONTROL
Implementing Loop Statements
• C code:while (i < j) i += 1;
• ARM code Loop:
cmp r0, r1bge Exitadd r0, r0, #1bal Loop
Exit:
i < j?i < j?
i=i+1i=i+1
i<j
ExitExit
i>=j
Basic Blocks• A basic block is a sequence of instructions with
– No embedded branches (except at end)– No branch targets (except at beginning)
A compiler identifies basic blocks for optimization
An advanced processor can accelerate execution of basic blocks
What about a Case Statement?
• Say we have a case statement:switch(x) {
case 0: foo(); break;case 1: bar(); break;case 2: baz(); break;case 3: qux(); break;
}
Jump Tables
• Set up a portion of memory as such:
• If our case variable is stored in r0…– r0 << #2 is the index into our jump table of the
function address.
Memory Location Contents
0x???? + 0 address of foo
0x???? + 4 address of bar
0x???? + 8 address of baz
0x???? + 12 address of qux
Cases Statements as Jump Tables
(assume r0 holds the switch variable)
ldr r1, =jumptableldr pc, [r1, r0, lsl #2]
Wasn’t that easy?
Pseudo-Instructions
• Notice the use of:– ldr r0, =jumptable
• What is really going on here?
Hello World
string: .asciiz "Hello World!\n";
ldr r1, =string
swi 0
mov r7, #1
swi 0
Pseudo-Instructions
Code as we wrote it:
Disasembled code:
ldr r1, =string
swi 0
mov r7, #1
swi 0
0x8080 ldr r1, [pc, #8]
0x8084 svc 0x0
0x8088 mov r7 #1
0x808c svc 0x0
0x8090 muleq r1 r4 r0
This is weird…
• Let’s play with gdb…x/x 0x80900x8090 <_exit+8>: 0x00010094x/x 0x100940x10094 <string>: “Hello World!\nA\025”
So why does it show up as muleq?
• Representing instructions
– Condition Field• 0000 – EQ
– 0000 | 000000 | 0 | 0 |????|????|????| 1001|????
mul r1, r4, r0mul{<cond>}{S} rd, rm, rs
Cond 000000 A S Rd Rn Rs 1001 Rm
Instruc 0000 000000 0 0 ???? ???? ???? 1001 ????
Hex 0 0 0 1 0 0 9 4
Bin 0000 0000 0000 0001 0000 0000 1001 0100
So why does it show up as muleq?
• Representing instructions
mul r1, r4, r0mul{<cond>}{S} rd, rm, rsmul 0001, 0100, 0000
Cond 000000 A S Rd Rn Rs 1001 Rm
Instruc 0000 000000 0 0 ???? ???? ???? 1001 ????
Hex 0 0 0 1 0 0 9 4
Bin 0000 0000 0000 0001 0000 0000 1001 0100
So what is this?
Code as we wrote it:
Disasembled code:
ldr r1, =string
swi 0
mov r7, #1
swi 0
0x8080 ldr r1, [pc, #8]
0x8084 svc 0x0
0x8088 mov r7 #1
0x808c svc 0x0
0x8090 muleq r1 r4 r0
The problem with immediates
• The fact that instructions, AND all their arguments, must take up only 32 bits limits the size of immediates to 1 byte.– Range 0 – 255.– Hello world was in 0x10094– PC was at 0x8088– Max offset with immediate value?
• 0x8088 + 0xFF = 0x8187
Enter, the Literal Pool0x8080 ldr r1, [pc, #8]
0x8084 svc 0x0
0x8088 mov r7 #1
0x808c svc 0x0
0x8090 00 01 00 94
Last instruction in basic block
Literal Pool
PROCEDURES
Basic BlocksA basic block is a sequence of instructions with
No embedded branches (except at end)No branch targets (except at beginning)
A compiler identifies basic blocks for optimization
An advanced processor can accelerate execution of basic blocks
A Call Chain
Image by David Thomas
Procedure Calling
1. Place parameters for procedure in registers2. Transfer control to procedure3. Procedure acquires storage4. Procedure performs function.5. Procedure places return value in appropriate
register6. Return control
The Stack
• Region of memory managed with stack discipline.
• Accessed with pushand pop
The Stack
Stack Frames
• Stack frames “belong” to a procedure.
• Store local variables here (they go out of scope automatically)
• Can communicate with other procedures with a stack frame.
Procedures and Register Use
• What if we want to use some registers in the procedure?
• Caller could have data in it!
Stack Discipline and ABI
• Stack Discipline is important
• Define an Application Binary Interface– How should procedures communicate? How
should the be called?
• Consistency, following standards, is the key.
Conventions and Discipline
Caller• Caller saves temporary
values in its frame before the call.
• Caller restores values in its frame after the call.
Callee• Callee saves temporary
values in its frame before using.
• Callee restores values in its frame after using.
Stack Frames
• Contents– Local variables– Return information– Temporary space
• Management– Space is allocated when entering
• Set-up code
– Deallocated when returning• Finish code
Frame Pointer
Stack Pointer
Examplefoo(){ … bar() …}
foo(){ … bar() …}
foofooframe ptrframe ptr
stack ptrstack ptr
foo()
Examplefoo(){ … bar() …}
foo(){ … bar() …}
foofoo
frame ptrframe ptr
stack ptrstack ptr
foo()
bar(){ …baz…baz() …}
bar(){ …baz…baz() …}
barbar
bar()
Examplefoo(){ … bar() …}
foo(){ … bar() …}
foofoo
frame ptrframe ptr
stack ptrstack ptr
foo()
bar(){ …baz…baz() …}
bar(){ …baz…baz() …}
barbar
bar()
baz(){…baz()…}
baz(){…baz()…}
bazbaz
baz()
Examplefoo(){ … bar() …}
foo(){ … bar() …}
foofoo
frame ptrframe ptr
stack ptrstack ptr
foo()
bar(){ …baz…baz() …}
bar(){ …baz…baz() …}
barbar
bar()
baz(){…baz()…}
baz(){…baz()…}
bazbaz
baz()
baz(){…baz()…}
baz(){…baz()…}
bazbaz
baz()
Examplefoo(){ … bar() …}
foo(){ … bar() …}
foofoo
frame ptrframe ptr
stack ptrstack ptr
foo()
bar(){ …baz…baz() …}
bar(){ …baz…baz() …}
barbar
bar()
baz(){…baz()…}
baz(){…baz()…}
bazbaz
baz()
baz(){…baz()…}
baz(){…baz()…}
bazbaz
baz()
baz(){…baz()…}
baz(){…baz()…}
bazbaz
baz()
Examplefoo(){ … bar() …}
foo(){ … bar() …}
foofoo
frame ptrframe ptr
stack ptrstack ptr
foo()
bar(){ …baz…baz() …}
bar(){ …baz…baz() …}
barbar
bar()
baz(){…baz()…}
baz(){…baz()…}
bazbaz
baz()
baz(){…baz()…}
baz(){…baz()…}
bazbaz
baz() baz()
Examplefoo(){ … bar() …}
foo(){ … bar() …}
foofoo
frame ptrframe ptr
stack ptrstack ptr
foo()
bar(){ …baz…baz() …}
bar(){ …baz…baz() …}
barbar
bar()
baz(){…baz()…}
baz(){…baz()…}
bazbaz
baz() baz() baz()
Examplefoo(){ … bar() …}
foo(){ … bar() …}
foofoo
frame ptrframe ptr
stack ptrstack ptr
foo()
bar(){ …baz…baz() …}
bar(){ …baz…baz() …}
barbar
bar() baz() baz() baz()
Examplefoo(){ … bar() …}
foo(){ … bar() …}
foofoo
frame ptrframe ptr
stack ptrstack ptr
foo()
bar(){ …baz…baz() …}
bar(){ …baz…baz() …}
barbar
bar()
baz(){…baz()…}
baz(){…baz()…}
bazbaz
baz() baz() baz()
baz()
Examplefoo(){ … bar() …}
foo(){ … bar() …}
foofoo
frame ptrframe ptr
stack ptrstack ptr
foo()
bar(){ …baz…baz() …}
bar(){ …baz…baz() …}
barbar
bar() baz() baz() baz()
baz()
Examplefoo(){ … bar() …}
foo(){ … bar() …}
foofooframe ptrframe ptr
stack ptrstack ptr
foo() bar() baz() baz() baz()
baz()
What is the frame pointer used for?
• Given a caller and a callee, the callee will begin with:– fp = sp
• A callee will use the stack to:– Save the current sp, lr, and fp before calling a function– Store the arguments for, and return value space
before calling a function– Save used registers before calling a function– Store variables local to the procedure
Frame pointerfoofoo
frame ptrframe ptrstack ptrstack ptr
Frame pointerfoofoo
frame ptrframe ptr
stack ptrstack ptra = 0x00a = 0x00
PUSH
Frame pointerfoofoo
frame ptrframe ptr
stack ptrstack ptr
a = 0x00a = 0x00
b = 0xFCb = 0xFC
PUSH
Frame pointerfoofoo
frame ptrframe ptr
stack ptrstack ptr
a = 0x00a = 0x00
b = 0xFCb = 0xFC
PUSH c = 0x87c = 0x87
Frame pointerfoofoo
frame ptrframe ptr
stack ptrstack ptr
a = 0x00a = 0x00
b = 0xFCb = 0xFC
PREPARETO CALL
c = 0x87c = 0x87
Frame pointerfoofoo
frame ptrframe ptr
stack ptrstack ptr
a = 0x00a = 0x00
b = 0xFCb = 0xFC
PUSH c = 0x87c = 0x87
r0r0
lrlr
fpfp
a0a0
retret
Frame pointerfoofoo
stack ptrstack ptr
a = 0x00a = 0x00
b = 0xFCb = 0xFC
RETURNFROMCALL
c = 0x87c = 0x87
r0r0
lrlr
fpfp
a0a0
retret
Frame pointerfoofoo
frame ptrframe ptr
stack ptrstack ptr
a = 0x00a = 0x00
b = 0xFCb = 0xFC
POP! c = 0x87c = 0x87
Frame pointerfoofoo
frame ptrframe ptr
stack ptrstack ptr
a = 0x00a = 0x00
b = 0xFCb = 0xFC
c = 0x87c = 0x87
+4
+8
+12
Frame pointer
• The frame pointer gives usa base address from which tooffset in our frame for localstorage that will automatically go out of scope.
foofoo
frame ptrframe ptr
stack ptrstack ptr
a = 0x00a = 0x00
b = 0xFCb = 0xFC
c = 0x87c = 0x87
+4
+8
+12
Recursionfoo(){ … bar() …}
foo(){ … bar() …}
foofoo
frame ptrframe ptr
stack ptrstack ptr
foo()
bar(){ …baz…baz() …}
bar(){ …baz…baz() …}
barbar
bar()
baz(){…baz()…}
baz(){…baz()…}
bazbaz
baz()
baz(){…baz()…}
baz(){…baz()…}
bazbaz
baz()
baz(){…baz()…}
baz(){…baz()…}
bazbaz
baz()
Recursion
• Stack frames give each function private storage– Saved registers– Local variables– Return portions
• Recursion is handled without special consideration.
• Following stack discipline and call/return pattern is critical
PUSH and POP
• PUSH<cond> {reglist} • POP<cond> {reglist}
• Really pseudo-instructions!
• PUSH – STMDB• Store multiple registers, decrement address before
access.• POP – LDMIA
• Load multiple registers, increment address after access.
Multiple Ways to Handle the Stack
• Stack Pointer can– Point to the last occupied stack (Full stack)
• (needs pre-decrementing)– Point to the next address to be occupied (Empty stack)
• (needs post-decrementing)• Stack type can be given as a postfix to the instruction:
– STMFD/LDMFD– STMFA/LDMFA– STMED/LDMED– STMEA/LDMEA
RISC Mentality
• There are no special functions for stacks!
• Let’s look at stack instructions:– STMDA/LDMDA
Single Data Transfer
• Interpreting– Cond – 4 bits, condition field– I – immediate offset– Pre/post indexing bit (add offset before(0)/after(1) transfer)– Up/down bit (subtract(0)/add(1) offset to base– Byte/word bit (transfer word(0)/byte(1))– Write-back bit (1 to write address back into base)– Load store bit (0 store to memory, 1 load from memory)– Rn – base register– Rd – source/destination register
CONDCOND 0101 II PP UU BB WW LL RnRn RdRd OffsetOffset
Single Data Transfer
• Interpreting– Cond – 4 bits, condition field– I – immediate offset
• 1 – offset is immediate
CONDCOND 0101 II PP UU BB WW LL RnRn RdRd OffsetOffset
Single Data Transfer
• Interpreting– Cond – 4 bits, condition field– I – immediate offset
• 0 – offset is register
CONDCOND 0101 II PP UU BB WW LL RnRn RdRd OffsetOffset
RmRmShiftShift
Block Data Transfer
• Interpreting– Cond – 4 bits, condition field– I – immediate offset– Pre/post indexing bit (add offset before(0)/after(1) transfer)– Up/down bit (subtract(0)/add(1) offset to base– PSR & force user bit (0 do not load PSR or force user mode, 1 load PSR
and force user mode)– Write-back bit (1 to write address back into base)– Load store bit (0 store to memory, 1 load from memory)– Rn – base register– Register List
CONDCOND 100100 PP UU SS WW LL RnRn Register ListRegister List
LDR/STR LDM/STM
• Load or Store single, or multiple
• Write back, W-bit– ldr Rd, [Rn, Offset]– ldr Rd!, [Rn, Offset]
Block Data Transfer
• Register list, how to implement?– 16 bit field
CONDCOND 100100 PP UU SS WW LL RnRn Register ListRegister List
For next time
MP1, more on the stack