上来直接:
$ cd xv6-riscv-fall19
$ git checkout syscall
这块要回答几个问题,打开 user/call.c
和 user/call.asm
,有如下代码片段:
int g(int x) {
return x+3;
}
int f(int x) {
return g(x);
}
void main(void) {
printf("%d %d\n", f(8)+1, 13);
exit(0);
}
000000000000001c <main>:
void main(void) {
1c: 1141 addi sp,sp,-16
1e: e406 sd ra,8(sp)
20: e022 sd s0,0(sp)
22: 0800 addi s0,sp,16
printf("%d %d\n", f(8)+1, 13);
24: 4635 li a2,13 ; printf("%d %d\n", f(8)+1, 13);
26: 45b1 li a1,12
28: 00000517 auipc a0,0x0
2c: 75050513 addi a0,a0,1872 # 778 <malloc+0xea>
30: 00000097 auipc ra,0x0
34: 5a0080e7 jalr 1440(ra) # 5d0 <printf>
exit(0);
38: 4501 li a0,0
3a: 00000097 auipc ra,0x0
3e: 1fe080e7 jalr 510(ra) # 238 <exit>
... lines omitted
00000000000005d0 <printf>:
void
printf(const char *fmt, ...)
{
....
下面来回答问题:
doc/riscv-calling.pdf
) , a0-a7 和 fa0-fa7 共计 16 个寄存器会用于传递参数13
f(8)+1 = 12
,又发现 main 中并为调用 f 函数,说明 f 在编译期被直接优化成一个常量 12
塞到 a1 寄存器里了。auipc ra,0x0
和 jalr 1440(ra)
,前者取当前指令的 pc 加上 0x0 存入 ra,后者跳转到 ra + 1440。计算知 0x0000000000000030 + 1440 = 0x00000000000005d0
。经验证是 printf 的入口地址。jalr
指令完成后,ra
寄存器会存储返回点位置(也即 pc + 4 )MIT 6.828 - 6. Lab 06: User-level Threads and Alarm
原文:https://www.cnblogs.com/nlp-in-shell/p/12178015.html