본문 바로가기
컴퓨터/컴퓨터구조

[UCB CS61C] Lec10 RISC-V Memory and Calling Conventions

by 봄여름가을 2024. 1. 9.

Machine Program

  • Program Counter는 processor 내에 위치하는 레지스터로서, 다음 instruction의 byte address를 보관함.
  • 보통은 다음 instruction을 찾기 위해 4 bytes를 더한다.
  • 32개의 레지스터 중 일부는 symbolic register name을 갖는다. e.g. zero(x0), a0-a7(x10-x17; 즉 argument registers for function calls)
  • pseudo-instructions: 실제 instruction이 아니라 자주 사용되는 것을 ㅈ간단히 표현하는 것임. e.g. (move) mv rd, rs = addi rd, rs, 0, (load immediate) li rd, 13 = addi rd, x0, 13, (no operation) nop = addi x0, x0, 0

Function Calls

  • 함수를 부르는 절차는 다음으로 구성된다.
  • argument를 준비
  • transfer control to function
  • acquire storage for function
  • perform the task of function
  • return value를 준비
  • return control
  • RISC-V Calling Conventions
  • a0-a7(x10-x17): 8 argument registers
  • ra: return address(x1)
  • s0-s1(x8-x9), s2-s11(x18-x27): saved registers
  • jr은 함수가 끝날 때 다시 ra의 위치로 돌아오는 데 사용함. 여기서는 j을 사용하지 않음. 왜냐하면 jump는 address의 값을 직접 넣기를 요구하는데, 함수는 그런 식으로 사용되지 않기 때문에 register를 넣을 수 있는 jr을 사용함. e.g. jr ra
  • ret = jr ra이라는 pseudo instruction으로 할 수도 있음.
  • jal(jump and link): 함수로 갈 때 자주 사용되는 jump and save return address를 한번에 해준다. e.g. jal sum
  • 진실: 사실은 jaljalr만 있다.
  • jal rd, Label: jump and link
  • jalr rd, rs, imm: jump and link register
  • j: jal x0, Label
  • jr: jalr x0, x1, 0
  • function call을 하는 동안 기존의 register값들을 어딘가에 저장해 두어야 함. 이를 위해서 stack을 이용하는데, stack은 레지스터가 아닌 메모리 상에 있기 때문에 이를 point하기 위한 레지스터가 필요함.
  • sp가 바로 stack pointer로 x2에 있음. stack은 높은 주소에서 낮은 주소로 쌓이기 때문에, Push하면 sp를 감소하고, Pop하면 sp를 증가시킨다.
# prologue
addi sp, sp, -8 # stack for 2 items
sw s1, 4(sp) # save s1 for use afterwards
sw s0, 0(sp)

add s0, a0, a1
add s1, a2, a3
sub a0, s0, s1

# epilogue
lw s0, 0(sp) # restore register
lw s1, 4(sp) 
addi sp, sp, 8

jr ra

Nested Calls and Register Conventions

  • caller vs. callee
  • register를 두 가지로 나눔
  • function call 동안 계속 변하지 않고 보존되는 레지스터들: sp, gp, tp, s0-s11(saved registers)
  • 보존되지 않는 레지스터들: a0-a7(argument registers), ra(return address), t0-t6(temporaries)
int sumSquare(int x, int y) {
  return mult(x, x) + y;
}

// 위 함수에 대한 어셈블리
sumSquare:
addi sp, sp, -8 # stack pointer 이동
sw ra, 4(sp) # save return address
sw a1, 0(sp) # save y. a1 was containing y
mv a1, a0 # argument for mult(x, x). a0 contains x
jal mult # call mult
lw a1, 0(sp) # restore y
add a0, a0, a1 # mult() + y operation
lw ra, 4(sp) # get return address
addi sp, sp, 8 # restore stack pointer
jr ra

Memory

  • RV32에서는 text segment(program)가 가장 low end(0001_0000), static data segment(constants, static variables)가 그 다음(1000_0000), heap은 작은 데서 큰 데로 자라고, stack은 큰 데서 작은 데로 자란다.

댓글