您的位置:首页 > 科技 > IT业 > 如何评价一个网页的设计_石家庄建站程序_谷歌商店paypal下载官网_新产品市场推广方案

如何评价一个网页的设计_石家庄建站程序_谷歌商店paypal下载官网_新产品市场推广方案

2025/1/10 11:04:02 来源:https://blog.csdn.net/2301_76355687/article/details/144945402  浏览:    关键词:如何评价一个网页的设计_石家庄建站程序_谷歌商店paypal下载官网_新产品市场推广方案
如何评价一个网页的设计_石家庄建站程序_谷歌商店paypal下载官网_新产品市场推广方案

1.ARMv8体系结构一共有8个小版本,分别是ARMv8.0、ARMv8.1、ARMv8.2、ARMv8.3、ARMv8.4、ARMv8.5、ARMv8.6、ARMv8.7,每个小版本都对体系结构进行小幅度升级和优化,增加了一些新的特性。

2.ARMv8 体系结构中的基本概念:处理机(Processing Element,PE):在 ARM 公司的官方技术手册中提到的一个概念,把处理器处理事务的过程抽象为处理机,可以将PE看作是CPU的一个核心;执行状态(execution state):处理器运行时的环境,包括寄存器的位宽、支持的指令集、异常模型、内存管理以及编程模型等。ARMv8 体系结构定义了两个执行状态:AArch64,64 位的执行状态(A64指令集,需要注意的是,A64指令集的指令宽度是32位,而不是64位)、AArch32,32位的执行状态(支持A32和T32指令集);系统寄存器命名:在 AArch64 状态下,很多系统寄存器会根据不同的异常等级提供不同的变种寄存器,<register_name>_Elx最后一个字母x可以表示 0、1、2、3。

3.ARMv8体系结构允许切换应用程序的运行模式。如在一个运行64位操作系统的ARMv8处理器中,我们可以同时运行A64指令集的应用程序和A32指令集的应用程序,但是在一个运行32位操作系统的ARMv8处理器中就不能运行A64指令集的应用程序了。当需要运行A32指令集的应用程序时,需要通过一条管理员调用(Supervisor Call,SVC)指令切换到EL1,操作系统会做任务的切换并且返回AArch32的EL0, 从而为这个应用程序准备好AArch32状态的运行环境。

4.ARMv8 支持如下几种数据宽度:字节:8位、半字:16位、字:32位、双字:64位、四字:128位。

5.AArch64执行状态支持31个64位的通用寄存器,分别是X0~X30寄存器,而AArch32状态支持16个32位的通用寄存器。

ARMv8体系结构除支持31个通用寄存器之外,还提供多个特殊的寄存器:ARMv8体系结构提供两个零寄存器(zero register),这些寄存器的内容全是0,可以用作源寄存器,也可以用作目标寄存器。WZR是32位的零寄存器,XZR是64位的零寄存器;PC指针寄存器通常用来指向当前运行指令的下一条指令的地址,用于控制程序中指令的运行顺序,但是编程人员不能通过指令来直接访问它;ARMv8体系结构支持4个异常等级,每一个异常等级都有一个专门的SP寄存器SP_ELn;当我们运行一个异常处理程序时,处理器的备份程序会保存到备份程序状态寄存器( Saved Program Status Register,SPSR)里。当异常将要发生时,处理器会把 PSTATE 寄存器的值暂时保存到SPSR里;当异常处理完成并返回时,再把SPSR的值恢复到PSTATE寄存器;ELR存放了异常返回地址;CurrentEL寄存器表示PSTATE寄存器中的EL字段,其中保存了当前异常等级,使用MRS指令可以读取当前异常等级(P8)。

除上面介绍的通用寄存器和特殊寄存器之外,ARMv8体系结构还定义了很多的系统寄存器,通过访问和设置这些系统寄存器来完成对处理器不同的功能配置。系统寄存器支持不同的异常等级的访问,通常系统寄存器会使用“Reg_ELn”的方式来表示。

6.QEMU提供用户模式和系统模式两种仿真方式。用户模式用于仿真单个用户空间程序,主要用于跨平台开发和测试,将目标程序的系统调用翻译为主机系统调用,启动和运行开销较小,性能较高。系统模式仿真完整的计算机系统,包括CPU、内存、外设和操作系统,用于运行完整操作系统镜像、开发和测试操作系统内核、构建虚拟机。两者区别在于仿真对象、用途和系统调用处理方式:用户模式专注于单个程序仿真,系统模式则提供全面的系统仿真。QEMU的-S选项用于在QEMU启动时暂停虚拟机的执行,并等待一个GDB调试器连接到QEMU的GDB服务器端口上,一旦GDB连接,虚拟机将继续执行,允许开发者在启动时进行调试。QEMU的-s选项用于在QEMU启动时打开GDB服务器功能, -s选项后面通常跟一个端口号,指定GDB调试器连接的端口,如果没有指定端口号,QEMU将使用默认端口1234,一旦GDB连接,开发者可以进行实时调试,包括查看寄存器状态、内存内容、单步执行代码等。

7.用gdb调试qemu中的代码的步骤:先用-S和-s选项在qemu中启动编译好的代码。然后重新打开一个终端,在拥有benos.elf的目录下使用gdb-multiarch –tui benos.elf命令打开gdb,该命令的作用是使用gdb-multiarch以TUI模式(Text User Interface,文本用户界面)调试名为benos.elf的ELF格式可执行文件,支持跨平台架构,提供文本用户界面显示调试信息。进入gdb中使用target remote localhost:1234命令连接qemu中的gdb服务器(默认端口号为1234)进行调试。这种调试方式无法显示中文注释,所以更推荐使用eclipse进行调试(见视频第三季1-5.mp4的1:54:05)。gdb中的常用命令:layout regs:查看寄存器的值。

8.使用qemu仿真时,ubuntu 20.04默认的qemu版本是不支持树莓派4b的,需要下载编译安装支持树莓派4b的qemu,可以使用qemu-system-aarch64 -M help | grep ras命令查看当前安装的qemu是否支持树莓派4b。使用J-Link调试时,有以下几个关键步骤:首先要确保通过usb连接的jlink已经可以被虚拟机识别到;然后需要下载编译安装openocd,其默认的configure是不支持jlink的,所以安装后无法识别到jlink,需要使用sudo ./configure --enable-jlink --enable-cmsis-dap --enable-stlink命令进行配置,此时依赖的libjaylink这个包需要先编译安装一下,否则会配置失败;安装好能识别jlink的openocd后,仍然无法识别到jlink设备,是因为openocd没有足够的权限访问 jlink设备。这通常是因为当前用户没有权限访问usb设备,尤其是在没有添加 udev 规则的情况下,所以需要添加相应文件。(使用eclipse调试见视频1的1:53:30)(刚开始实验时没有使用笨叔提供的qemu和openocd包,是从网上找的,实际笨叔是提供了的,应该可以直接安装使用)

9.链接文件定义了符号的虚拟地址,而在实际运行时,程序可能加载到不同的物理地址。如果虚拟地址和物理地址不一致,调试器(例如 GDB)会无法正确映射符号地址到实际内存中的位置,导致无法准确调试代码。为了解决这个问题,需要使用 add-symbol-file 命令来明确告诉调试器这些符号和代码段在实际内存中的加载地址。例如:add-symbol-file benos.elf 0x80030 -s .text.boot 0x80000 -s .rodata 0x80718。

