chapter7——处理字节顺序

1.定义

字节顺序定义数据在计算机系统中的存储格式。它描述存储器中地址的最高有效位(MSB)和最低有效位(LSB)的位置。对于数据始终以32位形式保存在系统存储器中的真正32位系统,字节顺序没什么实际意义,但是对于要将字节或16位半字映射到系统存储器中32位字的系统,字节顺序不匹配就会影响数据完整性。

字节顺序结构有两种类型,大端模式(Big Endian, BE)和小端模式(Little Endian, LE)。大端模式将MSB保存在最低存储器地址处,小端模式将LSB保存在最低存储器地址处。多字节数据的最低存储器可以认为是数据的起始地址。
下表是分别按大端模式和小端模式保存在存储器中的32位十六进制数0xAABBCCDD。字节0表示最低存储器地址。

在这里插入图片描述

在按原生数据类型(如32位)引用数据时,两种字节顺序所存储的多字节数据域是相同的。但在按字节或半字类型访问数据时,字域次序与系统的字节顺序配置相关。

在以半字方式处理时,存储器地址必须是2的倍数。

2.小端模式和大端模式的比较

  • 在小端模式中,因为最低位字节偏移值为0,并首先访问,访问1、2、4或更长字节数的汇编语言指令能按同样方式处理所有格式。同样,由于地址偏移量和字节数之间1:1的关系(偏移0对应字节0),多精度的数学程序也相对容易编写。
  • 在大端模式中,因为先访问高阶字节,所以很容易通过查看偏移量为0的字节来判断数值的正负。所以无须接收所有字节包就能知道符号信息。由于数字同时也以其打印出来的次序保存,所以对从二进制转化为十进制的程序特别有效。

大多数嵌入式通信处理器和定制解决方案在数据层采用大端模式(PowerPC,SPARC等)。因为为这些处理器所写的老程序通常遵循网络字节顺序(大端模式)。

某些CPU可以通过设置处理器寄存器而在大端或小端模式(双字节顺序)间切换。

3.处理字节顺序不匹配的问题

  • 在单个系统中字节顺序不会产生什么问题。只有在两台电脑通信时它才会产生影响。每个处理器和每种通信协议必须选择一种字节顺序。因此,如果需要通过存储器通信,两种不同字节顺序类型的处理器就会产生冲突。类似地,小端模式处理器在试图访问大端模式网络时需要用软件对字节重新排序。如果计算机无意间从共享存储区域或文件中读取以相反格式写入的二进制数据时,字节顺序的差异就会导致问题。
  • 另一个字节顺序会导致问题的领域是网络通信。由于在同一网络中可能存在不同类型(大端模式或小端模式)的处理器,它们之间必须彼此通信。因此网络协议栈和通信协议也必须定义字节顺序。否则,不同字节顺序的两个节点可能无法通信。
    在实际应用中,TCP/IP族中的所有协议层都定义为大端模式。也就是说,各层头中的16或32位值(如IP地址、包长度或校验和)必须首先发送或接收最高有效字节。TCP/IP协议所使用的多字节整数表达方式有时称为网络字节顺序。即使各终端计算机都是小端模式的,它们之间所传输的数据必须在通过网络前先转化为网络字节顺序,然后在接收端再转化为小端模式。

4.访问32位存储器

  • 字节地址和32位数据总线上特定位的关系如下所示:
    在这里插入图片描述
  • 下表为按8位、16位和32位访问大端与小端模式系统时的数据字节映射。
    在这里插入图片描述
    在这里插入图片描述

5.处理字节顺序不匹配

在包含若干IP的SOC中必然会发生字节顺序不匹配的问题,几乎所有第三方公司的IP都支持与处理器同样的字节顺序类型。处理字节顺序不匹配问题的最简单方法是为系统选择一种字节顺序类型(即,小端模式或大端模式),并将全部其他不同字节顺序的模块转化为目标字节顺序类型。

典型的字节顺序类型由系统中CPU体系结构的实现决定,所以建议目标的字节顺序类型与处理器的字节顺序类型相匹配。在对第三方IP选型时要考虑的另一个因素是确认其是否支持双字节顺序结构,以使IP可以方便地编程为大端模式或小端模式以与系统无缝集成。

有两种连接相反字节顺序外设的方法。根据应用的需要,要么选择将地址保持稳定(在地址不变处字节保持在同一地址)或者将位顺序保持稳定(在数据不变处地址改变)。

  • 保持数据完整性(数据不变)

由于不同的字节顺序模式下多字节域具有不同的字节地址,因此,如果将多字节域作为单个条目进行操作,那么当其在各IP之间移动时,必须保留该条目的位次序。

