CS61C 2020计算机组成原理Lab03

Exercise 1: Familiarizing yourself with Venus

.data
.word 2, 4, 6, 8
n: .word 9.text
main:   # add t0, x0, x0# addi 是 "add immediate"(立即数加法)的缩写,表示这是一个加法指令,其中一个加数是一个立即数(即直接在指令中给出的数)# 将 x0 寄存器的值(即 0)和立即数 1 相加,然后将结果(0 + 1 = 1)存储在 t1 寄存器中。# 简而言之,这条指令将 t1 寄存器的值初始化为 1addi t1, x0, 1# la 是 "load address" 的缩写,表示这是一个加载地址的指令# 将标签 n 的地址加载到寄存器 t3 中la t3, n# lw 代表 "load word"(加载字),用于从内存中加载一个 32 位的字(word)到寄存器中。# 0(t3) 指定了要从哪里加载字的内存地址。这里使用了基址加偏移量的寻址方式,其中 0 是偏移量,t3 是基址寄存器# 执行这条指令之后,t3 不再持有地址,而是持有该地址处的数据lw t3, 0(t3)
fib:    # beq 代表 "branch if equal"(如果相等则跳转)。这是一个条件分支指令,用于比较两个寄存器的值,如果它们相等,则执行跳转到指定的标签。# 如果 t3 寄存器中的值等于 0(因为 x0 的值永远是 0),那么程序将跳转到标签 finish 指示的位置。# 如果 t3 的值不是 0,程序将不会跳转,而是继续执行下一条指令。beq t3, x0, finishadd t2, t1, t0# 是将 t1 寄存器中的数据复制到 t0 寄存器中。mv t0, t1mv t1, t2addi t3, t3, -1  # j 是 "jump"(跳转)的缩写,表示这是一个无条件跳转指令,用于将程序的控制流跳转到指定的位置。# 使程序跳转到标签 fib 所在的代码位置,继续从那里执行j fib
finish: # addi a0, x0, 1 这条指令将 a0 寄存器的值设置为 1。# 在 RISC-V 架构中,进行系统调用(ecall)时,a0 寄存器通常用于指定系统调用的类型或功能代码。# 这里,将 a0 设置为 1 通常表示执行的是打印整数的系统调用addi a0, x0, 1# addi a1, t0, 0 这条指令将 t0 寄存器的值复制到 a1 寄存器中。# 在进行打印整数的系统调用时,a1 寄存器用于存储要打印的整数值。addi a1, t0, 0# 接着执行 ecall 指令时,系统将根据 a0 和 a1 寄存器的值来执行相应的操作。# 由于 a0 被设置为 1(表示打印整数的系统调用),并且 a1 包含了要打印的整数(来自 t0),# 因此 ecall 指令会导致打印出 a1 中的整数值ecall # print integer ecall# 将 a0 设置为 10 通常表示执行的是一个终止程序的系统调用addi a0, x0, 10# 随后执行的 ecall 指令,系统将根据 a0 寄存器的值来执行相应的操作ecall # terminate ecall

Paste the contents of ex1.s in Venus and record your answers to the following questions. Some of the questions will require you to run the RISC-V code using Venus’ simulator tab.

  1. What do the .data, .word, .text directives mean (i.e. what do you use them for)? Hint: think about the 4 sections of memory.

