CS61C | Lecture 7

Lecture 7

Change C language To RISC-V

Ex.1

char *p, *q;
while((*q++ = *p ++) != '\0');
p->s0, q->s1
t0 = *p
*q = t0
p = p + 1
q = q + 1
if *p == 0, go to Exit
go to Loop
Loop: lb    t0, 0(s0)
	  sb    t0, 0(s1)
	  addi  s0, s0, 1
	  addi  s1, s1, 1
	  beq   t0, x0, Exit
	  j     Loop
Exit:

Ex.2

int A[20];
int sum = 0;
for(int i = 0; i < 20; i ++) 
	sum += A[i];
	add   x9, x8, x0     # x9 = &A[0]
	add   x10, x0, x0    # sum
	add   x11, x0, x0    # i
	addi  x13, x0, 20    # x13
Loop:
	bge   x11, x13, Done
	lw    x12, 0(x9)     # x12 A[i]
	add   x10, x10, x12  # sum
	addi  x9, x9, 4      # &A[i + 1]
	addi  x11, x11, 1    # i ++
	j Loop
Done:

一些更短的指令

mv rd, rs = addi rd, rs, 0
li rd, 13 = addi rd, x0, 13
nop       = addi x0, x0, 0    # 无操作

Functions

jump register(jr)

address (shown in decimal)
1000 mv a0, s0           # x = a
1004 mv a1, s1           # y = b
1008 addi ra, zero, 1016 # ra = 1016
1012 j sum               # jump to sum
1016 ...
...
2000 sum: add a0, a0, a1
2004 jr ra

以上代码为什么使用 jr 而不是 j 是因为 sum 函数可能会在很多地方被调用,我们无法返回到一个固定的位置,所以必须要用 jr 来指定返回的位置。

jump and link(jal)

Single instruction to jump and save return address.

# Before
1008 addi ra, zero, 1016  # ra = 1016
1012 j sum                # goto sum

# After
1008 jal sum # ra = 1012, goto sum
jal  rd, Label   jump and link
jalr 

函数调用的一些步骤

int Leaf(int g, int h, int i, int j)
{
	int f;
	f = (g + h) - (i + j);
	return f;
}

g, h, i, j 分别存储在 a0, a1, a2, a3
f 存储在 s0
我们需要在调用函数之前存储旧的值,由于我们通常没有足够的寄存器来处理每个函数调用,所以将它们存储在内存中的 stack(LIFO)。
Stack 有两个操作:
Push: placing data onto stack
Pop: removing data from stack

由于 Stack 在内存中,所以需要有寄存器来指向它,也就是 sp(stack pointer),在 RISC-V 中,存储在 x2 寄存器中。

Stack frame

堆栈帧包含:
1.Return “instruction” address
2.Parameters (arguments)
3.Space for other local variables

Leaf:   
		# prologue
		addi sp, sp, -8  # adjust stack for 2 items
		sw   s1, 4(sp)   # save s1 for use afterwards
		sw   s0, 0(sp)   # save s0 for use afterwards

		add  s0, a0, a1  # f = g + h
		add  s1, a2, a3  # s1 = i + j
		sub  a0, s0, s1  # return value (g + h) - (i + j)

		# epilogue
		lw   s0, 0(sp)   # restore register s0 for caller
		lw   s1, 4(sp)   # restore register s1 for caller
		addi sp, sp, 8   # adjust stack to delete 2 items
		jr   ra          # jump back to calling routine

该函数调用前、中、后栈帧与 sp 变化

Saved registers: s0 - s11
易失性或临时存储器:
Argument/return registers: a0 - a7, ra
Temporary registers: t0 - t6

RegisterABI NameDescriptionSaver
x0zeroHard-wired zero-
x1raReturn addressCaller
x2spSatck pointerCallee
x3gpGlobal pointer-
x4tpThread pointer-
x5t0Temporary / Alternate link registerCaller
x6-7t1-2TemporariesCaller
x8s0/fpSaved register / Frame pointerCallee
x9s1Saved registerCallee
x10-11a0-1Function arguments / Return valuesCaller
x12-17a2-7Function argumentsCaller
x18-27s2-11Saved registersCallee
x28-31t3-6TemporariesCaller
其中,Caller 是调用函数,而 Callee 是被调用函数。
int sumSquare(int x, int y) {
	return mult(x, x) + y;
}
sumSquare:
	addi  sp, sp, -8   # space on stack (push)
	sw    ra, 4(sp)    # save ret addr  (push)
	sw    a1, 0(sp)    # save y         (push)
	mv    a1, a0       # mult(x, x)
	jal   mult         # call mult
	lw    a1, 0(sp)    # restore y      (pop)
	add   a0, a0, a1   # mult() + y
	lw    ra, 4(sp)    # get ret addr   (pop)
	addi  sp, sp, 8    # restore stack  (pop)
	jr    ra
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值