第四章 Lab4_assembly

实验描述及解答

理解一点RISC-V汇编是很重要的,你应该在6.004中接触过。xv6仓库中有一个文件user/call.c。执行make fs.img编译它,并在user/call.asm中生成可读的汇编版本。

阅读call.asm中函数g、f和main的代码。RISC-V的使用手册在参考页上。以下是您应该回答的一些问题(将答案存储在answers-traps.txt文件中):

  1. 哪些寄存器保存函数的参数?例如,在main对printf的调用中,哪个寄存器保存13?

call.c中的代码如下:

#include "kernel/param.h"
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"

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);
}

在Makefile中添加后(不知道怎么改xv-6的Makefile,可以参考第二章 实验:实现trace系统调用,这个实验过程基本包含了在xv-6下增加文件后,更改声明及编译规则的一般步骤),通过

make qemu
make fs.img

得到call.c对应的call.asm,在该文件的45行,(这里只列出相关的一部分,完整的call.asm见文章最后给出gitee仓库):

24:	4635                	li	a2,13

也就是a2保存了13的值。

  1. main的汇编代码中对函数f的调用在哪里?对g的调用在哪里(提示:编译器可能会将函数内联)

在call.asm中,没有对应的汇编代码来调用。查了资料上因为g和f这两个函数都被内链进main里了。

  1. printf函数位于哪个地址?

这次我们不直接看call.asm文件了,汇编代码的可读性是真难受,通过gdb来查看。
运行

make CPUS=1 qemu-gdb

再开一个窗口运行

riscv64-unknown-elf-gdb

进入gdb后,

source .gdbinit
file user/_call //进入用户程序的调试
b main			//在main处打一个断点

然后运行后,再在shell中执行call。gbd停在call进程的main里,接下来

b *0x34		//在调用printf的地址添加一个断点

运行到断点后,查看寄存器信息

info register	//根据提示输入RET获得更多寄存器信息

运行到printf时寄存器中的信息
第一问中的答案在这里也得到了印证。
然后

disas printf		//得到printf的路口地址在

得到

0x65a <printf>          addi    sp,sp,-96

也就是printf的地址在0x65a

  1. 在main中printf的jalr之后的寄存器ra中有什么值?

重新执行一遍call程序,在0x34处打下断点,查看一下要跳转的地址在0x65a,在这里打下断点后,执行,然后在gdb中查看寄存器ra(return address)
执行

i r ra

得到

ra             0x38     0x38 <main+28>

这一问就pass。

  1. 运行以下代码。
unsigned int i = 0x00646c72;
printf("H%x Wo%s", 57616, &i);

程序的输出是什么?
输出是

HE110 World

这是将字节映射到字符的ASCII码表。
输出取决于RISC-V小端存储的事实。如果RISC-V是大端存储,为了得到相同的输出,你会把i设置成什么?是否需要将57616更改为其他值?

i = 0x726c6400

57616的大小端序是一样的,不用更改。

这里有一个小端和大端存储的描述和一个更异想天开的描述。
6.在下面的代码中,“y=”之后将打印什么(注:答案不是一个特定的值)?为什么会发生这种情况?

printf("x=%d y=%d", 3);

打印

x=3 y=8229

第二个值是从a2寄存器读出来的,a2寄存器中是什么值打印出来的就是什么值。

实验所有代码见Lab4_assembly

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值