A: In the context of assembly language, particularly for systems like RISC-V or MIPS, the directives .data, .word, and .text are used to organize and manage different sections of a program’s memory. These align with the typical memory sections in a compiled program:

  1. .data Directive:
    • Purpose: The .data directive is used to declare the data segment of the program. This segment is for initializing variables that retain their values throughout the program’s execution. It’s primarily used for static and global variables.
    • Memory Section: It corresponds to the data segment in memory, which is different from the stack and heap segments. This segment is used for static data allocation.
  2. .word Directive:
    • Purpose: The .word directive is used within the data segment to define 32-bit words. Each .word allocates 4 bytes of memory (since a word is 32 bits) and can be used to initialize these words with specific values. For example, .word 2, 4, 6, 8 will allocate 16 bytes of memory and initialize them with the given values.
    • Memory Section: These words are part of the data segment. This directive helps in reserving memory space and initializing data in this segment.
  3. .text Directive:
    • Purpose: The .text directive indicates the start of the code segment of the program. This is where the actual instructions of the program are written. It’s the executable part of the program.
    • Memory Section: It corresponds to the text (or code) segment in memory. This segment is used for the executable instructions of the program and is distinct from data, stack, and heap segments.

These directives help in organizing a program into distinct sections, each with its own role in the program’s structure and execution. The .data segment for initializing and storing data, the .word directive for defining 32-bit integers in the data segment, and the .text segment for the actual executable instructions. This organization reflects the typical division of memory in compiled programs into segments like text (code), data, stack (for function calls and local variables), and heap (for dynamically allocated memory).

  1. Run the program to completion. What number did the program output? What does this number represent?

A: The program output the number 34. This number represents the 9th number in the Fibonacci sequence.

In the Fibonacci sequence, each number is the sum of the two preceding ones, starting from 0 and 1. So, the sequence goes 0, 1, 1, 2, 3, 5, 8, 13, 21, 34,… and so on. The number 34 is the 9th term in this sequence (if we start counting from 0 as the first term).

  1. At what address is n stored in memory? Hint: Look at the contents of the registers.

A: after “la t3, n” , t3这个地方变成了 268435464

在这里插入图片描述

Exercise 2: Translating from C to RISC-V

C程序:

int source[] = {3, 1, 4, 1, 5, 9, 0};
int dest[10];int fun(int x) {return -x * (x + 1);
}int main() {int k;int sum = 0;for (k = 0; source[k] != 0; k++) {dest[k] = fun(source[k]);sum += dest[k];}return sum;
}

对应的汇编语言:

.data
source:.word   3.word   1.word   4.word   1.word   5.word   9.word   0
dest:.word   0.word   0.word   0.word   0.word   0.word   0.word   0.word   0.word   0.word   0.text
main:addi t0, x0, 0addi s0, x0, 0# load address , 将source的内存地址加载到 寄存器s1中la s1, sourcela s2, dest
loop:# slli:这是一个指令操作码,代表“Shift Left Logical Immediate”。它表示将一个寄存器中的值向左逻辑移位(即在右边补零)一个立即数指定的位数# 将 t0 寄存器中的值向左移动 2 位,然后将结果存入 s3 寄存器slli s3, t0, 2# add 是寄存器中的值相加add t1, s1, s3lw t2, 0(t1)beq t2, x0, exitadd a0, x0, t2# 用于对栈指针(Stack Pointer)进行操作# addi sp, sp, -8 的操作是将栈指针 sp 的当前值减去 8,它实际上在栈上为新的数据或变量预留了 8 个字节的空间addi sp, sp, -8# 代表“Store Word”。它用于将一个字(word)的数据从寄存器存储到内存中。# 将寄存器 t0 中的数据存储到栈指针 sp 当前指向的内存地址处。由于偏移量是 0,这意味着数据被存储在栈顶sw t0, 0(sp)sw t2, 4(sp)# Jump and Link”。这个指令用于跳转到程序中的另一个位置(在这个例子中是标签 square 所指示的位置),同时将返回地址(即跳转之后下一条指令的地址)保存在一个特定的寄存器中jal squarelw t0, 0(sp)lw t2, 4(sp)addi sp, sp, 8add t2, x0, a0add t3, s2, s3sw t2, 0(t3)add s0, s0, t2addi t0, t0, 1# jal x0, loop 的操作是跳转到标签 loop 指示的代码位置,但不保存返回地址(因为它写入了零寄存器 x0)jal x0, loop
square:add t0, a0, x0add t1, a0, x0addi t0, t0, 1addi t2, x0, -1mul t1, t1, t2mul a0, t0, t1# jr ra 的操作是从 ra 寄存器中读取存储的地址,并跳转到那个地址继续执行程序。# 这种指令通常用于函数的末尾,用来返回到调用该函数的地方。# 当一个函数执行完毕,通过 jr ra 指令,程序控制权会返回到调用该函数的下一条指令处继续执行# Jump Register(操作指令) 和 Return Address寄存器jr ra
exit:add a0, x0, s0add a1, x0, x0ecall # Terminate ecall