10.ARMv8指令介绍(ARM64即A64指令集,A64汇编指令都是32bits宽的):(以下内容可参考官方手册和《arm64体系结构编程与实践》第3 4 5 6 7章)

  • LDR目标寄存器,<存储器地址>(C6.2.131),前变基模式即先更新地址后加载数据,如ldr x6,[x1,#8]!(在使用立即操作数时前面可以使用“#”也可以不使用“#”),表示先更新x1寄存器的值为x1加上8,再从x1寄存器指向的地址(此时已经加8)加载数据到x6寄存器中;后变基模式即先加载数据后更新地址,如ldr x7,[x1],#8,表示从x1寄存器指向的地址加载数据到x7寄存器中,然后x1寄存器的值增加8(前、后变基模式的立即数范围为-256~255);地址偏移模式即只加载数据不更新地址,如果使用了偏离量则这个偏移量必须是8的倍数且是正数(实际该指令的32位指令编码中只使用12位来表示偏移,为了获得更大寻址范围,汇编指令中的偏移量除以8就等于那12位编码的值。因为乘以了8所以这种加载方式又叫做可扩展模式,对于不可扩展模式,A64提供了LDUR和STUR指令,这两个指令的地址偏移是直接相加的,没有乘以8),如ldr x7,[x1,#8]表示将x1寄存器的值加上8所得地址处对应的数据加载到x7寄存器中(这三个类型对应手册中的C6.2.131 LDR(immediate)),对于LDR X0,[X1, X2, LSL #3]指令,其后面的偏移量只能是0或3,这是由编码位数限制所决定的,具体查看手册。伪指令:正常指令一条指令对应一个CPU操作,伪指令可能被编译器分解为几条指令的集合,ldr指令当使用“=”,形如ldr x7,=LABEL时就是伪指令,该指令作用是:若LABEL是宏定义就将LABEL对应的值赋值给x7寄存器,若LABEL是标号就将LABEL该标号对应的地址值赋值给x7寄存器,该伪指令还可以将立即数加载到寄存器,被加载的立即数可以是很大的数,如LDR X1,=0xffffffffffffffff;而没有=号不是伪指令,只是内存访问指令,如ldr x7,LABEL指令的作用是:若LABEL是宏定义则将当前PC值加上LABEL的值对应地址处的内容赋值给x7寄存器(注意如果这类指令中的目标寄存器是xn,即64位的寄存器,那么目标地址即当前PC值加上LABEL的值应该满足8字节对齐,否则会导致同步异常,同理若是wn则需4字节对齐),若LABEL是标号,则将LABEL对应地址处的内容赋值给x7寄存器(这个LABEL必须在当前PC地址前后1 MB的范围内,若超出这个范围,汇编器会报错,这是因为编码时用了19位来表示label,而指令是以4个字节寻址的,19位数据乘以4相当于共2M大小,前后1M)。(这没有=的类型对应手册中的C6.2.132 LDR(literal))
  • STR 源寄存器,<存储器地址>(C6.2.274),STR指令也有前变基、后变基(与LDR指令类似),但是STR没有伪指令。
  • MOV{条件}{S} 目的寄存器, 源操作数(C6.2.187),MOV指令可完成从另一个寄存器、被移位的寄存器或将一个立即数(立即数只能是16位的,超过16位会报错,所以MOV指令不能像LDR X1,=0xffffffffffffffff指令这样将一个很大的数直接加载到寄存器中)加载到目的寄存器。MOVZ指令用于将一个立即数加载到目标寄存器的低 16 位,且其余位被填充为零。
  • LDP 目标寄存器1,目标寄存器2,<存储器地址>(C6.2.129,这里的存储器地址的类型和LDR指令类似,也可以是前变基、后变基等形式),多字节加载指令(取代ARM32中的LDM),例如:LDP X3,X7,[X0]表示以X0的值为地址,加载此地址的值到X3寄存器,以X0+8为地址加载此地址的值到X7寄存器;STP 源寄存器1,源寄存器2,<存储器地址>(C6.2.273,这里的存储器地址的类型和STR指令类似,也可以是前变基、后变基等形式), 多字节存储指令(取代ARM32中的STM),例如:STP X1,X2,[X4]表示存储X1的值到地址为X4的内存中,然后存储X2的值到地址为X4+8的内存中。需要注意的是,LDP和STP指令中的立即数的取值范围为-512~504且必须是8的整数倍。A32指令集提供了PUSH与POP指令来实现入栈和出栈操作,不过A64指令集已经去掉了PUSH和POP指令,可以使用STP和LDP指令实现入栈和出栈:

  • 根据数据大小,例如1个字节、2个字节,有符号数等LDR和STR指令有如下变种:LDRSW是有符号的数据加载指令,大小为字(word) ,低位存储读取到的字,高位做符号扩展;LDRB是数据加载指令,大小为字节,低位存储读取到的字节,高位做零扩展;LDRSB是有符号的加载指令,大小为字节,低位存储读取到的字节,高位做符号扩展;LDRH是数据加载指令,大小为半字(Halfvord),低位存储读取到的半字,高位做零扩展;LDRSH是有符号的数据加载指令,大小为半字(Halfword) ,低位存储读取到的半字,高位做符号扩展;STRB是数据存储指令,大小为字节;STRH是数据存储指令,大小为半字。需要注意的是,访问和存储4个字节和8个字节都是LDR和STR,只不过目标寄存器使用Wn或者Xn。
  • ADD{条件}{S} 目的寄存器, 操作数1, 操作数2(C6.2.3),例如:ADD R0, R2, R3, LSL #1表示R0 = R2 + (R3 << 1),ADD指令中如果第二个操作数使用的是立即数,则立即数的范围只能是0~4095,如果想使用立即数并移位,只能使用LSL #0和LSL # 12,如果使用的第二个操作数是寄存器,可以对第二个寄存器操作数进行寄存器扩展,如UXTB(UXTB表示对8位的数据进行无符号扩展)、UXTH等,如命令:ADD X0, X1, X2, UXTB,还可以对第二个寄存器的值进行移位,移位的范围为0~63。ADDS指令与ADD指令类似,但是它会影响PSTATE条件标志位,ADC是带进位的加法指令:ADC{条件}{S} 目的寄存器(Rd), 操作数1(Rn), 操作数2(Rm),表示Rd = Rn + Rm + C,即会带上条件标志位C一起进行运算(对于加法运算,在无符号数相加溢出时会将C置1,否则C为0;对于减法运算,情况有些不同,因为实际计算时减法仍然会被当作加法运算进行,例如x-y,实际上是计算x+(-y),所以当x>=y时会溢出,此时C置1,否则C为0)。
  • SUB{条件}{S} 目的寄存器, 操作数1, 操作数2(C6.2.308),例如:SUB R0, R1, #256表示R0 = R1 – 256,SUBS指令与SUB指令类似,但是它会影响PSTATE条件标志位,SBC是带进位的加法指令:SBC{条件}{S} 目的寄存器(Rd), 操作数1(Rn), 操作数2(Rm),表示Rd = Rn - Rm -1+ C,即会带上条件标志位C一起进行运算。SUB指令中对于立即数范围以及移位范围的限定和ADD指令类似,具体可参考手册或《arm64体系结构编程与实践》。
  • CMP{条件} 操作数1, 操作数2(C6.2.60),例如:CMP R1, R0表示将寄存器R1的值与寄存器R0的值相减,并根据结果设置PSTATE的标志位(N、Z、C、V等标志位),其内部实现实际上是通过SUBS指令实现的(相当于执行操作数1-操作数2,但不存储结果,只更改条件标志位),例如当R1>=R0时,条件标志位C会被置1,否则C为0。CMN{条件} 操作数1, 操作数2,CMN指令用于把一个寄存器的内容和另一个寄存器的内容或立即数取反(即与其二进制补码进行比较,相当于执行操作数1+操作数2,但不存储结果,只更改条件标志位)后进行比较,同时更新条件标志位的值。CMP和CMN指令后一般会跟着一个条件跳转指令,条件码的意义如下图所示:

  • CMP和CMN指令后面除了跟条件跳转指令外,一般还可能跟条件选择指令,常见的条件选择指令有:CSEL Xd,Xn,Xm,cond,若cond为真则将Xn的值赋值给Xd,否则将Xm的值赋值给Xd;CSET Xd,cond,若cond为真则返回1给Xd,否则返回0;CSINC Xd,Xn,Xm,cond,若cond为真则将Xn的值赋值给Xd,否则将Xm+1的值赋值给Xd。这里提到的cond可以是上图中的eq、ne等条件。
  • LSL是逻辑左移指令,使用方式为:通用寄存器, LSL 操作数 或 LSL Xd, Xn, #shift/Xm(C6.2.177,Xd为目的寄存器,该指令效果为Xd = LSL(Xn, #shift/Xm)),逻辑左移最低位补0; LSR是逻辑右移指令,使用方式为:通用寄存器, LSR 操作数 或 LSR Xd, Xn, #shift/Xm(C6.2.180,Xd为目的寄存器,该指令效果为Xd = LSR(Xn, #shift/Xm)),逻辑右移最高位补0; ASR是算术右移指令,使用方式为:通用寄存器, ASR 操作数 或 ASR Xd, Xn, #shift/Xm(C6.2.17,Xd为目的寄存器,该指令效果为Xd =ASR(Xn, #shift/Xm)),算术右移最高位补符号位; ROR是循环右移指令,使用方式为:通用寄存器, ROR 操作数 或 ROR Xd, Xn, #shift/Xm(C6.2.226,Xd为目的寄存器,该指令效果为Xd =ROR (Xn, #shift/Xm))。
  • AND{条件}{S} 目的寄存器, 操作数1, 操作数2(C6.2.12),该指令将操作数1和操作数2相与的值写入目的寄存器,而ANDS指令会影响条件标志位,例如ANDS会根据结果影响条件标志位Z,若结果为0则会将Z置1,否则Z为0;ORR{条件}{S} 目的寄存器, 操作数1, 操作数2(C6.2.205),该指令将操作数1和操作数2相或的值写入目的寄存器;EOR{条件}{S} 目的寄存器, 操作数1, 操作数2(C6.2.85),该指令将操作数1和操作数2相或的值写入目的寄存器。
  • BIC{条件}{S} 目的寄存器, 操作数1, 操作数2(C6.2.31),该指令用于清除操作数1的某些位,并把结果放置到目的寄存器中,操作数1是一个寄存器,操作数2可以是一个寄存器,被移位的寄存器,或一个立即数。 操作数2为掩码,如果在掩码中设置了某一位,则清除这一位为0,否则相应位不变。
  • NZCV寄存器(C5.2.9)是一个专门用于存储条件标志的特殊寄存器(64位),可以用MRS指令将NZCV寄存器的值读取到普通寄存器中,如MRS X0,NZCV,其中第28-31位分别代表条件标志V、C、Z、N。

  • BFI Xd, Xn, #lsb,#width(C6.2.28),这是一个位段插入指令,该指令用Xn寄存器中的Bit[0:width]替换Xd寄存器中的从lsb开始的width个位,Xd其他位不变;UBFX Xd, Xn, #lsb, #width(C6.2.334),这是一个位段提取指令,从Xn寄存器提取位段,位段从第lsb位开始,位宽为width,然后将提取的位段写入到Xd寄存器最低比特位中,其他比特位填充0;SBFX(C6.2.234)和UBFX一样是位段提取指令,唯一的区别在于SBFX将其他比特位进行符号扩展,也就是说当提取后的字段中最高位为1时填充1,当提取后的字段中最高位为0时填充0。
  • CLZ Xd,Xn,这个指令可以计算Xn寄存器最高为1的比特位前面有几个0,并将结果存储在Xd寄存器中。
  • B Label是无条件跳转指令,不会返回,跳转范围为PC+/- 128MB。B.cond Label是条件跳转指令,其中cond是上文中提到的eq、ne、cs等条件,跳转范围为PC+/- 1MB。BX 寄存器 或 BR 寄存器,该指令跳转到寄存器指定的地址,不返回。BL Label,带返回地址的跳转指令,返回地址是当前PC+4,返回地址会存储在X30寄存器中,跳转范围为PC+/- 128MB。BLX 寄存器 或 BLR 寄存器,带返回地址的跳转指令,返回地址是当前PC+4,返回地址会存储在X30寄存器中。RET指令,从子函数里面返回,返回地址是X30寄存器中保存的地址。
  • ERET指令用于从当前的异常模式返回,可以实现模式的切换,例如从EL1切换到EL0,它会从SPSR_ELx寄存器中恢复PSTATE,并根据该寄存器的内容返回到相应的异常模式ELx,并从相应的ELR_ELx中获取返回地址。
  • 常见的比较跳转指令:CBZ 寄存器,Label,比较寄存器的值是否为0,若为0则跳转到Label处,跳转范围PC+/- 1MB。CBNZ 寄存器,Label,比较寄存器的值是否为不为0,若不为0则跳转到Label处,跳转范围PC+/- 1MB。TBZ 寄存器,#bit,Label,比较寄存器的#bit位是否为0,若为0则跳转到Label处,跳转范围PC+/- 32KB。TBNZ 寄存器,#bit,Label,比较寄存器的#bit位是否不为0,若不为0则跳转到Label处,跳转范围PC+/- 32KB。
  • ADR 寄存器,Label,该指令可以将Label的地址加载到目标寄存器中,可寻址的Label地址范围为PC+/- 1MB(这是由编码的机器码位数决定的),该指令的计算过程是通过将当前PC值和Label相对于当前PC地址的偏移量相加得到结果,这个结果是绝对地址,所以最终写入目的寄存器的也是绝对地址而不是偏移量。ADR X0,.的意思是加载当前PC值到X0(注意这里第二个操作数是一个点)。ADRP 寄存器,Label,将指定标签Label的页基地址(通常是指向该地址的高位部分4KB对齐的地址)加载到目的寄存器,可寻址的Label地址范围为PC+/- 4GB(这是由编码的机器码位数决定的),它的实现过程和ADR命令一样,最终写入目的寄存器的是Label的高位部分,要想得到整个绝对地址,可在ADRP命令后面加上命令add X0,X0,#:lo12:Label,这样X0得到的就是Label的绝对地址。LDR伪指令和ADRP指令的区别:当链接地址和运行地址相等时,LDR伪指令加载的地址等于ADRP指令加载的地址;当链接地址和运行地址不相等时,LDR伪指令加载的地址是链接地址(或称为虚拟地址),而ADRP指令加载的地址是当前运行地址的PC值+Label的偏移量,即Label在当前运行时的地址(或称为物理内存地址)(ADR指令和ADRP指令类似,返回的是运行时的物理地址)。在调试嵌入式系统或操作系统时,通常会遇到虚拟地址和物理地址不一致的情况。
  • 独占访存指令:在A64指令集中,LDXR指令尝试在内存总线中申请一个独占访问的锁,然后访问一个内存地址。STXR指令会往刚才LDXR指令已经申请独占访问的内存地址中写入新内容。

    LDXR Xd, [Xn|sp]指令从寄存器Xn|sp指向的内存地址以独占的方式(监视器会把这个内存地址标记为独占访问,保证以独占的方式来访问)加载内容到目的寄存器Xd中。STXR Wd,Xt, [Xn|sp]指令是内存独占存储指令,通常与LDXR指令配合使用(当一个线程使用LDXR加载数据后,在执行完STXR存储之前,其他线程无法干扰该数据的读取和写入,执行STXR指令后对应的地址会被监视器取消独占标记),该指令以独占的方式将Xt寄存器的内容存储到寄存器Xn|sp指向的内存地址,若成功返回0到寄存器Wd中,否则返回1表示不成功。Linux内核常用这两个独占指令来实现atomic的访问,spinlock机制可以简单地通过LDXR和STXR指令来实现。可以将这两个指令理解为加锁和解锁,实现互斥访问。在使用gdb调试时,LDXR和STXR指令之间是不能单步调试的,因为他们是原子的,调试时若执行单步调试会从LDXR指令直接跳到STXR指令之后。
  • SVC #imm指令是系统调用指令,允许应用程序通过SVC指令来自陷到操作系统里,通常会进入到ELI异常等级。HVC #imm指令是虚拟化系统调用指令,允许主机操作系统通过HVC指令自陷到虚拟机管理程片(Hpervior)中,通常会进入到EL2异常等级。SMC #imm指令是安全监控系统调用指令,允许主机操作系统感者虚拟机管理程序通过SMC指今自陷到安全监管(SecueMonitor)中,通常会进入至EL3异常等级。
  • MRS 寄存器,系统寄存器,该指令用于读取系统寄存器的值到通用寄存器中。MSR 系统寄存器,寄存器,该指令用于将通用寄存器中的值写入到系统寄存器中。
  • ARM提供了三个同步指令:DMB(Data Memory Barrier,数据内存屏障),该指令确保仅当所有在它前面的存储器访问操作都执行完毕后(注意,仅针对存储操作,因此不能保证任何指令),才提交在它后面的存储器访问操作,它保证的是内存屏障前后的内存访问指令的执行顺序。DSB(Data Synchronization Barrier,数据同步屏障),该指令比DMB严格,他确保仅当所有在它前面的存储器访问操作都执行完毕后,才执行在它后面的指令(亦即任何指令都要等待存储器访问操作)。ISB(Instruction Synchronization Barrier,指令同步屏障),该指令最严格,它会清洗流水线,以保证所有它前面的指令都执行完毕之后,才从高速缓存或内存中提取位于该指令后的其他所有指令,这可确保提取时间晚于 ISB 指令的指令能够检测到 ISB 指令执行前就已经执行的上下文更改操作的执行效果。DMB和DSB后面是可以带参数的,用于指定共享属性域以及具体的访问顺序,具体查看手册。

11.汇编指令中的一些坑:坑1:MMU没有被enable时,访问物理内存会被当成是device memory访问,ldr指令一般每次访问8个字节,例如LDR X6,MY_LABEL,如果访问的地址不是八个字节对齐,就会触发alignment异常,也就是Data Abort。可以通过将LDR X6,MY_LABEL改为LDR W6,MY_LABEL来解决这个问题;坑2:另一个对齐问题的坑如下图:

在ARM中内存可以分为normal memory和device memory,对于normal memory是支持不对齐访问的(需要enable MMU,并设置内存的属性为normal才可实现不对齐访问),可以通过设置SCTLR_ELx.A寄存器来单独设置不对齐访问时触发异常。对于device memory,不对齐访问会触发Data Abort异常,在没有enable MMU的系统中,访问DDR会被视为访问device memory。指令预取需要4个字节对齐,否则会触发异常。坑3:使用str指令来设置寄存器,一定要注意待设置的寄存器的位宽,否则会出现死机问题,例如下图中目的是写U_IBRD_REG寄存器,但可能同时将FBRD寄存器也写了。

ldxr指令的使用有很多限制,一般只能用于访问normal memory。如下图:

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com