对于跨字节边界的多位域也同样如此。比如,一个含16位控制寄存器编程模型的IP。如果控制寄存器位域 [8:7] 定义了控制域,那么要求对于所有访问控制寄存器的操作,要保持该16位之间的稳定关系,而不再与字节顺序有关。

为了理解匹配字节顺序以使数据位顺序完整的过程,以由小端模式的外设接收连续帧并将接收到的数据通过DMA/CPU保存到系统存储器举例。
在这里插入图片描述
接收到的连续帧以Type、H2、H1和H0的顺序保存在外设存储器中。帧中的域可能跨多个字节并不在字节边界处终止,例如状态域可能是12位。所以对于应用程序来说,数据不会因为字节顺序转换而改变就显得很重要,因为这样软件就可以以该顺序处理数据了。

在这里插入图片描述
在上图中,数据按小端寻址保存在外设的存储器中。现在当数据要传送到大端模式的系统RAM中时,必须保证数据位顺序保持不变。为了用硬件达到这个目的,需要对访问外设RAM的存储器的地址进行修改。对地址的改动基于要传送数据的大小,如下所示:
在这里插入图片描述在这里插入图片描述
使用上面的逻辑,对地址总线最后两个LSB取反,数据不变,对应HDL代码如下:

assign	le_ram_addr[31:0] = (Size = 8-bits) ? 
							{ram_addr[31:2], ~ram_addr[1], ~ram_addr[0]};
							(Size = 16-bits) ? 
							{ram_addr[31:1], ~ram_addr[0], ~ram_addr};

assign	le_ram_data[31:0] = data[31:0];

使用上面的方案可以使字节顺序转换对软件透明,并能确保数据完整性在字节顺序转换过程中不会被破坏。

从小端设备到大端存储器,并保持数据不变的数据流如下所述:
1)DMA发出对外设存储器的读字节操作。
2)若系统产生的地址为0x00,在数据变化的实现中,小端模式设备RAM所看到的地址为0x03。
3)设备存储器对该地址解码,访问位31:24即Type域。
4)外设输出该值为{Type, 0x000000} (32位输出)。
5)DMA对系统的大端存储器发出按字节方式的写操作。
6)再次产生0x00地址(字节访问)。
7)大端存储器将该访问解码为写入位31:24。
8)由于来自于小端存储器的数据处于同样的字节区域,因此可以保持数据的完整性并将数据保存在大端RAM中。
9)对其他需要从外设RAM传输到系统RAM中的数据继续进行该操作。
10)16位和32位访问过程与上面所述相同,只是地址需要加以改变。

  • 地址不变

与数据不变的字节顺序转换相比,某些应用程序或系统不需要数据保持特定的次序,但是需要在字节顺序转换后数据字节保持在同样的地址区域。这时就需要使用地址不变的字节顺序变换。

参考同一个接收连续帧的例子,对于地址不变的系统,访问字节Type的地址偏移量永远是0x3。而在前一节中,访问该字节需要使用不同的地址偏移量。为了用硬件实现该过程,需要修改或交换从外设RAM中读到的数据值,RTL代码如下所示:

assign	le_ram_addr[31:0] = ram_addr;
assign	le_ram_data[31:0] = data[0:31];

字节转换顺序如下图所示:

在这里插入图片描述

使用地址不变方式,从小端外设到大端存储器的数据流如下所述:
1)DMA发出对外设存储器的读字节操作。
2)若系统产生的地址为0x00,地址不变的实现使地址值始终相同。
3)外设RAM对该地址解码,访问位[7:0]或H0区域。
4)外设输出的数据为{0x000000, H0} (32位输出)。由于字节顺序匹配时地址不变,给系统RAM的数据变为{H0,0x000000} 。
5)DMA发出对系统大端存储器的字节写操作。
6)再次产生地址0x00(字节访问)。
7)大端存储器将该访问解码为写入位[31:24] 。
8)在字节顺序转换完成后,从小端存储器读出的数据已处在同样的地址区域,把地址存入大端RAM。
9)对其他需要从外设RAM传递到系统RAM的字节继续进行以上操作。
10)对16位或32位的访问,上述过程是相同的,只需将输出的数据进行交换即可。

  • 软件字节交换

交换字节是实现字节顺序转换的一种方式。在由应用程序本身决定字节顺序的系统中,该模式是有用的。因此,无需用硬件实现这种字节顺序匹配过程。字节顺序中性代码的字节交换方法使用字节交换控制来决定是否必须进行字节交换过程。

