字节序的定义与背景

N0va7
2025-09-22 / 0 评论 / 2 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2025年09月22日,已超过254天没有更新,若内容或图片失效,请留言反馈。

多字节数据在内存中的排列方式

在计算机中,一个变量的值往往由多个字节组成,例如 32 位整数占 4 个字节。
不同的体系结构在将这些字节存入内存时,其排列顺序可能不同。
举例:int a = 0x12345678,这个数值由四个字节组成:0x12, 0x34, 0x56, 0x78

为什么要关心字节序

因为不同系统间的数据传输需要统一标准,否则读取结果可能出错。

两种常见字节序

小端序(Little-Endian)

特点:低位字节存放在低地址处,高位字节存放在高地址处。
举例:0x12345678

  • 内存排列: [0x78][0x56][0x34][0x12]
    使用平台:Intel x86 / x86_64

代码示例:

#include <stdio.h>

int main() {
      int a = 0x12345678;
      unsigned char *p = (unsigned char *)&a;
      printf("Value of a: 0x%x\n", a);
      printf("Memory layout:\n");
      for (int i = 0; i < 4; i++) {
      printf(" byte %d: 0x%x\n", i, p[i]);
      }

      return 0;
}

输出结果:

Value of a: 0x12345678
Memory layout:
 byte 0: 0x78
 byte 1: 0x56
 byte 2: 0x34
 byte 3: 0x12

这样可以形象的看出来小端序在内存中是如何排序保存的

大端序(Big-Endian)

特点:高位字节存放在低地址处,低位字节存放在高地址处。
举例:0x12345678

  • 内存排列: [0x12][0x34][0x56][0x78]
    使用场景:
  • 网络协议(如 TCP/IP 标准)
  • 某些嵌入式平台(如 PowerPC

小结

字节序只影响内存中的排列方式,不改变数值本身。

字节序对程序的影响

网络通信问题

不同主机架构(大端 vs 小端)传输数据时,如果不统一字节序,接收端可能解读错误。
TCP/IP 使用大端序,主机通常使用 htonl() 等函数转换为网络字节序。

PWN/CTF 中的符号判断、爆破

利用程序溢出漏洞时,输入的 payload 与内存中的布局严格相关,字节序决定目标地址的写入方式。
如:覆盖返回地址时,需按照小端顺序构造字节串。

二进制反汇编对字节序的敏感性

汇编代码操作内存时,会按照平台默认字节序解释指令中的立即数和地址。
错误理解字节序将导致调试分析结果出现偏差。

判断字节序的常用方法

C语言

int check_endian() {
      int a = 1;
      return (*(char *)&a == 1) ? 0 : 1;
      // 返回0:小端;返回1:大端
}

Python

import sys
print(sys.byteorder) # 输出 little 或 big

GDB 动态调试查看内存

直接观察变量在内存中的字节排列方式,判断平台字节序。

x/4xb &value

字节序转换函数(网络相关)

头文件

#include <arpa/inet.h>

主机转网络

  • htons :Host to Network Short(16位)
  • htonl :Host to Network Long(32位)

网络转主机

  • ntohs :Network to Host Short
  • ntohl :Network to Host Long

测试代码

#include <stdio.h>
#include <stdint.h>
#include <arpa/inet.h>

int main() {
      uint32_t host_value = 0x12345678;

      // 主机字节序 → 网络字节序(大端)
      uint32_t net_value = htonl(host_value);

      // 网络字节序 → 主机字节序
      uint32_t recovered_value = ntohl(net_value);
      printf("原始主机字节序: 0x%x\n", host_value);
      printf("转换为网络字节序: 0x%x\n", net_value);
      printf("还原为主机字节序: 0x%x\n", recovered_value);

      // 直接打印字节内容
      unsigned char *ptr = (unsigned char *)&net_value;
      printf("网络字节序的字节表示: ");
      for (int i = 0; i < 4; i++) {
            printf("%02x ", ptr[i]);
      }
      printf("\n");
      return 0;
}
原始主机字节序: 0x12345678
转换为网络字节序: 0x78563412
还原为主机字节序: 0x12345678
网络字节序的字节表示: 12 34 56 78

一些常识

CPU 是支持哪种字节序的?可否切换?

大多数通用 CPU(x86/x86_64)默认使用小端序。
某些 RISC 架构支持双模式(如 ARM 支持 bi-endian),但通常设为固定模式。

混用架构或跨平台软件中的字节序陷阱

多平台程序需显式处理字节序,避免不同架构产生的数据不一致。
常用中间件或序列化框架(如 protobuf)内置处理机制。

为什么现代平台倾向使用小端

小端序对低位访问更加友好,适合逐字节处理。
在低层硬件设计上更易实现,因此成为工业主流

0

评论 (0)

取消