这是一个关于数据危险的作业的片段,但是我很难理解它在做什么。
loop:
1. 𝐴𝐷𝐷𝐼 𝑅2, 𝑅2, 1 : Add 1 to R2
2. 𝐿𝐷 𝑅4, 0(𝑅3) : Load data at R3 address into R4 (?)
3. 𝐿𝐷 𝑅5, 4(𝑅3) : Load data at R3 address into R5 (?)
4. SLT 𝑅6, 𝑅4, 𝑅5 : Set R6 = R4 < R5 ? 0 : 1
5. SD 𝑅6, 8(R3) : Store data in R6 at R3 address (?)
6. ADDI 𝑅3, 𝑅3, 1 : Add 1 to R3 (?)
7. 𝐵𝑁𝐸𝑍 𝑅2, 𝑙𝑜𝑜𝑝. : If R2 == 0, goto 1, else proceed to 8
8. ADD R11, R12, R13.: ???
备注
- 初值
R2 = -2
问题
0(R3)
、4(R3)
、8(R3)
之间有何区别?- 由于没有提供R3的初始值,我如何理解这个循环呢?我唯一确定的事实是-它运行了两次(
R2: -2 -> -1 -> 0
) - 为什么这里包括R11、R12和R13?
- 一个更一般的问题-我相信这是一个RISC-V指令集。有详细的在线文档来解释这些指令吗?
谢谢大家!
找到了这个
1条答案
按热度按时间qvk1mo1f1#
我编辑了每个指令的功能列表:
(R3)
前面的数字是一个临时偏移量,在R3
被取消引用之前,它将被添加到R3
。换句话说,LD R5,4(R3)
对寄存器的作用与以下相同:除此之外,所有这些都发生在一条指令中,实际上没有对
R3
进行修改。R3
的初始值并不像R2
那样重要。R2
被用作循环计数器,而R3
被用作指向内存的指针(我不知道它指向什么)。假设
R3
指向一个32位整数。这是由所有偏移量都是4的倍数所暗示的。为了说明的目的,让我们假设在循环的开始,R3 = 0x40000000
。所有存储在这些地址的字节都是由我组成的,除了存储在0x40000008-0x4000000B
的字节。它们是通过指令SD R6,8(R3)
写入内存的。(我假设是big-endian体系结构,因此采用字节顺序。)在执行列表中的指令6之后,
R4
包含0xDEADBEEF
,R5
包含0x12345678
。这没问题,但问题是我们给R3
加了1,而不是4。这意味着我们在后续循环中加载到R4
和R5
中的数字不是预期的数据。而是从不同价值观中被科学地结合在一起的垃圾。下面是我们在第二遍之后得到的结果:这里,
R4 = 0xADBEEF12
和R5 = 0x34567800
。为了正确地遍历内存,我们需要将ADDI R3,R3, 1
更改为ADDI R3,R3, 4
。现在,为什么CPU会允许你这样做呢?嗯,有些CPU实际上不允许,如果你试图写入一个未对齐的地址,就会出错。其他的,比如x86,就没有那么挑剔。事实证明,CPU * 不知道你的数据是什么类型,* 依赖于程序员或编译器来强制执行类型规则。