CPU眼中的编程知识

发布时间:2022-06-08 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了CPU眼中的编程知识脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

参考资料:https://www.bilibili.com/video/BV1bm4y1Q7Cn/?spm_id_from=333.788

 

初始化:准备堆栈,中断向量表,硬件初始化,然后跳转到main函数

 

main函数:

其汇编指令与普通函数完全一样,main函数是默认起点,可以指定其他函数为起点。

 

变量:

cpu不能直接访问内存,只能通过寄存器,配合“方括号”,间接访问内存

rip寄存器存放着cpu下一条指令的地址

 

this指针:是每一个成员函数必备的默认参数

输入this指针就是输入对象的地址,当调用成员函数时,对象会把自己的地址当作this指针输入给成员函数

 

构造函数:

也带有this指针,派生类的构造会调用基类的构造函数

如果存在虚函数,构造函数会记录虚函数表的地址,并保存在对象实例里面

 

虚函数:在函数体上与普通函数没有区别

普通函数的地址是确定的,这就是静态绑定

虚函数的地址通过rdx寄存器的值来获得,这就是动态绑定,本质是获取隐藏的成员变量V的值(虚函数表的地址),再从虚函数表中找到对应虚函数的地址

当存在虚函数时,类会生成隐藏的成员变量 V, 其中存放着虚函数表的地址,根据便宜找到对应虚函数的地址,存放入rdx中,然后 call rdx

 

 

多态:合法且安全的类型转换;调用相同名称的函数,会根据对象的实际类型执行不同的函数版本

复用基类的共性,展现自己的特性

特性通过虚函数来体现

可以用多态来避免,相似、重复的代码,容易维护和扩展

 

指针变量|数组指针|野指针

共性:和普通变量没有区别

特性:*操作,指针变量用于定位内存

野指针:指向位置不可知的指针,常见出现原因:没有初始化;变量内存释放后,指针变量还保存着该变量的内存地址

*操作是对内存的读写操作,指针变量的加减运算是指针偏移

 

 

指针:可以访问任意地址,除非被MMU阻止

a.x == (&a)->x

作用:0拷贝(只需要复制地址);驱动硬件,像访问内存一样访问i/o寄存器;无穷变身,兼容各种数据类型

 

i++与++i

++i是左值,i++是右值

++i不用构建临时变量,效率高

GCC中i++ 与 ++i 的原则:都是函数调用,都有返回值;i++返回常量,++i返回变量i的引用/指针

 

数组:一段连续的内存;传递数组本质是传递指针;高维数组和一维数组保存方式一样

传递指针;增加长度参数,防止越界

数组往高地址越界会立刻崩溃,往低地址则不会,但与其他变量冲突时,会出错;

常见出错情形:strcpy,strcat,memcpy,memmove;用全局变量索引数组

 

函数调用:

线程有一段内存记录了函数调用轨迹

堆栈是一段普通的内存,用来存放每次函数调用的返回地址和其他信息(参数,栈变量,其他数据,所以使用rbp寄存器);一直堆栈没有返回,就会堆栈溢出

 

{函数}|栈帧|堆栈|栈变量|调用栈

栈的使用是从高端地址向低端地址蔓延,esp标识栈顶的内存地址,ebp标识main函数的栈帧基地址

操作系统提供内存,cpu提供ebp和esp两个寄存器;正括号{用来保护上层主调函数的栈帧,并设置被调函数的栈帧,反括号}用来放弃被调函数的栈帧,恢复主调函数的栈帧;ebp作为栈帧基地址,配合偏移就可以读写函数体中的临时变量(栈变量)

 

传值 vs传指针 | 传引用 | 参数传递

在cpu眼里,传值与传指针就是传递的值不同;传递参数就是给寄存器赋值,寄存器是主调函数向被调函数输入参数的载体(传递对象需要靠堆栈)

 

进程 vs 线程 | MMU系列

进程有空间独立性,没有MMU(内存管理单元)就没有进程的概念,就全是线程,用线程使用多任务编程会很便利,但一个线程崩溃,该进程的所有的线程就都会崩溃,因此网络服务器一般都是多进程

进程:应用程序的执行副本,进程拥有文件资源,硬件资源,权限信息,进程信息,cpu资源,内存分页;但程序执行只需要内存和CPU

线程:cpu中的线程是真实的,程序中的多线程需要cpu的支持

协程:轻量级的线程,routine,用一个线程来管理所有的线程,

 

虚拟内存 | 虚拟地址 | 地址映射 | 页表 | MMU

高20位表示在页表中的偏移,低12位表示在页块中的偏移

总结:MMU通过操作系统或程序员提供的页表,进行虚拟地址到物理地址的转换;每个进程都有一张自己的页表,页表不同则说明内存隔离,如果相同或部分相同,则说明在做内存共享,线程没有页表,共享同一个进程的页表;分页也适用于虚拟地址,能有效减少地址映射表的体量,页表里的值也可以是扇区信息。

一级页表与二级页表

 

左值(本身地址) |  右值(创建临时变量)

 

goto(凡是用到跳转的地方,都会用到goto的汇编指令)

 

模板 | 泛化

泛化:避免重复的代码,需要使用模板

总结:编译器自动补充代码;对程序员不可见,只能黑盒测试;会引入编译问题;使用stl标准模板库比较安全

 

二义性,注意比较等号两侧对象的数据类型

竞争 | 线程切换 | 上下文

竞争往往是因为多线程,多进程同时读写共享资源造成的;加锁来解决竞争;锁有性能消耗,因此要注意轻重缓急

 

volatile 易变的,不稳定的

用于编译器优化:编译器会把他认为值不会变的变量,当常量对待,缩减汇编指令,volatile就是阻止这种优化

 

大端和小端

多字节的数据存储时有大端和小端两种,在物联网时代,各种设备要互联,需要解决这个问题,解决方式是字符串,也就是json格式,char字节没有大小端之分。

脚本宝典总结

以上是脚本宝典为你收集整理的CPU眼中的编程知识全部内容,希望文章能够帮你解决CPU眼中的编程知识所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签: