1、二进制基础:计算机为什么用二进制、位与字节、十六进制表示法、二进制与十进制的转换

各位同学好,我是老周。在二进制文件的世界里摸爬滚打了十几年,今天咱们来聊聊最基础、也最容易被忽视的东西——二进制本身。

很多人觉得二进制就是一堆0和1,太简单了。嗯,确实简单。但恰恰是这种简单,造就了整个数字世界的基石。我见过不少工程师,写上层代码溜得很,一碰到二进制数据就抓瞎。说白了,就是基础没打牢。

1.1 计算机为什么用二进制?

这个问题我当年刚学计算机时也想过。为什么不用十进制?我们人类用十进制不是挺方便吗?

原因其实很朴素:物理实现上,二进制是最可靠的。

你想想看,一个开关只有两种状态:开或关。一个电压只有两种电平:高或低。一个磁畴只有两种方向:正向或反向。如果用十进制,你得区分10种不同的电压或状态——这在工程上几乎不可能做到稳定可靠。

核心原因有三点:

  • 物理实现简单:两种状态容易区分,抗干扰能力强
  • 运算规则简单:二进制加法表只有4条规则(0+0=0, 0+1=1, 1+0=1, 1+1=10),十进制加法表有100条
  • 逻辑代数基础:布尔代数只有真/假两种值,天然适配二进制

我在做嵌入式系统时遇到过一件事:某款芯片在高温环境下,3.3V的电压会漂到3.0V。如果是十进制电路,3.0V算几?但二进制电路只要区分高于2.0V还是低于0.8V,3.0V稳稳地算高电平。这就是二进制的容错优势。

1.2 位与字节

先明确两个基本概念:

  • 位(bit):二进制中的一位,取值0或1。这是计算机信息的最小单位。
  • 字节(byte):8个bit组成1个byte。这是计算机存储和处理的基本单位。

为什么是8位?不是7位也不是9位?

历史原因占大头。早期IBM的System/360用了8位字节,后来Intel的8086也用了8位,这个标准就这么延续下来了。我个人习惯把字节想象成一个8格的盒子,每个格子里放一个0或1。

单位 缩写 大小 常见用途
位 b 1 bit 标志位、开关状态
字节 B 8 bits 字符、小整数
字 word 16 bits (2 bytes) 早期CPU处理单位
双字 dword 32 bits (4 bytes) 现代CPU处理单位
四字 qword 64 bits (8 bytes) 64位系统指针大小

避坑指南:我曾经在解析一个网络协议时,把16位字段当成了2个字节来处理,结果忘了考虑字节序(大端/小端)。数据全乱了。记住:位是概念单位,字节是存储单位。读写二进制文件时,你操作的最小单位是字节,不是位。

1.3 十六进制表示法

二进制写起来太长了。一个32位的整数,写成二进制是32个0和1,谁看得下去?

十六进制就是二进制的"缩写"。4位二进制对应1位十六进制,简洁又直观。

二进制 十六进制 二进制 十六进制
0000 0 1000 8
0001 1 1001 9
0010 2 1010 A
0011 3 1011 B
0100 4 1100 C
0101 5 1101 D
0110 6 1110 E
0111 7 1111 F

我建议你把这16个对应关系背下来。真的,不骗你。做二进制分析时,看到0x4A能立刻反应出0100 1010,速度会快很多。

在代码里,十六进制通常用0x前缀表示:

// C语言示例
unsigned char data = 0x4A;  // 二进制 0100 1010
unsigned int magic = 0x1A2B3C4D;

注意:十六进制只是表示法,不是数据本身。0x4A和十进制的74是同一个数,只是写法不同。很多新手会混淆"表示形式"和"实际值",调试时吃了不少亏。

1.4 二进制与十进制的转换

这部分是基本功。我直接上方法,不绕弯子。

二进制 → 十进制

方法:按权展开求和。每一位的值乘以2的幂次,然后加起来。

二进制: 1 0 1 1 0 1
权值:   2^5 2^4 2^3 2^2 2^1 2^0
       32  16   8   4   2   1

计算: 1×32 + 0×16 + 1×8 + 1×4 + 0×2 + 1×1
     = 32 + 0 + 8 + 4 + 0 + 1
     = 45

十进制 → 二进制

方法:除2取余,逆序排列。

十进制: 45

45 ÷ 2 = 22 余 1  ← 最低位
22 ÷ 2 = 11 余 0
11 ÷ 2 = 5  余 1
5  ÷ 2 = 2  余 1
2  ÷ 2 = 1  余 0
1  ÷ 2 = 0  余 1  ← 最高位

逆序读取余数: 101101

我刚开始学的时候,总觉得除2取余太慢。后来发现一个技巧:记住2的幂次表,用减法来做更快。

2^0=1, 2^1=2, 2^2=4, 2^3=8, 2^4=16, 2^5=32, 2^6=64, 2^7=128

十进制 45:
45 - 32 = 13  → 第5位是1 (32)
13 - 8  = 5   → 第3位是1 (8)
5  - 4  = 1   → 第2位是1 (4)
1  - 1  = 0   → 第0位是1 (1)

结果: 101101 (第5、3、2、0位为1)

个人经验:做二进制文件分析时,我几乎不用手动转换。用计算器或者写个小脚本就行。但理解转换原理很重要——它能帮你建立"数值感"。看到0xFF知道是255,看到0x100知道是256,这种直觉在调试时非常有用。

知识体系总览

下面这张图把本章的核心知识点串起来了。你可以把它当作一个思维导图来看。

二进制基础 · 知识体系 二进制基础 为什么用二进制 物理实现简单可靠 运算规则极少 适配布尔代数 位与字节 bit:最小信息单位 byte:8 bits = 1 B word/dword/qword 十六进制表示法 4位二进制 = 1位十六进制 0x前缀表示 0-9 A-F 共16个符号 进制转换 二进制→十进制:按权展开求和 十进制→二进制:除2取余逆序 十六进制↔二进制:4位映射

这张图把四个核心知识点串在了一起。你注意看,所有分支都指向同一个中心——二进制基础。后面的章节会在这个基础上不断叠加新的概念。

好了,第一章就到这里。内容不多,但都是硬通货。把这些基础打牢,后面解析ELF、PE、Mach-O这些二进制格式时,你才不会晕头转向。