我的回答:

  • The register representing the variable k

Answer: t0

  • The register representing the variable sum.

Answer: s0

  • The registers acting as pointers to the source and dest arrays.

Answer: s1 和 s2

  • The assembly code for the loop found in the C code.

Answer: loop

  • How the pointers are manipulated in the assembly code.

Answer: 使用偏移

gpt4的回答(更详细,举了例子,和我的答案是一样)

The register representing the variable k

  • The variable k seems to be represented by the register t0. This is inferred from the line addi t0, x0, 0, which initializes t0 to 0 (similar to k = 0 in C), and the line addi t0, t0, 1, which increments t0 by 1 (similar to k++ in a loop).

The register representing the variable sum

  • The variable sum appears to be represented by the register s0. This is based on the line addi s0, x0, 0 (initializing s0 to 0, like sum = 0), and the line add s0, s0, t2, which adds the value in t2 to s0 (akin to accumulating values in sum).

The registers acting as pointers to the source and dest arrays

  • s1 is used as a pointer to the source array (la s1, source).
  • s2 is used as a pointer to the dest array (la s2, dest).

The assembly code for the loop found in the C code

  • The loop in the assembly code is represented by the label loop: and includes instructions from this label down to jal x0, loop. The loop terminates when beq t2, x0, exit is executed, which happens when t2 (loaded from the source array) is zero, effectively translating to a check like if (source[k] == 0) break; in C.

How the pointers are manipulated in the assembly code

  • The pointers (s1 for source and s2 for dest) are manipulated using offset calculations. For instance, slli s3, t0, 2 and add t1, s1, s3 calculate the address to read from or write to in the source or dest arrays. The slli s3, t0, 2 instruction shifts t0 left by 2 bits, effectively multiplying k by 4 (since each word is 4 bytes). This value is then added to s1 or s2 to get the correct address in the array for the current loop iteration.

Exercise 3: Factorial

完成factorial.s, 实现求阶乘的功能

我的解法:

.globl factorial.data
n: .word 8.text
main:la t0, nlw a0, 0(t0)lw t0, 0(t0)# 跳转到标签 factorial 指示的地址去执行代码,并将下一条指令的地址保存在 ra 寄存器中jal ra, factorialfinish:addi a1, a0, 0addi a0, x0, 1 #a0设置为1,表示打印整数ecall # Print Resultaddi a1, x0, '\n'addi a0, x0, 11 # a0设置为11,表示打印字符ecall # Print newline# a0设置为10,表示终止程序addi a0, x0, 10ecall # Exitfactorial:# YOUR CODE HEREaddi t1, t0, -1beq t1, x0, finishmul a0, a0, t1add t0, t1, x0j factorial

安装java环境后,测试代码是否正确:
在这里插入图片描述

Exercise 4: RISC-V function calling with map

