C03 · 第 1 章 · 数据与电路
二进制与数值表示
说明位宽、无符号整数、补码、溢出、字节序与定点比例,并计算编码转换和内存字段。
本章目标
- 确定给定位宽下无符号整数和补码的范围。
- 完成整数与二进制编码之间的转换。
- 判断符号扩展、截断和加法溢出。
- 按字节序读取内存数据,并计算定点数的分辨率。
本页目录
位序列与数值范围
处理器和内存保存有限长度的位序列。一个位只有零和一两种取值,八个位组成一个字节。为了把位序列解释成整数、字符或地址,程序还需要确定类型、位宽和编码规则。同一组位按无符号整数读取时得到非负值,按补码整数读取时可能得到负值;这种区别来自解释规则,存储单元中的位本身没有改变。
我们把最低有效位记为 ,把最高有效位记为 ,其中位宽 是正整数,每个 属于集合 。下标从右侧开始,编号与书写方向需要区分。无符号解释把每个位乘以对应的二次幂,然后相加,因此最高位的权重最大。
位宽为 的无符号整数表示为
共有 种不同位序列,最小值对应全零,最大值对应全一。地址、长度和计数常采用这种表示,但具体数据类型仍由语言和接口规定。
十六进制每位对应四个二进制位,适合抄写字节内容。转换时先按四位分组,再把每组映射为一个十六进制数字。例如十六进制的字母 A 到 F 分别表示十进制的十到十五。书写中的前缀用于标明进制,不占存储位;读取调试器输出时应先确认显示进制,再进行数值比较。
补码与符号扩展
补码把最高位的权重改为负数,其余位保持原来的正权重。位宽为 时,数值范围关于零不对称,负数比正数多一个。我们用相同位序列的无符号值 表示补码值 ,便于检查转换:
由此得到补码范围 。对范围内的正数取负时,逐位取反后加一得到负数的编码;最小负数的正值超出同一位宽的范围,因此对它取负需要额外位宽或明确的异常处理。补码零只有一种表示,这使零比较和加法电路的组织较为直接。
给定字节 1110 1101,求其无符号值、八位补码值和扩展到十六位后的编码。按无符号权重求和,我们得到 。最高位为一,所以补码值为 。扩展时复制原符号位,结果是 1111 1111 1110 1101,十六进制为 0xFFED;其无符号值为 ,减去 后仍为 。如果在左侧补零,得到的值会变成 ,因此扩展方式必须随原类型确定。
符号扩展保留有符号数值,零扩展保留无符号数值。截去高位则通常改变数值,只有被截去的部分满足对应扩展规则时才保持原值。把宽整数转换为窄整数前,应检查目标类型的范围;对外部文件字段尤其需要验证长度和符号约定,以免把负数误读成巨大的长度。
固定位宽加法与溢出
一个只保留低 位的加法器产生模 的结果。无符号相加时,最高位之外的进位说明数学和超出表示范围;补码相加时,应检查两个同号操作数是否得到异号结果。这两种判定针对不同解释,单独查看最高位进位无法判断所有补码溢出。
用八位补码计算 。两个编码分别是 0110 0100 和 0011 1100,逐位相加得到 1010 0000,保留的位序列按无符号数解释为 ,按补码解释为 。数学和超出八位补码最大值 ,所以发生有符号溢出。再计算 :1111 1111 加 0000 0001 得到九位结果 1 0000 0000,低八位为零。这里有最高位进位,但数学和零处于补码范围内,有符号运算没有溢出。两次计算分别检查数学范围,结论与符号判据一致。
硬件结果还需要与编程语言规则区分。RISC-V 基础整数加法保留低位结果;在 C 和 C++ 中,有符号整数溢出属于未定义行为,不能用处理器的低位行为直接推断程序语义。编写范围检查时,我们应在运算前比较边界,或在更宽且足够的类型中计算,再核对结果是否适合目标类型。
位移也依赖类型和指令。逻辑右移在左侧补零,算术右移通常复制符号位;对负数的整数除法还要核对舍入方向。按位与、或、异或对各位分别运算,常用于掩码。设置某位时使用按位或,清除某位时与对应反掩码相与,读取某位时先掩码再判断是否为零。
字节序与内存读取
当一个数占多个字节时,内存地址顺序与数值高低位之间还存在字节序约定。小端序把最低有效字节放在较低地址,大端序把最高有效字节放在较低地址。两种约定都保留字节内部的位权关系,不需要把一个字节的位逐个倒转。
例如一个三十二位数 0x12345678 从地址 开始存储,小端字节顺序为 78 56 34 12,大端顺序为 12 34 56 78。读取网络报文或文件时,应按格式规定组合字节,避免直接把字节缓冲区强制解释成主机整数。对齐要求与字节序是独立问题:即使字节顺序正确,某些平台仍可能限制多字节读写的起始地址。
字符编码进一步说明了类型信息的重要性。一个字节既可能是整数的一部分,也可能是文本编码的一部分。文本的字符数量、编码字节数量和屏幕显示宽度分别计量不同对象,处理中文文件时不能把它们直接等同。二进制格式应明确字段宽度、编码、字节序和允许范围,接收方才能逐项恢复数据。
定点数与精度
位序列也能表示带小数的数值。一种定点约定是在整数解释之外,统一乘以一个固定比例。例如把八位补码整数乘以四分之一,则相邻数值间隔为四分之一,范围从负三十二到三十一点七五。小数点的位置由约定保存,实际字节中无需单独存储一个小数点字符。处理传感器读数时,这种方法能直接把整数编码与物理单位联系起来,但乘除运算后需要重新处理比例。
浮点表示则另外保存指数,使不同大小的数使用不同间距。有限位数仍只能表示有限多个数,十进制中有限位的小数未必具有有限长度的二进制展开。计算所得结果因此可能经过舍入,比较浮点计算结果时需要结合问题的误差范围。整数溢出、浮点舍入和文本解析分别来自不同规则,定位数值错误时应逐项核对数据类型与转换步骤。
数值表示练习
求十二位无符号整数与补码整数的表示范围,并核对两者包含的整数数量。
查看解答
十二位无符号范围是零到四千零九十五;十二位补码范围是负二千零四十八到二千零四十七。两个范围各包含四千零九十六个整数。
写出负五的八位补码和十六进制编码,再用无符号值减去模数核对答案。
查看解答
五的八位编码为00000101,取反加一得11111011,即十六进制FB。按无符号解释为二百五十一,减去二百五十六恢复负五。
对字节 0xA6 分别保留低四位、保留高四位和设置最低位,写出三种运算及其结果。
查看解答
十六进制A6按二进制是10100110。与0F相与保留低四位得到06;与F0相与保留高四位得到A0;或01设置最低位后得到A7。
相邻地址中依次保存字节 34 12,分别按小端和大端十六位整数读取,求十六进制与十进制结果。
查看解答
按小端序组合为十六进制1234,即十进制四千六百六十;按大端序组合为3412,即一万三千三百三十。两个数均小于十六位补码上限。
数字表示参考资料
1 Basics of Information: Computation Structures
Chris Terman · 2017 · Massachusetts Institute of Technology
打开官方来源RV32I Base Integer Instruction Set, Version 2.1
RISC-V International
打开官方来源MIT 6.004 的信息表示课程讨论位序列、编码与数值表示,可结合本章的补码算例阅读。RISC-V RV32I 规范规定整数寄存器及算术指令的低位结果,适合核对硬件运算规则。