在软件中通常使用的各种字节交换方法有:
1)交换汇编指令。
2)用于交换字节的软件库宏。
3)协议特定的交换函数。
4)制定的交换函数。

该方法的限制在于,在软件中实现交换功能会增加额外开支。位交换所引起的软件开支虽然存在,但是在需要处理的包的数量很多时开支引起的问题很容易修复,特别是在高频处理器中。

6.字节顺序中性代码

避免由字节顺序所引发问题的最好方法是在设计中使用字节顺序中性。可以通过两种途径完成这一任务:

  • 将字节顺序选项作为软件可配置的选项。
  • 在设计(IP)中使用字节使能,并将解码的任务留给系统或SOC。

7.字节顺序中性编码指南

字节顺序中性代码可以通过标识外部软件接口实现,遵循下面的指南来访问这种接口:

  • 数据存储和共享存储体,数据必须以独立于字节顺序体系结构的格式保存。
  • 字节交换宏,宏(或包装器)能用于所有多字节数据接口进行交换操作。
  • 数据传送,可以建立特定宏来从网络读数据或将数据写到网络中。根据输入数据的类型(如果它与本地主机字节顺序格式不匹配),可用宏来进行批量字节的交换。
  • 位域,避免定义跨越字节边界的位域。
  • 编译器指令,在使用会影响到数据存储(对齐、包装)的编译指令时要小心。指令在不同编译器之间并不是总能移植的。

遵守字节顺序中性指南能使代码有更好的移植性,可以使同一源码运行在不同字节顺序结构的处理器上,从而减少了平台移植时的负担。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 什么是 Java 异常? Java 异常是指程序执行期间可能发生的错误或异常情况,例如除以零、数组越界、空指针引用等。当这些异常发生时,Java 虚拟机会抛出一个异常对象,并且程序的执行流程将被中断。 2. Java 异常处理机制有哪些关键字和语句? Java 异常处理机制包括以下关键字和语句: - try:用于包含可能会抛出异常的代码块。 - catch:用于捕获指定类型的异常,并在捕获到异常时执行相应的处理代码。 - finally:用于包含无论是否发生异常都需要执行的代码块。 - throw:用于抛出指定的异常对象。 - throws:用于声明可能会抛出指定类型异常的方法。 3. Java 中的异常分为哪几类? Java 中的异常分为两大类:Checked Exception 和 Unchecked Exception。 Checked Exception 是指在编译时就能够检查出来的异常,例如 IOException、ClassNotFoundException 等。程序必须显式地处理这些异常,否则编译不通过。 Unchecked Exception 是指在运行时才能检查出来的异常,例如 NullPointerException、ArrayIndexOutOfBoundsException 等。程序可以选择处理这些异常,但不处理也不会导致编译错误。 4. 请简要说明 try-catch-finally 的执行流程。 当程序执行到 try 块时,Java 会尝试执行其中的代码。如果在 try 块中抛出了异常,则会将异常对象传递给 catch 块进行处理。catch 块会匹配异常类型,如果匹配成功,则执行相应的处理代码。如果 catch处理完异常后,程序需要继续执行,则会执行 finally 块中的代码。如果 finally 块中也抛出了异常,则该异常会覆盖 try 或 catch 块中的异常。 如果 try 块中没有抛出异常,则 catch 块不会被执行。如果 finally 块中抛出异常,则该异常会覆盖 try 块中的异常。 5. 什么是异常链? 异常链是指在处理异常时,将一个异常对象作为另一个异常的原因,并将它们组合成一个异常链。这样做的好处是,在抛出异常时可以同时传递多个异常信息,从而更加清晰地表示异常发生的原因。 6. 请简要说明 try-with-resources 的作用和使用方法。 try-with-resources 是 Java 7 中引入的语法,用于自动关闭实现了 AutoCloseable 接口的资源。在 try 块中声明需要使用的资源,Java 会在 try 块执行完毕后自动关闭这些资源,无需手动调用 close 方法。 try-with-resources 的语法如下: ``` try (Resource1 r1 = new Resource1(); Resource2 r2 = new Resource2()) { // 使用资源 } catch (Exception e) { // 处理异常 } ``` 7. 请简要说明 Java 中的文本 IO。 Java 中的文本 IO 主要包括两种类:Reader 和 Writer。Reader 用于读取字符流,而 Writer 用于写入字符流。 Java 中常用的 Reader 类包括 InputStreamReader、FileReader 和 BufferedReader,常用的 Writer 类包括 OutputStreamWriter、FileWriter 和 BufferedWriter。这些类提供了各种方法来读取和写入字符流,并且可以处理多种编码格式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值