CSAPP小记

补码的非

一个补码x的加法逆元即为补码的非。

加法逆元+x =0,通常为 补码 x 真值 的相反数的补码,记为 -x(最小数除外,为自身)。
用处:一个负数 的 补码的非为 该负数相反数的补码,且正数补码等于原码,可以快速算出真值,真值取反即为最初的负数。所以可以根据补码的非快速算出一个负数补码的真值。

方法:
在这里插入图片描述在这里插入图片描述

例子:补码0xfffffffa的真值为多少?
找到0xfffffffa最右边的1,将其左边所有位取反得到:0x00000006,该补码非真值为6,所以0xfffffffa真值为-6.

数组越界

原因:对越界的数组元素的写操作会破坏存储在栈中的状态信息(比如返回地址),当程序使用被破坏的状态,试图重新加载寄存器或执行ret指令时,就会出现很严重的错误。
一种常见的状态破坏称为缓冲区溢出(buffer overflow),字符串数组的长度超过了为数组分配的空间。可能遭受缓冲区溢出攻击。
对抗策略:1.栈随机化;2.栈破坏检测,存储特殊的金丝雀值(哨兵值);3限制可执行代码区域。

程序优化的方法

gcc自动优化:

1.一个文件内内联函数替换优化函数调用。

2.循环展开(n次循环 缩小为n/k 次)
用优化等级3及以上调用GCC,可自动执行循环展开

3.重新结合变换
在满足结合律(或者基本满足)的情况下,更改结合顺序,使不依赖上下文的数据先结合在一起。可靠性不如循环展开和多个累积变量。

需要手动进行的优化:

1.消除循环的低效率
代码移动:识别要执行多次(例如在循环里)但是计算结果不会改变的计算,移到循环前面。

2.减少过程调用

3.消除不必要的内存引用
因为指针很少被编译器优化,所以应该尽量少用指针,数组也相当于指针引用。
很多时候可以可以先用局部变量充当中介,因为局部变量存放在寄存器中,循环结束,再放进数组(指针引用)中。
例子:

读写数组元素要读写内存,先用局部变量来代替数组元素效率更高,因为局部变量存储在寄存器中。

//效率高
vector<int> singleNumber(vector<int>& nums) {
    int XORsum=0,classify=0;
    for(int num:nums)
        XORsum^=num;
    classify=XORsum&(-XORsum);
    int a=0,b=0;
    for(int num:nums){
        if(classify&num)
            a^=num;
        else
            b^=num;
    }
    return {a,b};
//效率低
vector<int> singleNumber(vector<int>& nums) {
    vector<int> res{0,0};
    int XORsum=0,classify=0;
    for(int num:nums)
        XORsum^=num;
    classify=XORsum&(-XORsum);
    for(int num:nums){
        if(classify&num)
            res[0]^=num;
        else
            res[1]^=num;
    }
    return res;
}

3.多个累积变量
在满足结合律(或者基本满足)的情况下,将一个循环运算分成两个并行,最后再结合。

4.使用AVX向量指令,多路并行向量运算。

5.对于条件判断语句,使用“功能性的”风格书写,使其产生条件数据传送而不是条件控制转移。
“功能性”风格:用条件操作来计算值,然后用这些值来更新程序状态。
对立于“命令式”风格:用条件语句来有选择的更新程序状态。
但不是所有条件行为都能用条件数据传送来完成,有时候无法避免用条件控制转移。
P380

6.程序剖析
使用程序剖析工具

SSE、AVX

在这里插入图片描述在这里插入图片描述

进程

定义:进程的经典定义就是一个执行中程序的实例。系统中的每个程序都运行在某个进程的上下文(context)中。上下文是由程序正确运行所需的状态组成的。这个状态包括存放在内存中的程序的代码和数据,它的栈、通用目的寄存器的内容、程序计数器、环境变量以及打开文件描述符的集合。

内存地址分析:https://blog.csdn.net/qq_40586164/article/details/107550072

线程:
有些进程同时干不止一件事,比如Word,它可以同时进行打字、拼写检查、打印等事情。在一个进程内部,要同时干多件事,就需要同时运行多个“子任务”,我们把进程内的这些“子任务”称为线程。线程是最小的执行单元。
(1)线程就是运行在进程的上下文中的逻辑流(是在进程中活动的对象),线程由内核自动调度。

(2)线程都有自己的线程上下文,包括线程ID,线程栈,栈指针,程序计数器,通用目的寄存器,条件码。

(3)所有运行在一个进程的线程都共有虚拟地址空间。

虚拟内存

https://www.jianshu.com/p/a7633d7687c2
虚拟内存是计算机系统内存管理的一种技术。
缓存:它使得应用程序认为它拥有连续的可用的内存(一个连续完整的地址空间),而实际上,它通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换。
内存管理:操作系统为每个进程提供了独立的虚拟地址空间,可以有效的管理内存。
内存保护:虚拟内存可以控制进程对内存系统的访问,比如PTE的许可位可以控制对一个虚拟页面内容的访问,如修改只读内容会触发段异常。
目前,大多数操作系统都使用了虚拟内存,如Windows家族的“虚拟内存”;Linux的“交换空间”等。

地址翻译
在这里插入图片描述

存储结构

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值