代码:https://github.com/RedemptionC/xv6-riscv-6s081/tree/syscall
warm up
(对riscv汇编的熟悉,其实使用gdb调试汇编是”最好“的学习方法)
回答一下几个问题:
Which registers contain arguments to functions? For example, whichregister holds 13 in main's call to printf?
这个很简单,从call.asm就能看出来,是a2
printf("%d %d\n", f(8)+1, 13);
24: 4635 li a2,13
26: 45b1 li a1,12
28: 00000517 auipc a0,0x0 # save pc+0 to a0
2c: 7d050513 addi a0,a0,2000 # 7f8 <malloc+0xea>
30: 00000097 auipc ra,0x0 # save pc to ra
34: 620080e7 jalr 1568(ra) # 650 <printf>
Where is the function call to f from main? Where is the call to g? (Hint:the compiler may inline functions.)
确实,从汇编代码中可以看出,对f,g的调用被优化掉了,体现在汇编代码里是一个立即数:如上图,地址为26
At what address is the function printf located?
printf的地址,注意这里没有使用call,而是jalr,代表jump and link register,语法是:
jalr dst src imm
作用是跳转到imm(src),并且"set the location of the instruction to dst"(这里好像是指把一个地址复制给dst,一般要调用函数时ra,但是一方面这个代码里不是这么写的,这里是在之前就要用auipc设置了ra,而方面感觉risc-v的汇编形式很灵活,半天没找到特殊说明,所以先就这样吧TODO)
注意此时ra等于0x30(是有上一条auipc设置的,pc+0=0x30,注意当时的pc是0x30,而不是0x34,因为pc指向的是即将要执行的一条指令,在执行auipc之前,那当然就是auipc了),再加上1568,就是0x650
What value is in the register ra just after the jalr to printf in main?
这里是问,jalr之后,ra是多少,本来以为jalr里没有出现ra,所以ra没有变,还是0x30,但是通过debug,发现是0x38,也就是指向了正确的返回地址:jalr的下一条
0x0000000000000030 <main+20>: 97 00 00 00 auipc ra,0x0
=> 0x0000000000000034 <main+24>: e7 80 00 62 jalr 1568(ra) # 0x650 <printf>
=> 0x0000000000000038 <main+28>: 01 45 li a0,0
因为auipc和jalr两条指令所占字节共为8个(之前pc为0x30,指向的是auipc那一行的开头)
这里debug,用到了
set disassemble-next-line on
display /x $reg(你选定的寄存器)
之后就可以使用ni,si(如果有函数调用就进入