1. 核心解构

  • 补码 (Two’s Complement)
    • 本质:将减法转化为加法,利用模运算(Modulo Arithmetic)消除减法逻辑。
    • 设计哲学:统一了正负数的运算逻辑,且“0”的表示唯一。
    • 关键特性
      • 正数:符号位为0,其余同原码。
      • 负数:符号位为1,其余位取反加1。
      • 不对称性:8位带符号数范围是 。注意那个无法取反的最小负数(-128),它是溢出判断的常见坑点。
    • 另一种理解方式:符号位位权为 ,而后面位权不变
    • 符号位可以参与运算

注意

补码十六进制表示时,可能为xxH,最后的 H 表示 hex

2. 安全探针:无符号数与扩展

  • C 语言中的类型转换陷阱
    • 符号扩展 (Sign Extension):带符号数变长时,用符号位填充高位。
    • 零扩展 (Zero Extension):无符号数变长时,用0填充高位。
    • CTF 实战
      short si = -32768; // 0x8000
      unsigned short usi = si; // 0x8000
      int i = si; // 0xFFFF8000 (符号扩展,值仍为 -32768)
      unsigned ui = usi; // 0x00008000 (零扩展,值变为 +32768)
      // 符号转换时,根据短的类型来扩展
      // 长 -> 短,直接去掉高位
      // 位数相同,机器数不变,更换翻译方式
      警惕:当有符号数被错误地当成无符号数处理时,小负数会瞬间变成巨大的正数,导致缓冲区长度检查失效。

3. 关联链接

  • C语言漏洞:整数溢出(Integer Overflow)通常发生在无符号数回绕或符号位被篡改时。
  • 汇编语言SLT (带符号比较) vs SLTU (无符号比较) 的底层区别。
  • 移码

易错点

特殊情况

  • 在 8 位补码中,正数最大是 0111 1111 (+127)。

  • 负数最小本该是 1111 1111 (-1) 到 1000 0001 (-127)。

  • 剩下的 1000 0000 怎么办? * 如果我们对 +127 (0111 1111) 加 1,得到 1000 0000。逻辑上 ,但符号位变成了 1(负数)。

  • 如果对其取反加一:~1000 0000 + 1 = 0111 1111 + 1 = 1000 0000。它自己是自己的补码。

  • 规定:这是人为规定的最小负数 ,即 -128。它没有对应的原码和反码