数据和运算
程序的生命周期从源程序(源文件)开始。源程序实际上就是由 0 和 1 组成的位序列。
一般用 ASCII 标准来表示文本字符,实际上是用一个字节的整数值来表示一种字符。
源文件中每个文本行都是以看不见的 '\n' 结束的。
只由 ASCII 字符组成的文件成为文本文件,其他都是二进制文件。.cpp 文件就是文本文件。
系统中的所有信息都是由一串比特(bit:位)表示的,区分不同数据对象的唯一方法就是根据上下文。
定点数
大多数计算机系统采用补码来表示机器数,符号位加入运算,加法方便实现减法,零的表示唯一,多表示一个负数
分为无符号数和有符号数。无符号数所有位都是数值位,有符号数的最高位一位是符号位。无符号整数都是二进制非负数,不需要过多的解释。重点在于有符号数。
关于有符号数,正数的符号为0,三码(原码,反码,补码)相同,数值=真值。负数的符号1,反码和原码分别对应每位求反,补码是在反码的基础上,末位加1。
简化反码的中间步骤,关于原码和补码的转化规则如下:1内取反,负数生效。意思是将二进制码最左边的1和最右边的1中间的所有位取反。在负数时生效即最左边的1即符号位的1.
例如:原码10010110的补码是11101010。
补码的符号位相同时,数值位越大,码值越大。且不同于反码和原码的两种,0的补码只有一种,所以可以多表示一个-128。
移码是补码的符号位取反,实际含义是真值+偏移值
一些需要记忆的常用值
无符号:
1B = 0~2552B = 0~655354B = 0~4294967295有符号:
1B = -128~1272B = -32768~327674B = -2147483648~2147483647
移位运算
逻辑移位
shl eax,1;shl ebx, cl;:无符号数,空位补零算数移位:正数三码空位补零,负数原0反1,补码左0右1.
算术移位中,补码左移的前提条件是,原最高有效位和原符号位相同
双符号位的移位操作,只有低符号位需要参加移位操作
加减运算
加减运算(补码)
- 原码 符号位和数值位判断求之
溢出判断
加数符号相同,结果符号不同,产生溢出。
最高数值位进位和符号位进位异或,结果为1则溢出。
变形补码:两符号位进行判断:符号位不同表示溢出,高位符号位代表真正的符号。
乘法运算
乘法是通过加法和移位操作进行的,两个n位数相乘,需要进行n次加法操作和n次移位操作
1. 符号位 单独异或运算
2. 数值位 X Y
res = 0.00000
X = 0.ABCDE
Y = 0.abcde
for(i in edcba){
res = res + i * X;
res >> 1;//因为都是绝对值,没有正负,所以移位都是高位补零,所以是逻辑移位
}
3. 整合符号位和数值位
// Y的每一位起判断作用,每判断一次,Y的最低位就没用了
// 因此ACC和MQ的寄存器放一起,ACC放乘积高位,MQ放乘数和乘积低位
// 矫正法
Y是正数按照原码运算规则,移位按照补码的算数移位进行。
Y是负数按照原码运算规则,移位按照补码的算数移位进行,在最后结果上加上[-x]_b进行矫正
// 比较法
双符号位 例题看王道e2.8
R = 00.00000
X = UU.ABCDE
Y = N.abcde_f
while ._没相遇{
if e_f == 0_0 RY >>1
if e_f == 1_0 RY + [-x]_b >>1
if e_f == 0_1 RY + x_b >>1
if e_f == 1_1 Ry >>1
}
._相遇 完成最后一次加法操作
合并RY即为所求补码
除法运算
具有N位尾数的合法除法,逻辑移位N次,上商N+1次
浮点数
IEEE754 :1+8+23格式,尾数原码纯小数,阶码定点正数:移码 指数e真值要减去127
偏移量127 因为阶码全0表示指数负无穷,阶码全1表示正无穷大
浮点数规格化
- 左移阶码-1,右移阶码+1
溢出判断:
对阶操作不会引起溢出
右归和尾数舍入都可能引起阶码上溢
左归时可能引起阶码下溢
尾数溢出时结果不一定溢出
加减运算
对阶
尾数求和
规格化 溢出风险
舍入 溢出风险