assembly 这个组装说明书是干什么的?

iaqfqrcu  于 2022-11-24  发布在  其他
关注(0)|答案(1)|浏览(178)

这是一个关于数据危险的作业的片段,但是我很难理解它在做什么。

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指令集。有详细的在线文档来解释这些指令吗?

谢谢大家!
找到了这个

qvk1mo1f

qvk1mo1f1#

我编辑了每个指令的功能列表:

1. 𝐴𝐷𝐷𝐼 𝑅2, 𝑅2, 1  : Add 1 to R2 and store the result in R2
2. 𝐿𝐷 𝑅4, 0(𝑅3)    : Load data at R3 address into R4.
3. 𝐿𝐷 𝑅5, 4(𝑅3)    : Load data at (R3 address + 4) into R5
4. SLT 𝑅6, 𝑅4, 𝑅5  : R4 < R5 ? R6 = 1 : Do Nothing
5. SD 𝑅6, 8(R3)     :  Store data in R6 at (R3 address + 8)
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.: Add R13 to R12 and store the result in R11.
  • (R3)前面的数字是一个临时偏移量,在R3被取消引用之前,它将被添加到R3。换句话说,LD R5,4(R3)对寄存器的作用与以下相同:
ADDI R3,R3,4  ;add 4 to the value in R3, and store the result in R3
LD R5,(R3)    ;treating the value in R3 as a memory address, 
              ;dereference it and store the integer at that address into R5
SUBI R3,R3,4  ;return R3 to its original state.

除此之外,所有这些都发生在一条指令中,实际上没有对R3进行修改。

  • R3的初始值并不像R2那样重要。R2被用作循环计数器,而R3被用作指向内存的指针(我不知道它指向什么)。
  • 至于与数据危害的相关性,危害如下:
ADDI R3,R3, 1  : Add 1 to R3 and store the result in R3.

假设R3指向一个32位整数。这是由所有偏移量都是4的倍数所暗示的。为了说明的目的,让我们假设在循环的开始,R3 = 0x40000000。所有存储在这些地址的字节都是由我组成的,除了存储在0x40000008-0x4000000B的字节。它们是通过指令SD R6,8(R3)写入内存的。(我假设是big-endian体系结构,因此采用字节顺序。)

0x40000000: 0xDE
0x40000001: 0xAD
0x40000002: 0xBE
0x40000003: 0xEF

0x40000004: 0x12
0x40000005: 0x34
0x40000006: 0x56
0x40000007: 0x78

0x40000008: 0x00
0x40000009: 0x00
0x4000000A: 0x00
0x4000000B: 0x01

在执行列表中的指令6之后,R4包含0xDEADBEEFR5包含0x12345678。这没问题,但问题是我们给R3加了1,而不是4。这意味着我们在后续循环中加载到R4R5中的数字不是预期的数据。而是从不同价值观中被科学地结合在一起的垃圾。下面是我们在第二遍之后得到的结果:

0x40000000: 0xDE
0x40000001: 0xAD
0x40000002: 0xBE
0x40000003: 0xEF

0x40000004: 0x12
0x40000005: 0x34
0x40000006: 0x56
0x40000007: 0x78

0x40000008: 0x00
0x40000009: 0x00
0x4000000A: 0x00
0x4000000B: 0x00

0x4000000C: 0x01

这里,R4 = 0xADBEEF12R5 = 0x34567800。为了正确地遍历内存,我们需要将ADDI R3,R3, 1更改为ADDI R3,R3, 4
现在,为什么CPU会允许你这样做呢?嗯,有些CPU实际上不允许,如果你试图写入一个未对齐的地址,就会出错。其他的,比如x86,就没有那么挑剔。事实证明,CPU * 不知道你的数据是什么类型,* 依赖于程序员或编译器来强制执行类型规则。

相关问题