跳至正文
这篇笔记的目录
回到学习目录
技术开发

二进制与补码

位模式本身只是 0/1;把它解释为无符号数、有符号补码、地址或指令,要看上下文和位宽。

#RISC-V#xv6#计算机系统#学习笔记

一句话: 位模式本身只是 0/1;把它解释为无符号数、有符号补码、地址或指令,要看上下文和位宽。

本章导航#

位与进制 · 位运算 · 有符号数 · 溢出与扩展 · RISC-V 实例

学习目标#

  • 在二进制、十进制之间转换。
  • 计算补码表示、可表示范围和逻辑/算术移位结果。
  • 区分位宽固定的硬件运算与高级语言的溢出规则。

1. 位、字节与进制#

一个 bit 是一个二进制位,只能为 0 或 1。一个 byte 通常为 8 bit。十进制数按 10 的幂展开,二进制按 2 的幂展开:

1101₂ = 1×2³ + 1×2² + 0×2¹ + 1×2⁰ = 13₁₀

十进制转二进制可反复除以 2 并倒序读取余数:13 → 余数 1、0、1、1 → 1101₂

写法精确含义例子
bit单个位1 bit
byte / B8 位1 B = 8 bit
kB / MBSI 十进制单位1 kB = 1000 B
KiB / MiBIEC 二进制单位1 KiB = 1024 B

代码和旧教材常把 KB 写成 1024 B;严格书写时,建议用 KiB 表示 1024 B。

2. 位运算#

下表按单个位演示;多位运算逐位进行:

ABA AND BA OR BA XOR B
00000
01011
10011
11110
1010
& 1100
= 1000
1010
^ 1100
= 0110

NOT 会在指定位宽内翻转每一位。真实操作必须明确位宽:4 位的 NOT(1010) 是 0101,8 位则是 11110101。

3. 有符号数和补码#

无符号数#

n 位无符号数范围是 0 到 2ⁿ−1。8 位例子:00000000 = 0,11111111 = 255。

二进制补码#

常见 n 位有符号整数使用二进制补码,范围为 −2ⁿ⁻¹ 到 2ⁿ⁻¹−1。正数按普通二进制表示;负数可对其绝对值逐位取反再加 1。

以 8 位 −5 为例:

+5 00000101
逐位取反 11111010
加 1 11111011 ← −5 的 8 位补码

可用权重法验证:最高位权重为 −2⁷,其他位权重依次为 2⁶…2⁰;11111011 = −128 + 64 + 32 + 16 + 8 + 0 + 2 + 1 = −5。

位宽无符号范围有符号补码范围
80…255−128…127
320…2³²−1−2³¹…2³¹−1
640…2⁶⁴−1−2⁶³…2⁶³−1

补码只有一个 0,并能让加法器用同一套位运算处理加法和减法。固定 n 位的运算结果可理解为对 2ⁿ 取模。

4. 溢出与扩展#

8 位补码中,127 + 1 的位运算结果为 10000000;将其解释成补码就是 −128。位模式得到结果该结果是否超出有符号范围是两件事。

  • 对补码加法,若两个操作数同号而结果异号,则发生有符号溢出。
  • 无符号加法若超出位宽,则高位进位被截掉,相当于模 2ⁿ。
  • C 语言的有符号整数溢出属于未定义行为;不要把某次硬件回绕结果当成 C 语言保证。

扩展位宽时要区分:

  • 零扩展: 高位填 0,保持无符号数值。
  • 符号扩展: 复制原最高位,保持补码数值。

移位也要区分:逻辑右移左侧补 0;算术右移通常复制符号位。左移在数学上像乘 2,但固定宽度下高位可能丢失,且语言层面的溢出规则可能不同。

5. RISC-V 中的位宽#

RISC-V 指令按寄存器宽度和指令语义操作位模式。RV32 的整数寄存器为 32 位,RV64 为 64 位。以 addi 为例,立即数是有限宽度且按规范符号扩展;它不是任意大的十进制常量。

RV64 的 lw 读取 32 位并符号扩展到 64 位;lwu 则零扩展。这个区别在读反汇编和调试数据时很重要。

自测: 8 位补码中 −1 是多少?答案是 11111111;符号扩展到 16 位后仍表示 −1:1111111111111111。

核心结论: 先问“几位、按什么类型解释”,再读二进制;位模式不是天然的正数或负数。

下一篇: 03 · RISC-V 寄存器04 · RISC-V 指令详解