YSC4230 Lecture 3
What is ~$
?
.text
.globl program
program:
movq $6, %rdi
movq $1, %rsi
callq fac
retq
.text
fac:
movq %rsi, %rax
cmpq $1, %rdi
je exit
imulq %rdi, %rsi
decq %rdi
callq fac
.text
exit:
retq
[rdi, rsi, rax] [6, 1, 1]
mem | |
---|---|
stack |
8bytes between each memory location
callq fac allows us to go to retq tells us where to resume
What happens when we have:
callq fac
subsequent callq fac recursive calls push more things onto the stack.
How can we see this for ourselves wrt to the stack?
how does retq work?
- pops the latest value from the stack
- loads address from this value
.text
.globl program
program:
movq $6, %rdi
movq $1, %rsi
callq fac
retq
.text
fac:
movq %rsi, %rax
cmpq $1, %rdi
je exit
imulq %rdi, %rsi
decq %rdi
callq fac
.text
exit:
retq
optimized
.text
.globl program # exposes this for importing
program:
movq $1, %rax
movq $6, %rdi
.text
fac:
cmpq $1, %rdi
je exit
imulq %rdi, %rax
decq %rdi
jmp loop
.text
exit:
retq
Homework will be dealing with X86lite.
- Write an interpreter for x86Lite.
- Read the specification.
- Syntax is already defined.
- State needs to store: Heap, Stack, registers
Build a quickcheck lib in ocaml which is embeddable.
- provide example program
- Implement an array in asm program
What is stack for?
Stores local vars. stores return addr of function.
Need space to store:
- Global variables -> data segment
- Values -> stack
- Local variables registers (small 64-bits, limited 16) memory (stack, need to cache, won’t run out of space 2GB)
Calling conventions
Where do we locate arguments passed to function / returned by the function.
Where do we store return result?
We follow the convention that we store in rax
. See prog.s
What is a caller and callee?
f() {
...
g()
}
f is caller, g is callee
How to designate registers for caller, callees?
Designate registers either:
- caller save - freely usable by the called code. Moves values from register to memory, usually by pushing them onto the stack.
- callee save - restored by called code.
Define protocol for dealloc stack-alloc args:
- caller cleans up during runtime caller always knows how many arguments were used.
- callee cleans up (makes variable number args harder)
What is a stack frame?
Space in the stack stored between 2 pointers. rsp top of stack frame. rbp points to bottom of stack frame. Partition stack space into territory used by different functions.
Call instruction convention
f: … callq g
lret:
if 6 or less arguments, must be stored in registers. in order: rdi, rsi,rdx, rcx, r8, r9
if more than 6 arguments: stack: arg7 arg8 … %rbp preserve the order, so arg7 is on the top of stack.
To execute the call
callq g
: a. push the return address onto the stack stack: lret arg7 arg8
g: pushq %rbp movq %rsp, %rbp subq $128, %rsp
stack: old %rbp lret arg7 arg8 … old %rbp
we allocate 128 bytes of scratch stack space stack: stack: <128-bytes> old-%rbp lret arg7 arg8 … old %rbp
Callee save registers: %rbp, %rbx, or %12-%r15
movq ANS, %rax - return value
addq $128, %rsp - erase scratch space -> store in %rip
popq %rbp - pop the old %rbp, store it to %rbp
retq - pop the location stored on top of the stack, writes it into %rip
once this is done, f has result of g in %rax
f should cleanup its stack as needed now.
How callee know how many arguments there are?
Compiler can see the argument numbers. So it will statically compile the rbp.
compile.md
Take the compiled programs, pass them into calculator.c
nanopass
my first 15 compilers.