“我不知道你们的名字,”冯·诺伊曼拍拍前两个士兵的肩,“你们两个负责信号输入,就叫‘入1’、‘入2’吧,”他又指指最后一名士兵,“你,负责信号输出,就叫‘出’吧。”他伸手拨动三名士兵,“这样,站成一个三角形,出是顶端,入1和入2是底边。”[...]冯·诺伊曼接过来分给三名士兵,每人一白一黑,说:“白色代表0,黑色代表1。好,现在听我说,出,你转身看着入1和入2,如果他们都举黑旗,你就举黑旗,其他的情况你都举白旗,这种情况有三种:入1白,入2黑;入1黑,入2白;入1、入2都是白。”[...]“这三个人组成了一个计算系统的部件,是门部件的一种,叫‘与门’。”冯·诺伊曼说完停了一会儿,好让皇帝理解。”
摘录来自 《三体》刘慈欣
逻辑运算符
与(·)(&&)
或(+)(||)
非(Ᾱ,表达式上边加个横线)(!)
异或(⊕)
表达式(这里的乘
和加
是与
和或
)
Ai+Bi如果两个数相同,加一块后一定是0(先不考虑进位),否则一定是1,所以可以直接用异或门进行计算
因为可能有前面的进位Ci-1,所以计算一次后需要与低位的进位再通过一次异或门,这样就能求出Si
只有Ai与Bi同时为1时需要进位,也可能是Ai+Bi第一次通过异或门后得到的数与Ci-1同时为1时需要进位,不管哪个符合都需要进位
所以Ai和Bi通过一次与门,Ai+Bi第一次通过异或门后得到的数和Ci-1通过一次与门,然后这两个结果通过一次或门就可以得到Ci
这样就可以得到一个电路图
对蓝色框部分进行封装就可以变为一位全加器(full adder,简称FA)
心平气和,学不会就摆烂,也不是什么重点
根据FA的表达式,如果计算两位数相加
不仅能计算和/差,还能生成相应的标志信息
为了加快加法运算速度,实际电路一定使用多级先行进位方式
OF(Overflow Flag): 溢出标志,溢出时为1,否则为0
SF(Sign Flag): 符号标志,结果为负数时为1,否则为0
ZF(Zero Flag): 零标志,结果为0时为1,否则为0
CF(Carry Flag): 进位/借位标志,进位/借位时为1,否则为0
A-B<0时,CF=1;溢出时OF=1
记忆方法 | 解释 | 是否有意义 |
---|---|---|
Zero零 | ZF=1表示结果F为0 | 对无符号和有符号数都有意义 |
Overflow溢出 | OF=1表示带符号整数运算 | 对无符号数无意义 |
Signal信号 | SF表示结果的符号 | 对无符号数无意义 |
Carry进位 | CF表示无符号整数运算时的进位,判断是否发生溢出 | 对有符号数无意义 |
仅当两符号相同的数相加或两个符号相异(其实还是同符号相加)的数相减才可能产生溢出
一般用异或门来实现溢出判断电路
计算时,左边出现溢出,将溢出位丢掉
判断溢出的方式
采用一位符号法
采用一位符号位根据数据位的判断情况判断溢出
双符号法/模4补码
模4补码有模2补码的所有优点,且更容易检查溢出问题
模4补码存储时只需要一个符号位
模4补码计算时(在ALU中)需要两个符号位
最高位代表真正的符号,低位符号参与移位操作
两个符号的意义
算术移位的对象是有符号数,移位过程中符号位保持不变
原码的算数移位:符号位保持不变,数值位进行移位
右移:高位补0,低位舍弃。如果舍弃的低位=0,相当于➗2,否则会丢失精度
左移:低位补0,高位舍弃。如果舍弃的高位=0,相当于✖️2,否则会出现严重误差
反码的算数移位
补码的算数移位
正数原反补相同所以参考原码
负数右移:高位补1,低位舍弃(同反码)
负数左移:低位补0,高位舍弃(同原码)
规律:负数补码中,最右边的1及其右边同原码,左边同反码
当作无符号数的算数移位
乘法运算由累加和右移操作实现
是一种有符号数的乘法
最多进行n次移位,n+1次加法运算
Booth算法的移位规则
yn(高位) | yn+1(低位) | 操作 |
---|---|---|
0 | 0 | 部分积右移一位 |
0 | 1 | 部分积加[X]补,右移一位 |
1 | 0 | 部分积加[-X]补,右移一位 |
1 | 1 | 部分积右移一位 |
除法运算由累加和(逻辑)左移实现
符号扩展
正数符号位不变,扩展位填充0
负数原码表示和正数相同,符号位为1
负数补码符号位不变,附加位用1(整数)或0(小数)进行填充
Ox8FA0
扩展为32位为OxFFFF 8FA0
1100 0000
,则其十六进制为OxFFFF FFC0
该方法商符和商值分开进行
商符由两个操作数的符号位异或形成
该方法符号位和数值位一起参加运算,商符自然形成
根据被除数和除数的符号决定做加法还是减法
上商的原则根据余数和除数的符号位共同决定
最后一步商置1
xxxxxxxxxx
201int main() {
2 //例1
3 // x的补码为 1110 1111 0001 1111
4 short x1 = -4321;
5 // 无符号位y的二进制为 1110 1111 0001 1111 真值61215
6 unsigned short y1 = (unsigned short) x1;
7 printf("x1=%d\ny1=%u\n\n", x1, y1);// %u是按unsigned int输出
8 // x1=-4321
9 // y1=61215
10
11 //例2
12 // x2 1111 1111 1111 1111
13 unsigned short x2 = 65535;
14 // y2 1111 1111 1111 1111 真值-1
15 short y2 = (short) x2;
16 printf("x2=%u\ny2=%d", x2, y2);
17 // x2=65535
18 // y2=-1
19 return 0;
20}
当大字长变量向小字长变量强制类型转换时
短字长整数到长字长整数的转换时
char为8位无符号整数,转换为int时高位补0即可
xxxxxxxxxx
251int main(){
2 //例1
3 // int 占用32位(4B)
4 //x: 0x000286a1
5 //u: 0xffff7751
6 int x = 165537, u = -34991;
7 //y: 0x86a1
8 //v: 0x7751
9 short y = (short) x, v = (short) u;
10 printf("x=%d, y=%d\n", x, y);//x=165537,y=-31071
11 printf("u=%d, v=%d\n", u, v);//u=-34991,v=30545
12
13 //例2
14 //x1: 0xef1f
15 //y1: 0xffffef1f
16 short x1 = -4321;
17 int y1 = x1;
18 //u1: 0xef1f
19 //v1: 0x0000ef1f
20 unsigned short u1 = (unsigned short)x1;
21 unsigned int v1 = u1;
22 printf("x=%d, y=%d\n", x1, y1);//x=-4321, y=-4321
23 printf("u=%d, v=%d\n", u1, v1);//u=61215, v=61215
24 return 0;
25}
0800H
,i的机器数为01234567H
- 则地址0800H
表示的内容为67H
例1:
251struct asd1{
2 char a;
3 int b;
4 short c;
5};//12字节
6
7struct asd2{
8 char a;
9 short b;
10 int c;
11};//8字节
12
13struct asd3{
14 char a;
15 char b;
16 short c;
17 int d;
18};//8字节
19
20struct asd4{
21 char a;
22 short b;
23 char c
24 int d;
25};//12字节
C语言结构体中不同的声明顺序导致结构体占用的空间也不一样