You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
; Example 1:MOV x2,0x400000 ; -> x2 is 0x400000LDR x6, =0x1234abce ; -> x6 is 0x1234abceSTR x6,[x2, #8]! ; -> 把x6的值(0x1234abce),存储到0x400008地址的内存里面; What's value of x2? And the value in 0x400000 address? ;Example 2:MOV x2,0x500000 ; -> x2 is 0x500000STR x6,[x2], #8 ; -> 把x6的值(0x1234abce),存储到0x500000里面,并将x2寄存器变为0x500008; What's value of x2? And the value in 0x400000 address?
The LDNP and STNP instructions provide a streaming or non-temporal hint, that the data does not need to be retained in caches. 指令提供了一个流式或非临时提示,即数据不需要保留在缓存中。
The PRFM, or prefetch memory instructions enable targeting of a prefetch to a specific cache level .“PRFM”或预取存储器指令能够将预取定为特定的高速缓存级别。
load/store
All Load/Store instructions now support consistent addressing modes。现在,所有加载/存储指令都支持一致寻址模式。This makes it much easier, for example, to treat char, short, int and long long in the same way when loading and storing quantities from memory. 例如,这使得在从内存加载和存储量时更容易以相同的方式处理“char”、“short”、“int”和“long-long”。
Github地址:carloscn/uncle-ben-os at car_lab_06 (github.com)
ARMv8指令集介绍
LDR指令
LDR Xd, [Xn, $offset]
【释义】:将Xn寄存器中存储的地址+offset地址偏移存 组成一个新的地址,把这个地址里面存储的值放在Xd寄存器中。[]有取地址内存储的数值的含义。
【示例】:
S1: 使用MOV指令把0x80000加载到X1寄存器:
MOV x1, 0x80000
(如果是一个数,而非#0x80000, 则是一个地址)S2: 使用MOV指令把16数值加载到X3寄存器:
MOV x3, 16
S3: 使用LDR指令读取X1地址里面存储的值,存储到X0中:
LDR x0,[x1]
, 这个不允许->LDR x2,[0x80000]
S4:使用LDR指令读取X1 + 8地址里面存储的值,存储到X2中:
LDR x2,[x1, #8]
S5:使用LDR指令读取(X1 + X3)地址里面存储的值,存储到X4中:
LDR x4,[x1, x3]
S6: 使用LDR指令读取(X1+(X3<<3))地址里面存储的值,存储到X5中:
LDR x5,[x1,x3,lsl #3]
【注意】:
LDR x2,[x1, #8]
x1的值不会被更新为0x80008【变基模式】:
前变基模式 pre-index: 先更新偏移地址,后访问地址 (注意有叹号!表示)
LDR x6, [x1, #8]!
: 将x1里面的地址增加偏移#8并赋给x1,最后将新的x1寄存器内的地址的值给x6寄存器后变基模式 post-index: 先访问内存地址,再更新偏移地址
LDR x6, [x1], #8
: 将x1寄存器内的地址的值赋给x6寄存器,并将x1地址偏移+8。【伪指令】:
伪指令与指令的最大不同在于,伪指令属于编译器处理的范畴,伪指令会被编译展开为多条指令;指令是CPU处理的命令的最小单元。
LDR x7,=0x80000
-> 等同于 MOV x7, 0x80000LDR x7, 0x800000
; 这条指令的意义是,将当前PC寄存器的地址的 + 0x80000的偏移,取出地址内容填充到x7寄存器中。STR指令
从一个寄存器的值吐到内存中,支持立即数和寄存器操作。把Xd的值,存储到[xn|sp]里面。
immediate-post-index:
STR Xd, [Xn|SP], #<simm>
immediate-pre-index:
STR Xd, [Xn|SP, #<simm>]!
【示例】:
MOV/MOVZ指令
MOV底层原理实际上是MOVZ,MOV 16-bit的立即数到寄存器。
MOV xd, #<imm>
16位立即数MOVZ xd, #<imm16>, LSL #<shift>
16位的立即数,逻辑左移动 16,32,48位LDP/STP指令
相比于LDR和STR指令(8 bytes),LDP和STP指令用于多字节(16 bytes)操作,
【释义】:
LDP x3, x7, [x0]
-> 从x0的值为基地址,加载地址到X3寄存器,存储x0+8到x7寄存器。STP x1, x2, [x4]
-> 以x4的值为基地址,存储x1地址的值到x4,存储x2地址的值到x4 + 8。【练习】:
练习1: 使用LDR和STR多字节加载和存储命令实现memset()函数,假设内存地址s是16字节对齐,count也是16字节对齐。例如:memset(0x200000, 0x55, 32)
练习二:同上,使用非对齐的memset(0x200004, 0x55, 37)
一些需要注意的地方
FAQ1:加载一个很大的数值到通用寄存器,例如0xFFFF0000FFFF0000, 使用MOV指令,是否正确?
错误,MOV 后面的立即数为16-bit,应该是使用LDR x1,=0xFFFF......0000 伪指令来加载大数。
FAQ2:加载一个寄存器的值,使用移位:MOV x1, (1<<0) | (1<<2)|(1<<20)|(1<<40)|(1<<55)
错误,同样是MOV立即数16-bit,使用LDR x1, = (1<<0)|......|(1<<55).
FAQ3: 字符串的LDR指令
FAQ3: 定义数据LDR指令
一种易错的死机状态: 树莓派4b上面的寄存器都是32bit的,下面代码配置26到U_IBRD_REG寄存器,有什么问题?
错误点在于树莓派4b寄存器访问都是32bit的,现在使用X寄存器,为64位的寄存器,应该使用W寄存器,32位寄存器访问。
GDB-Tips
启动GDB和QEMU链接
> gdb-multiarch --tui benos.elf
gdb> c
gdb> target remote localhost:1234
gdb> b ldr_test
// 设定断点gdb> c
gdb> next
//下一步gdb> info register
// 查看所有寄存器gdb> info x1 x2 x3
// 查看x1/x2/x3寄存器gdb> x 0x80000
// 读取内存0x80000值 32位gdb> x/xg 0x80000
// 读取内存0x80000值64位Addressing
参考03_ARMv7-M_存储系统结构的地址对齐访问设计。我们对ARMv8架构的对齐操作进行整理。
和Cortex-M一样,独占和顺序(ordered)访问(相对于指令预取和乱序访问)不可以对非对齐的地址进行访问。但是所有的load和store是支持非对齐访问的。
块传输(bulk transfers)
LDM
,STM
,PUSH,
和POP
指令不存在与A64指令集。所有的块传输都是通过STP
和LDP
LDNP
andSTNP
instructions provide a streaming or non-temporal hint, that the data does not need to be retained in caches. 指令提供了一个流式或非临时提示,即数据不需要保留在缓存中。PRFM
, or prefetch memory instructions enable targeting of a prefetch to a specific cache level .“PRFM”或预取存储器指令能够将预取定为特定的高速缓存级别。load/store
char
,short
,int
andlong long
in the same way when loading and storing quantities from memory. 例如,这使得在从内存加载和存储量时更容易以相同的方式处理“char”、“short”、“int”和“long-long”。Alignment checking
当执行在AArch64模式的时候,需要对取指令的load和store操作需要使用栈指针,所以会对PC和SP进行对齐检查。
https://developer.arm.com/documentation/den0024/a/An-Introduction-to-the-ARMv8-Instruction-Sets/The-ARMv8-instruction-sets/Addressing
The text was updated successfully, but these errors were encountered: