itpestudy c c++
C 概述
计算机组成
计算机基本结构为 5 个部分,分别是运算器、控制器、存储器、输入设备、输出设备,这 5 个部分也被称为冯诺依曼模型。
accumulator
(computer science) a register that has a built-in adder that adds an input number to the contents of the register
arithmetic logic unit
/əˈrɪθmətɪk/
the type of mathematics that deals with the adding, multiplying, etc. of numbers
控制单元负责控制 CPU 工作,逻辑运算单元负责计算,而寄存器可以分为多种类
通用寄存器,用来存放需要进行运算的数据,比如需要进行加和运算的两个数据。
程序计数器,用来存储 CPU 要执行下一条指令「所在的内存地址」,注意不是存储了下一条要执行的指令,此时指令还在内存中,程序计数器只是存储了下一条指令「的地址」。
指令寄存器,用来存放当前正在执行的指令,也就是指令本身,指令被执行完成之前,指令都存储在这里。
一个程序执行的时候,CPU 会根据程序计数器里的内存地址,从内存里面把需要执行的指令读取到指令寄存器里面执行,然后根据指令长度自增,开始顺序读取下一条指令。
总线是用于 CPU 和内存以及其他设备之间的通信,总线可分为 3 种:
地址总线,用于指定 CPU 将要操作的内存地址;
数据总线,用于读写内存的数据;
控制总线,用于发送和接收信号,比如中断、设备复位等信号,CPU 收到信号后自然进行响应,这时也需要控制总线;
当 CPU 要读写内存数据的时候,一般需要通过下面这三个总线:
首先要通过「地址总线」来指定内存的地址;
然后通过「控制总线」控制是读或写命令;
最后通过「数据总线」来传输数据;
指令
MIPS 的指令是一个 32 位的整数,高 6 位代表着操作码,表示这条指令是一条什么样的指令,剩下的 26 位不同指令类型所表示的内容也就不相同,主要有三种类型R、I 和 J。
R 指令,用在算术和逻辑操作,里面有读取和写入数据的寄存器地址。如果是逻辑位移操作,后面还有位移操作的「位移量」,而最后的「功能码」则是再前面的操作码不够的时候,扩展操作码来表示对应的具体指令的;
I 指令,用在数据传输、条件分支等。这个类型的指令,就没有了位移量和功能码,也没有了第三个寄存器,而是把这三部分直接合并成了一个地址值或一个常数;
J 指令,用在跳转,高 6 位之外的 26 位都是一个跳转后的地址;
指令从功能角度划分
数据传输类型的指令,比如 store/load 是寄存器与内存间数据传输的指令,mov 是将一个内存地址的数据移动到另一个内存地址的指令;
运算类型的指令,比如加减乘除、位运算、比较大小等等,它们最多只能处理两个寄存器中的数据;
跳转类型的指令,通过修改程序计数器的值来达到跳转执行指令的过程,比如编程中常见的 if-else、switch-case、函数调用等。
信号类型的指令,比如发生中断的指令 trap;
闲置类型的指令,比如指令 nop,执行后 CPU 会空转一个周期;
加和运算 add 指令是属于 R 指令类型:
add 对应的 MIPS 指令里操作码是 000000,以及最末尾的功能码是 100000,这些数值都是固定的,查一下 MIPS 指令集的手册就能知道的;
rs 代表第一个寄存器 R0 的编号,即 00000;
rt 代表第二个寄存器 R1 的编号,即 00001;
rd 代表目标的临时寄存器 R2 的编号,即 00010;
因为不是位移操作,所以位移量是 00000
key words
enum
enumerate
枚举
to name things on a list one by one
extern
external
volatile
/ˈvɑːlətl/
易变的
change suddenly and unexpectedly.
1 |
|
system("pause");
gcc
windows explore
地址栏选择路径 —》 直接输入CMD
以当前文件夹地址打开CMD
gcc helloworld.c -o helloworld.exe
helloworld.exe
linux gcc
vi hello.cinsert
esc
-> :wq
apt install gcc
gcc hello.c -o hello./hello
预处理
gcc -E hello.c -o hello.i
头文件展开
宏定义替换:将宏名替换为宏值
1 |
|
替换注释为空行
展开 条件编译
1 |
|
编译
检查语法错误
生成汇编语言的汇编文件
gcc -S hello.i -o hello.s
汇编
将汇编指令翻译成二进制机器编码
gcc -c hello.s -o hello.o
链接
gcc hello.o -o hello
数据段合并
数据地址回填
库引入
printf
1 |
|
8
c = 8
3 + 5 = 8
3 + 5 = 8
debug
f11 逐语句,会进入函数内部
f10 逐过程,不会进入子函数
调试 —》 窗口 —》 反汇编
visual studio
ctrl + k, ctrl + f 格式美化代码
ctrl + k, ctrl + c 注释
ctrl + k, ctrl + u 取消注释
常量
“hello”, ‘A’, -10, 3.1415#define PI 3.1415 //推荐
const int a = 10; //只读变量
1 |
|
printf(“s = %.2f, l = %f\n”, s, l);%.2f
保留2位小数,会进行四舍五入
extern 关键字, 只是声明外部符号(标识符)extern int a;
sizeof关键字
返回unsigned int类型printf("size of int = %u\n", sizeof(int));
1 |
|
size of int = 4
size of short = 2
size of long = 4
size of long long = 8
size of a = 4
size of b = 2
size of c = 4
size of d = 8
size of e = 4
size of f = 2
size of g = 4
size of h = 8
int a = 10;
sizeof int
sizeof a
char
1 |
|
ch = A
ch = 65
ch = a
\0
char a = ‘\0’;
printf(“a = %d\n”, a); // 0
浮点数
1 |
|
a = 3.141
b = 0013.457
c = 3200.000
d = 0.002
除2方向取余法 10 –> 2
原码,反码,补码
原码:最高位为符号位
反码:
正数与原码相同
负数,最高位为1,其他位取反
补码:为计算机中存储负数的形式
正数与原码相同
负数,最高位为1,其他位取反 + 1
00000000 为 0
11111111 为 -128