补码Twos Complement是计算机中表示有符号整数最常用的方法。理解补码是学习计算机底层、数字电路、芯片设计的基础。一、为什么需要补码计算机中数据用二进制表示但二进制本身没有正负的概念。为了表示负数历史上有过三种方案表示法优点缺点原码直观最高位表示符号有 0 和 -0 两个零加减法需要额外判断反码加减法稍简化仍有 0 和 -0加减法仍需特殊处理补码0 和 -0 统一加减法可以用同一套加法器电路实现略不直观核心好处CPU 只需要一个加法器就能完成加法和减法硬件电路大大简化。二、补码的计算规则对于正数和零正数的补码 原码本身最高位是符号位 0对于负数负数的补码 反码 1 原码取反含符号位除外后 1具体三步法写出该数绝对值的二进制原码按位取反0 变 11 变 0得到反码末位加 1得到补码或者一个更快的口诀从右往左数遇到第一个 1 之前的所有位保持不变第一个 1 也不变之后的位全部取反。三、详细例子8 位补码为例8 位补码能表示的范围-128 ~ 127例 15 的 8 位补码正数补码 原码5 的原码: 0000 0101 5 的补码: 0000 0101 ← 直接就是例 2-5 的 8 位补码重点方法一三步法步骤 1: 写出 |-5| 5 的原码: 0000 0101 步骤 2: 按位取反反码: 1111 1010 步骤 3: 末位加 1补码: 1111 1011所以-5 的 8 位补码 1111 1011方法二口诀法从右往左找第一个 1原码: 0000 0101 ↑ 从右往左第一个 1 在最低位 保持这个 1 和它右边不变这里它就是最低位没有右边 左边所有位取反 补码: 1111 1011例 3-1 的 8 位补码Apply步骤 1: |−1| 1 的原码: 0000 0001 步骤 2: 按位取反: 1111 1110 步骤 3: 末位 1: 1111 1111所以-1 的 8 位补码 1111 1111全是 1很好记例 4-128 的 8 位补码边界情况步骤 1: |−128| 128 的原码: 1000 0000恰好 8 位 步骤 2: 按位取反: 0111 1111 步骤 3: 末位 1: 1000 0000所以-128 的 8 位补码 1000 0000注意8 位补码能表示 -128最小负数但不能表示 128所以补码的表示范围是不对称的[-128, 127]。例 5-20 的 8 位补码步骤 1: |−20| 20 的原码: 0001 0100 步骤 2: 按位取反: 1110 1011 步骤 3: 末位 1: 1110 1100所以-20 的 8 位补码 1110 1100用口诀法验证原码 20: 0001 0100 ↑ 从右往左第一个 1位 2 保持它和右边不变 → 100 左边所有位取反 → 1110 1 补码: 1110 1100 ✓四、补码的反向解读如何从补码读出十进制规则如果最高位是0正数按普通二进制读如果最高位是1负数对补码再做一次取反 1得到的就是它的绝对值例 6补码1111 1011是多少最高位是 1是负数 取反: 0000 0100 1: 0000 0101 对应十进制: 5 所以原数是: -5 ✓验证了例 2例 7补码1000 0001是多少最高位是 1是负数 取反: 0111 1110 1: 0111 1111 127 所以原数是: -127五、补码的精髓用加法做减法这是补码最神奇的地方。下面用例子展示。例 8计算7 - 5即7 (-5)把减法转换为补码加法7 的补码: 0000 0111 -5 的补码: 1111 1011 ───────────── 相加: 1 0000 0010 ↑ 第 9 位的进位被丢弃8 位寄存器溢出 最终结果: 0000 0010 2 ✓完美用加法器实现了减法硬件无需专门的减法器电路。例 9计算-3 (-5)-3 的补码: 1111 1101 -5 的补码: 1111 1011 ───────────── 相加: 1 1111 1000 ↑ 第 9 位进位丢弃 最终结果: 1111 1000 验证: 最高位是 1是负数 取反: 0000 0111 1: 0000 1000 8 原数: -8 ✓六、不同位宽的补码补码的位宽决定了表示范围位宽表示范围-1 的补码最小负数的补码4 位-8 ~ 711111000 (-8)8 位-128 ~ 1271111 11111000 0000 (-128)16 位-32768 ~ 327670xFFFF0x8000 (-32768)32 位-2³¹ ~ 2³¹-10xFFFF_FFFF0x8000_000064 位-2⁶³ ~ 2⁶³-10xFFFF_FFFF_FFFF_FFFF0x8000_0000_0000_0000例 10-5 的 16 位补码步骤 1: |−5| 5 的 16 位原码: 0000 0000 0000 0101 步骤 2: 按位取反: 1111 1111 1111 1010 步骤 3: 末位 1: 1111 1111 1111 1011 简写: 0xFFFB七、补码的几个重要性质性质说明例子0 和 -0 唯一0 的补码只有一个 0000 0000取反 1111 1111 1 → 1 0000 0000丢弃进位 → 0000 0000最小负数没有正对应8 位中 -128 存在但 128 不能表示范围 [-128, 127] 不对称符号位扩展高位补符号位本身正数补 0负数补 1值不变8 位 1111 1011 (-5) → 16 位 1111 1111 1111 1011 (-5)取反 1 是自反操作对补码再做取反 1得到相反数-5 补码取反1 → 5例 11符号位扩展重要把 8 位的 -5 扩展为 16 位8 位 -5 补码: 1111 1011 ↑ 符号位是 1高位全补 1 16 位 -5 补码: 1111 1111 1111 1011 └────────┘ 新增的 8 位全是 1而把 8 位的 5 扩展为 16 位8 位 5 补码: 0000 0101 ↑ 符号位是 0高位全补 0 16 位 5 补码: 0000 0000 0000 0101这就是 CPU/Verilog 中的有符号扩展sign extension在指令集设计中极其常见。八、Verilog 中的补码运算示例module twos_comp_demo; reg signed [7:0] a, b; reg signed [7:0] result; initial begin a 8d7; // 7 的补码: 0000_0111 b -8d5; // -5 的补码: 1111_1011编译器自动转 result a b; // 7 (-5) 2 $display(a %0d (binary: %b), a, a); $display(b %0d (binary: %b), b, b); $display(a b %0d (binary: %b), result, result); end endmodule输出a 7 (binary: 00000111) b -5 (binary: 11111011) a b 2 (binary: 00000010)九、综合速查表8 位补码十进制二进制补码十六进制1270111 11110x7F640100 00000x4010000 00010x0100000 00000x00-11111 11110xFF-21111 11100xFE-641100 00000xC0-1271000 00010x81-1281000 00000x80十、一句话总结正数的补码 它自己负数的补码 绝对值取反 1。补码让计算机用一套加法器实现加减法是现代计算机和芯片设计的基石。需要的话我可以进一步讲解浮点数的表示IEEE 754补码乘法Booth 算法在 Verilog 中实现有符号运算的注意事项溢出检测overflow / carry 区别