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 retq

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?

  1. pops the latest value from the stack
  2. 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.

  1. Write an interpreter for x86Lite.
  2. Read the specification.
  3. Syntax is already defined.
  4. State needs to store: Heap, Stack, registers

Build a quickcheck lib in ocaml which is embeddable.

  1. provide example program
  2. 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:

  1. caller save - freely usable by the called code. Moves values from register to memory, usually by pushing them onto the stack.
  2. callee save - restored by called code.

Define protocol for dealloc stack-alloc args:

  1. caller cleans up during runtime caller always knows how many arguments were used.
  2. 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:

  1. if 6 or less arguments, must be stored in registers. in order: rdi, rsi,rdx, rcx, r8, r9

  2. if more than 6 arguments: stack: arg7 arg8 … %rbp preserve the order, so arg7 is on the top of stack.

  3. 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

  1. stack: old %rbp lret arg7 arg8 … old %rbp

  2. we allocate 128 bytes of scratch stack space stack: stack: <128-bytes> old-%rbp lret arg7 arg8 … old %rbp

  3. Callee save registers: %rbp, %rbx, or %12-%r15

  4. movq ANS, %rax - return value

  5. addq $128, %rsp - erase scratch space -> store in %rip

  6. popq %rbp - pop the old %rbp, store it to %rbp

  7. retq - pop the location stored on top of the stack, writes it into %rip

  8. once this is done, f has result of g in %rax

  9. 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.