.globl map.text
main:# 跳转到标签 create_default_list 指示的地址去执行代码,并将下一条指令的地址保存在 ra 寄存器中jal ra, create_default_listadd s0, a0, x0  # a0 = s0 is head of node list#print the listadd a0, s0, x0jal ra, print_list# print a newlinejal ra, print_newline# load your argsadd a0, s0, x0  # load the address of the first node into a0# load the address of the function in question into a1 (check out la on the green sheet)### YOUR CODE HERE ###la a1, square   # 加载 square 函数的地址到 a1# issue the call to mapjal ra, map# print the listadd a0, s0, x0jal ra, print_list# print another newlinejal ra, print_newlineaddi a0, x0, 10ecall #Terminate the programmap:# Prologue: Make space on the stack and back-up registers### YOUR CODE HERE ###addi sp, sp, -12  # 为三个寄存器分配栈空间sw ra, 0(sp)      # 保存 rasw s0, 4(sp)      # 保存 s0sw s1, 8(sp)      # 保存 s1beq a0, x0, done    # If we were given a null pointer (address 0), we're done.add s0, a0, x0  # Save address of this node in s0add s1, a1, x0  # Save address of function in s1# Remember that each node is 8 bytes long: 4 for the value followed by 4 for the pointer to next.# What does this tell you about how you access the value and how you access the pointer to next?# load the value of the current node into a0# THINK: why a0?### YOUR CODE HERE ###lw a0,0(s0) # 加载当前节点的值到 a0# Call the function in question on that value. DO NOT use a label (be prepared to answer why).# What function? Recall the parameters of "map"### YOUR CODE HERE #### 这条指令的功能是从一个寄存器中读取地址,并跳转到该地址执行,同时将下一条指令的地址(即返回地址)保存在默认的链接寄存器 ra(返回地址寄存器)jalr a1       # 调用 a1 寄存器中的函数# store the returned value back into the node# Where can you assume the returned value is?### YOUR CODE HERE ###sw a0, 0(s0)  # 将返回值存回当前节点# Load the address of the next node into a0# The Address of the next node is an attribute of the current node.# Think about how structs are organized in memory.### YOUR CODE HERE ###lw a0, 4(s0)  # 加载下一个节点的地址到 a0# Put the address of the function back into a1 to prepare for the recursion# THINK: why a1? What about a0?### YOUR CODE HERE ###add a1, s1, x0  # 恢复函数地址到 a1# recurse### YOUR CODE HERE ###jal ra, map    # 递归调用 mapdone:# Epilogue: Restore register values and free space from the stack### YOUR CODE HERE ###lw ra, 0(sp)   # 恢复 ralw s0, 4(sp)   # 恢复 s0lw s1, 8(sp)   # 恢复 s1addi sp, sp, 12  # 释放栈空间jr ra # Return to callersquare:add t0, a0, x0mul a0 ,t0, t0jr racreate_default_list:addi sp, sp, -12sw  ra, 0(sp)sw  s0, 4(sp)sw  s1, 8(sp)# li 指令的全称是 "Load Immediate"。它用于将一个立即数(即直接指定的数值)加载到一个寄存器中。这个指令通常用于初始化寄存器的值li  s0, 0       # pointer to the last node we handledli  s1, 0       # number of nodes handled
loop:   #do...li  a0, 8jal ra, malloc      # get memory for the next nodesw  s1, 0(a0)   # node->value = isw  s0, 4(a0)   # node->next = lastadd s0, a0, x0  # last = nodeaddi    s1, s1, 1   # i++addi t0, x0, 10bne s1, t0, loop    # ... while i!= 10lw  ra, 0(sp)lw  s0, 4(sp)lw  s1, 8(sp)addi sp, sp, 12jr raprint_list:# bne: 这是一个条件分支指令,代表“branch if not equal”。它的作用是比较两个寄存器的值,如果它们不相等,则跳转到指定的标签或地址。bne a0, x0, printMeAndRecursejr ra       # nothing to print
printMeAndRecurse:add t0, a0, x0  # t0 gets current node addresslw  a1, 0(t0)   # a1 gets value in current nodeaddi a0, x0, 1      # prepare for print integer ecallecalladdi    a1, x0, ' '     # a0 gets address of string containing spaceaddi    a0, x0, 11      # prepare for print string syscallecalllw  a0, 4(t0)   # a0 gets address of next nodejal x0, print_list  # recurse. We don't have to use jal because we already have where we want to return to in raprint_newline:addi    a1, x0, '\n' # Load in ascii code for newlineaddi    a0, x0, 11ecalljr  ramalloc:addi    a1, a0, 0addi    a0, x0 9ecalljr  ra

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/144866.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

