Linux操作系统分析孟宁Lab1

本次实验内容:将一个简单的C程序汇编成x86或x86-64汇编代码,并逐步分析程序的执行过程,深入理解存储程序计算机和函数调用堆栈框架在执行过程中所起的作用。
我选择使用RISC-V汇编代码。
首先安装对应的gcc交叉编译环境:

sudo apt-get install gcc -riscv64-linux-gnu

安装成功:
在这里插入图片描述
然后编写一段简单的C语言代码:
在这里插入图片描述
执行编译指令:

riscv64-linux-gnu-gcc -S -o main_riscv64.s main.c

编译成功:
在这里插入图片描述
查看汇编代码:

 .file   "main.c"                                                                                                                                                             
  2     .option nopic
  3     .text
  4     .align  1
  5     .globl  g
  6     .type   g, @function
  7 g:
  8     add sp,sp,-32 #sp=sp-32 为栈顶预留四个字节的存储空间
  9     sd  s0,24(sp)#store指令,s0为栈底指针,将s0的值存放到sp+24的位置
 10     add s0,sp,32#s0 = sp+32 构造g函数的栈空间,形成g函数的逻辑空栈
 11     mv  a5,a0#将a0的值赋给a5即a5 = a0
 12     sw  a5,-20(s0)#store指令 将a5的值存放至s0-20的位置中
 13     lw  a5,-20(s0)#load指令,将s0-20的值存放至a5
 14     addw    a5,a5,2023#a5 = a5 + 2023
 15     sext.w  a5,a5
 16     mv  a0,a5#a0 = a5 将g函数的返回值存放至a0中
 17     ld  s0,24(sp)#s0 = sp+24 将sp+24的值重新存储道s0栈底指针中,指向f函数的栈空间
 18     add sp,sp,32 #栈顶指针指向f函数栈空间的栈顶
 19     jr  ra#无条件跳转指令 函数返回
 20     .size   g, .-g
 21     .align  1
 22     .globl  f
 23     .type   f, @function
 24 f:
 25     add sp,sp,-32#sp = sp -32 sp为栈顶指针预留出四个字节存储空间
 26     sd  ra,24(sp)#store指令,ra存放的是返回地址
 27     sd  s0,16(sp)#store指令 s0为栈底指针,将s0的值存放到sp+16指向的位置中
 28     add s0,sp,32#s0=sp+32,构造f函数的栈空间,形成f函数的逻辑空间
 29     mv  a5,a0#a5=a0,a0存放的是函数参数,此处保存一次参数的作用是用来给后面的g函数进行传递参数,此时a5中存放的是23,可以发现RISC-V使用 寄存器 进行参数传递
 30     sw  a5,-20(s0)#store指令,将a5的值存放到s0-20指向的位置中
 31     lw  a5,-20(s0)#load指令,将s0-20位置中的值存放到a5中
 32     mv  a0,a5#a0=a5,此时a0保存的是函数参数,为调用g(x)做准备
 33     call    g#调用g函数
 34     mv  a5,a0#a5=a0
 35     mv  a0,a5#a0=a5,将f函数返回值保存在a0中
 36     ld  ra,24(sp)#ra=sp+24,获取main函数的返回地址
 37     ld  s0,16(sp)#s0=sp+16,将sp+16的值重新存储到s0栈底指针中,指向main函数的栈空间
 38     add sp,sp,32#sp,sp,32 ;指向main函数栈空间栈顶
 39     jr  ra#无条件跳转指令,返回main函数
 40     .size   f, .-f
 41     .align  1
 42     .globl  main
 43     .type   main, @function
main:
 45     add sp,sp,-16#sp=sp-16,64位指令集,一条指令需要8个字节,这里预留16字节分别存储上一个程序的堆栈的返回地址和栈底指针
 46     sd  ra,8(sp)#store指令,ra存放的是返回地址,将ra存放到sp+8指向的位置中
 47     sd  s0,0(sp)#store指令,s0为栈底指针,将s0的值存放到sp指向的位置中
 48     add s0,sp,16#s0=sp+16,构造main函数的栈空间,形成main函数的逻辑空栈
 49     li  a0,23#保存f函数参数23,li是RISC-V中的一条伪指令,意思是load immediate,即将一个立即数加载到寄存器中
 50     call    f#调用函数f,返回值会保存在a0中
 51     mv  a5,a0#a5 = a0
 52     addw    a5,a5,1#将寄存器 a5 的值加上 1,然后将结果作为一个 32 位的有符号整数写回 a5 中
 53     sext.w  a5,a5#将寄存器 a5 的值作为一个 32 位的有符号整数扩展到 64 位,然后写回 a5 中。这是一种伪指令,相当于 addiw a5,a5,0。
 54     mv  a0,a5
 55     ld  ra,8(sp)#从栈指针 sp 加上 8 的地址处加载 64 位的数据,然后存入寄存器 ra 中。ra 是返回地址寄存器,用于保存函数调用的返回地址
 56     ld  s0,0(sp)#从栈指针 sp 的地址处加载 64 位的数据,然后存入寄存器 s0 中。s0 是一个被调用者保存的寄存器,用于保存函数内部的状态或者参数
 57     add sp,sp,16#将栈指针 sp 的值加上 16,然后将结果存回 sp 中。这样做的目的是为了释放栈上分配的空间,恢复原来的栈指针位置
 58     jr  ra#无条件跳转到寄存器 ra 的值所表示的地址处继续执行。这样做的目的是为了返回到函数调用者处,结束当前函数的执行
 59     .size   main, .-main
 60     .ident  "GCC: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0"                                                                                                                           
main_riscv64.s                                         

任课老师:孟宁老师

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值