大端序和小端序

字节存储顺序主要分为大端序(Big-endian)和小端序(Little-endian),区别如下

  • Big-endian:高位字节存入低地址低位字节存入高地址
  • Little-endian:低位字节存入低地址高位字节存入高地址

例如,将12345678h写入1000h开始的内存中,以大端序小端序模式存放结果如下
TIM图片20190805113725.png
一般来说,x86系列CPU都是Little-endian字节序,PowerPC通常是Big-endian字节序。

因为网络协议也都是采用Big-endian方式传输数据的,所以有时也把Big-endian方式称为网络字节序

下面通过一个简单的例子继续理解小端序

#include "windows.h"


BYTE b = 0x12;
WORD w = 0x1234;
DWORD dw = 0x12345678;
char str[] = "abcde";

int main(int argc, char* argv[])
{
	byte lb = b;
	WORD lw = w;
	DWORD ldw = dw;
	char* lstr = str;

	return 0;
}

通过visual studio调试一下,转到反汇编查看反汇编代码

可以看到全局变量bwdwstr的地址分别为06AA000h06AA004h06AA008h06AA00Ch。我们在内存窗口查看相应的地址,可以看到对应的数据,上面不同颜色的方框对应不同变量。
Snipaste_2019-08-05_10-41-41.png

dw这个变量来说,他的地址是06AA008h,可以看到他的数据是0x78 0x56 0x34 0x12,注意小端序是地址高位存储数据的高位,地址低位存储数据的低位

Snipaste_2019-08-05_10-29-00.png

而字符串“abcde”被保存在一个字符(char)数组str中,字符数组在内存中是连续的,此时向字符数组存放数据,无论是采用大端序还是小端序,存储顺序都相同。

还有另个知识点,就是注意到反汇编代码中的ptr了吗,逆向分析的时候是不是经常看见这个符号,知道他是干什么的吗?

PTR运算符可以重写操作数默认的大小类型,ptr的前面会有类型的声明,比如byte ptr [b(06AA000h)],他的意思从这个地址取一个byte大小的数据。比如byte ptr [dw(06AA008h)] 得到的就是0x78word ptr [dw(06AA008h)] 得到的就是0x5678,以此类推。

### Java 中大端小端序区别及用法 #### 区别 在计算机科学中,字节指的是多字节数值类型的字节排列方式。主要分为两种: - **大端 (Big-endian)**:最高有效位存放在最低地址处;即数值的高位先存储。 - **小端序 (Little-endian)**:最低有效位存放在最低地址处;即数值的低位先存储。 不同平台可能采用不同的字节方案,这取决于底层硬件架构的设计[^2]。 对于Java而言,默认情况下处理的数据是以网络字节(即大端)来操作的,但在某些场景下也需要支持本地机器的小端模式,尤其是在跨平台开发或是与其他系统的接口交互过程中[^1]。 #### 使用方法 为了实现大小端之间的转换,在Java中有多种途径可以完成这项工作。下面给出几个常见的方式来进行说明: ##### 方法一:利用`ByteBuffer` 通过设置`ByteBuffer`对象的字节顺属性(`order`)为相应类型即可轻松切换读写时遵循的大/小端规则: ```java import java.nio.ByteBuffer; import java.nio.ByteOrder; public class EndianExample { public static void main(String[] args) { short value = 0x1234; // 假设要传输这个short型变量 ByteBuffer buffer = ByteBuffer.allocate(Short.BYTES); // 设置成大端并放入数据 buffer.order(ByteOrder.BIG_ENDIAN).putShort(value); System.out.println("Big endian bytes:"); for(int i=0;i<buffer.capacity();i++){ System.out.printf("%02X ", buffer.get(i)); } System.out.print("\n"); // 清除缓冲区准备再次使用 buffer.clear(); // 改变到小端序再放一次同样的数进去 buffer.order(ByteOrder.LITTLE_ENDIAN).putShort(value); System.out.println("Little endian bytes:"); for(int i=0;i<buffer.capacity();i++){ System.out.printf("%02X ", buffer.get(i)); } } } ``` 这段程展示了如何创建一个具有指定容量的`ByteBuffer`实例,并分别以大端小端的形式向其内部填充相同的一个短整型数值,最后打印出各自的结果以便观察差异。 ##### 方法二:手动计算 当不需要频繁改变字节的时候也可以采取直接编码的方式来达到目的。这里提供了一个简单的例子用于将两个字节组合成无符号短整形,同时允许选择输入参数决定是否按小端格式解释给定的一组bytes: ```java public static int combineBytesToUnsignedShort(byte highByte, byte lowByte, boolean isLittleEndian){ if(isLittleEndian){ return ((lowByte & 0xFF) << 8) | (highByte & 0xFF); }else{ return ((highByte & 0xFF) << 8) | (lowByte & 0xFF); } } ``` 此函数接受高低两位byte以及指示当前期望解析形式(boolean flag),返回最终合成后的unsigned short integer值[^3]。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值