macos tcl-tk python图形库软件包安装 port 和brew 包管理工具安装方法和使用总结

macos下安装这个tcl-tk 图形库, 使用port和brew 安装时是不一样的, 软件包名称不一样,安装后的软件文件路径信息也不一样。 在brew 包管理工具中,这个软件包的名称就是tcl-tk, 安装方法为 brew install tcl-tk , 而…

昂科烧录器支持Senasic琻捷电子的蓝牙低功耗芯片SNP746

芯片烧录行业领导者-昂科技术近日发布最新的烧录软件更新及新增支持的芯片型号列表,其中Senasic琻捷电子的蓝牙低功耗芯片SNP746已经被昂科的通用烧录平台AP8000所支持。 SNP746是一款蓝牙低功耗芯片,集成了压力传感器和加速度传感器的测量电路。它是为…

表达式求值(综合应用的难题)

一、各种表达式的含义与操作 请看下面链接里面的博客吧,这是一位大佬写的,里面的图很是不错,可以看看。 各种表达式的概念与操作 二、题目 给定一个表达式,其中运算符仅包含 ,-,*,/(加 减 乘 整除)&…

产业报告 | 2024年中国机器人产业研究报告

近日,世界机器人大会在北京亦庄国际会展中心举办。据悉,这是国内最大的机器人展会,今年的展会规模更是创下新高,共有169家企业参展,展出的产品数量超过600款,观展人次超过30万,足见各行各业对机…

QT widgets 窗口缩放,自适应窗口大小进行布局

1. 窗口布局 2. 尺寸策略:扩展 Fixed (固定): 行为:控件的大小是固定的,不会随着窗口大小的变化而改变。它的大小由控件的 sizeHint() 返回的值决定。 适用场景:当你希望控件的大小保持不变,不随布局调整时使用&#x…

前端vue-插值表达式和v-html的区别

创建vue实例的时候,可以有两种形式。 1.let appnew Vue({}) 2 const appnew Vue({}) 3 el是挂载点,是上面div的id值 4 data中的值可以展示在上面div中 5 v-html标签里面如果有内容,则我们的新内容会把标签里面的内容覆盖掉

解决 Torch not compiled with CUDA enabled 问题 | MiniCPM3-4B 【应用开发笔记】

最近在研究测试MiniCPM3-4B,这里记录一下遇到的cuda和torch版本问题 在调试和运行MiniCPM3-4B过程中如果出现找不到某个包,就用pip进行安装,如果提示GPU相关的问题则需要进一步检查 解决 Torch not compiled with CUDA enabled 问题 一、查看…

Arthas 全攻略:让调试变得简单

文章目录 一、简介二、命令列表 一、简介 注意 : 我安装的版本是:Arthas V3.7.2 官网:https://arthas.aliyun.com/doc/ 相关错误解决方案请看GitHub:https://github.com/alibaba/arthas/issues Alibaba开源的Java诊断工具。 从…

我的AI工具箱Tauri版-MicrosoftTTS文本转语音

本教程基于自研的AI工具箱Tauri版进行MicrosoftTTS文本转语音服务。 MicrosoftTTS文本转语音服务 是自研的AI工具箱Tauri版中的一款功能模块,专为实现高效的文本转语音操作而设计。通过集成微软TTS服务,用户可以将大量文本自动转换为自然流畅的语音文件…

圣多纳释放法,达到内心的平静

圣多纳释放法的关键在于:我们被情绪控制时,不应该压抑情绪或是发泄情绪。 利用释放法处理情绪是最健康的方法,可以帮助我们获得自由与平静。当我们面对讨厌的人时,我们真正要做的并非压抑或者爆发,而是将“讨厌”这种…

仪表放大器AD620

AD623 是一款低功耗、高精度的仪表放大器,而不是轨到轨运算放大器。它的输入电压范围并不覆盖整个电源电压(轨到轨),但在单电源供电下可以处理接近地电位的输入信号。 AD620 和 AD623 都是仪表放大器,但它们在一些关键…

HTB-Netmon(prtg配置文件获取,CVE-2018-9276复现)

前言 各位师傅大家好,我是qmx_07,今天给大家讲解Netmon靶机 渗透流程 信息搜集 服务器开放了80HTTP、21FTP(匿名登录)、445SMB服务 FTP匿名登录 获取敏感文件 登录后台 网站登录需要 账号、密码 ,尝试去FTP服务 碰下运气 通过翻阅ft…

基于Python flask的淘宝商品数据分析可视化系统,包括大屏和主题分析,还有回归预测

背景介绍 随着电子商务的迅猛发展,平台上积累了大量的用户行为和商品交易数据。这些数据蕴含着极大的商业价值,可以为市场趋势预测、商品优化以及用户行为分析提供重要的参考。淘宝作为全球最大的在线购物平台之一,拥有海量的商品和用户数据…

联想一体机怎么重装系统_联想一体机重装win10系统教程

联想一体机怎么重装系统?联想一体机重装系统有很多,有一键重装、有U盘重装、有硬盘重装等方式,最保险的方式是u盘重装系统。需要准备一个空U盘,然后利用第三方工具制作启动u盘,制作完成后进入pe重装系统,下…

集装箱机房可视化:高效管理与监控

通过图扑可视化平台实时监控集装箱机房的运行状态和环境参数,优化资源配置,提升运维效率,确保数据中心安全可靠运行。

Swagger 概念和使用以及遇到的问题

前言 接口文档对于前后端开发人员都十分重要。尤其近几年流行前后端分离后接口文档又变 成重中之重。接口文档固然重要,但是由于项目周期等原因后端人员经常出现无法及时更新, 导致前端人员抱怨接口文档和实际情况不一致。 很多人员会抱怨别人写的接口文档不…

dll注入的实现及session0注入

记录一下跟着红队蓝军师傅学免杀的过程 本节旨在学习dll注入和代码实现并不涉及免杀知识 dll注入流程 dll注入要么注入自己写的程序要么找个程序进行注入,一般是找其他程序进行注入 所以按照上面的步骤进行 其中申请空间,创建线程都是在远程的另一个进…

【Linux】-----进程第一弹

目录 概念 描述进程-PCB 查看进程 获取进程标识符 终止进程 fork创建进程 返回值说明 进程的状态 ①运行状态(R) ②浅度睡眠(S) ③深度睡眠(D) ④暂停状态(T) ⑤僵尸状态(Z)(重点) 是什么? 举例 危害 孤儿进程 ⑥死亡状态(X) 概念 课本上对于进程…

土豆王国小乐队携手阿派朗创造力乐园,打造2024年okgo儿童音乐节

艺术与科技的完美融合,为首都少年儿童带来音乐盛宴 北京,2024年9月19日 —— 备受期待的2024年okgo儿童音乐节即将于9月21日至22日在北京阿派朗创造力乐园盛大开幕。这场由土豆王国小乐队与阿派朗创造力乐园联合举办的音乐节,旨在为首都及全国…

【828华为云征文|华为云Flexus X实例部署指南:轻松搭建可道云KODBOX项目】

文章目录 华为云 Flexus X 实例:引领高效云服务的新时代部署【可道云KODBOX】项目准备工作具体操作指南服务器环境确认宝塔软件商店操作域名解析可道云KODBOX登录页效果验证 总结 华为云 Flexus X 实例:引领高效云服务的新时代 在云计算领域&#xff0c…