首页 > 其他分享 >CSAPP

CSAPP

时间:2024-07-31 21:30:45浏览次数:7  
标签:CSAPP int 地址 0000000000000000 gdb main 断点

深入理解计算机系统

0x ff 杂项

Instruction set Architecture:ISA,指令集体系架构

软件和硬件之间的一层抽象层

冯诺依曼计算机,即程序存储型计算机

重要思想:程序就是一系列被编码了的字节序列(看上去和数据一模一样)


https://www.cnblogs.com/SovietPower/p/14877143.html

0x 00 参考资料 && lab

official:

官网

实验


note:

视频详解

笔记参考视频的源码


lab:

比较详细的Attack,Data,Boom Lab参考

Boom,Attack,Shell Lab

全部实验的详细参考–知乎

全部实验的详细参考–CSDN

全部实验的详细参考–Github


video:

导读 导读笔记

小视频复习


book:

学生版重点知识

讲师版重点知识


lab操作流程
# 1.datalab:
在源文件 bits.c 中完善函数即可
./dlc bits.c 	 // 用于检查程序是否合法,是否使用了程序规定的符号
make btest   	 // btest是评分(检查对错工具),每次执行btets前都要重新make一下
./btest bits.c   // 评分

# 2.bomblab
./bomb
输入答案
导读P3-52分钟有第一关的实操

# 3.attacklab
./hex2raw < att1.txt > attraw1.txt // 将字节序列at t1转换为字符串attraw1
./ctarget -q -i attraw1.txt     //测试答案
// (https://github.com/wuxueqian14/csapp-lab/tree/master/Attack%20Lab)

0x 01 二进制

内存中存储的是电压,然后通过(不知道)某种方式抽象为数字01,然而计算机的内存太大了,以致于01的个数实在太多了,于是,我们把原有的0和1分块,并再次抽象为0,1…。

![img](file:///C:\Users\24072\AppData\Roaming\Tencent\Users\2407217576\QQ\WinTemp\RichOle\7E[W6J9]YPX$8MS~3CCM[DG.png)

加入内存中有n bit,每m bit分为一块,则最多可以分为2^m块,因为m bit的排列组合数为2 ^ n个序列(sequence)

例如十进制数字123,它应该表示为1*10^2 + 2*10^1 + 3*10^0,所以这里的123准确来说应该是一个sequence,而不是一个数。

数是一个比较唯心的抽象的概念,你说一个数3,它可以是十进制序列3,也可以是二进制序列11…,3和11都是这个真正的(唯心的)3,这些序列之间是一一对应的,不仅如此,他们的运算也是一一对应的。十进制的序列1+2,对应的二进制下序列为1+01

取反对称:对称轴的两侧是相反数

对于1,2,3,4,他们分别取反对称于-1,-2,-3,-4

对于二进制000,001,010,011,他们分别取反对称于111,110,101,100

IMAGE

0x 02 二进制运算

位运算的循环圈:

IMG

​ (int类型有符号数)

img

​ (int类型无符号数)

通过这张图,你可能会更好地理解补码和无符号数运算是在mod 2^n 下计算的意义。

看一下树状数组lowbit函数

int lowbit(int x) {
    return x & -x; // <==> x & (~x + 1);
}

这个函数为什么能求得最后一个1所在位置的代表的权值呢?

首先 -x,其实就是x的补码。关于补码,我们有一个求补码的方法:从右到左直到第一个1保持不变,后面的位取反,我们将x和x的补码做与运算,最后得到的结果一定是这样的形式:00..010..0,最后一个1左侧全为0,右侧也全为0。

#include <iostream>
using namespace std;

unsigned func1(unsigned x) {
    // 输出一个无符号数x,判断x在十六进制下的的每一位是不是字母
    // 如果该位是字母就返回1,否则返回0
    // 并以一个16进制数的形式返回
    unsigned x1 = (x & 0x22222222) >> 1;
    unsigned x2 = (x & 0x44444444) >> 2;
    unsigned x3 = (x & 0x88888888) >> 3;
    // printf("[1]:%04x\n[2]:%04x\n[3]:%04x\n", x1, x2, x3);
    return x3 & (x2 | x1);
}

unsigned func2(unsigned x) {
    // 输出一个无符号数x,判断x在十六进制下的每一位是不是字母
    // 如果所有位都是字母返回1,否则返回0
    x = func1(x); //得到了每一位的结果
    x = x & (x >> 16); // 每次判断一半
    x = x & (x >>  8);
    x = x & (x >>  4);
    return x;
}

unsigned func3(unsigned x) {
    // bigCount
    unsigned c;
    c = (x & 0x55555555) + ((x >>  1) & 0x55555555);
    c = (c & 0x33333333) + ((c >>  2) & 0x33333333);
    c = (c & 0x0f0f0f0f) + ((c >>  4) & 0x0f0f0f0f);
    c = (c & 0x00ff00ff) + ((c >>  8) & 0x00ff00ff);
    c = (c & 0x0000ffff) + ((c >> 16) & 0x0000ffff);
    return c;
}

int main()
{
    unsigned x = 0x1;
    // printf("0x%X = %X\n", x, func1(x));
    // printf("0x%X = %X\n", x, func2(x));
    printf("0x%X = %d\n", x, func3(x));
    
    return 0;
}

0x 03 浮点数

为什么 IEEE 754浮点数Float类型的bias=127而不是128?

其实这也没有一个官方的说法,不过为了让自己接受这个设定,我们可以从两个角度考虑:

  1. 首先,bias采用127时绝对值的范围比较对称
  2. 其次,bias采用127时最大的指数是127比bias=128时的126大,虽然只大1,但是我们直到指数的增长是“爆炸”的,因此其表示的范围也大得多。

浮点的根据exp和frac分为三种情况:

  1. exp=111..1,指数全1。此时又分为两种情况:(1)当frac全0时表示无穷大,根据符号位又分为正无穷和负无穷。(2)frac不全为0,表示NaN,一种未定义行为。(可以这样区分无穷和NaN,由于未定义的行为有很多,因此需要根据frac进一步区分,所以frac不是固定的全0,(胡乱猜的),可以这样记忆)。
  2. exp=000..0,指数全0。表示不规格化的浮点数。这里的主要目的是为了拓展精度和范围(往值小的方向)。
  3. else,规格化浮点数。

将一个无符号数转换为一个浮点数的表示形式并保存在一个无符号数字中

IEEE 754浮点数十六进制相互转换

关于浮点数舍入的讨论

#include <iostream>
#include <cstring>
#include <stdint.h>
#include <algorithm>

using namespace std;

uint32_t uint2float(uint32_t u){ // 将一个服务号数u转换成浮点数存储的形式
    
    // 特判
    if (u == 0x00000000)
    {
        return 0x00000000;
    }
    
    // 找到最后一个1的后面的一个位置,求得该1后面还有多少个数
    int n = 31;
    while (n >= 0 && (((u >> n) & 0x1) == 0x0))
    {
        n = n - 1;
    }
    cout << "n: " << n << endl;
    
    uint32_t e, f; // exp, frac
    // <= 0000 0000 1.111 1111 1111 1111 1111 1111 : 32位
    // u的位数<=24,此时再隐藏一个1,就<=23位,于是frac就可以保存所有位,不需要舍入
    if (u <= 0x00ffffff)
    {
        // no need rounding
        uint32_t mask = 0xffffffff >> (32 - n); // mask就是frac的掩码
        f = (u & mask) << (23 - n);             // f = u & mask得到frac,但还需要左移移动到最右侧[frac00..0],而不是[00..0frac]
        e = n + 127;
        printf("e: 0x%x, f: 0x%x\n", e, f);
        return (e << 23) | f;
    }
    // >= 0000 0001 0000 0000 0000 0000 0000 0000 
    // 总位数>=25,一位可以隐藏,还剩下至少24位,frac无法全部保存,需要舍入(rounding)
    else
    {
        // expand to 64 bit for situations like 0xffffffff
        uint64_t a = 0;
        a += u;
        // compute g, r, s
        uint32_t g = (a >> (n - 23)) & 0x1;
        uint32_t r = (a >> (n - 23 - 1)) & 0x1;
        uint32_t s = 0x0;
        for (int j = 0; j < n - 23 - 1; ++ j)
        {
            s = s | ((u >> j) & 0x1);
        }
        // compute carry
        a = a >> (n - 23);
        // 0    1    ?    ... ?
        // [24] [23] [22] ... [0]
        if (r & (g | s) == 0x1)
        {
            a = a + 1;
        }
        // check carry
        if ((a >> 23) == 0x1) /
        {
            // 0    1    ?    ... ?
            // [24] [23] [22] ... [0]
            f = a & 0x007fffff; // 0x0000 0000 0111 1111 1111 1111 1111 1111只保留frac
            e = n + 127;
            return (e << 23) | f;
        }
        else if ((a >> 23) == 0x2) 
        {
            // 1    0    0    ... 0
            // [24] [23] [22] ... [0]
            e = n + 1 + 127;
            return (e << 23);
        }
    }
    // INF as default error
    return 0x7f800000; // 0 1111 1111 000 0000 0000 0000 0000 0000
}

int main()
{
    int x;  cin >> x;
    printf("%x", uint2float(0x10000000));
    
    return 0;
}

0x 04 时序电路和组合电路

原文链接:


数字电路根据逻辑功能的不同特点,可以分成两大类,一类叫组合逻辑电路(简称组合电路),另一类叫做时序逻辑电路(简称时序电路)。组合逻辑电路在逻辑功能上的特点是任意时刻的输出仅仅取决于该时刻的输入,与电路原来的状态无关。而时序逻辑电路在逻辑功能上的特点是任意时刻的输出不仅取决于当时的输入信号,而且还取决于电路原来的状态,或者说,还与以前的输入有关。

时序电路,是由最基本的逻辑门电路加上反馈逻辑回路(输出到输入)或器件组合而成的电路,与组合电路最本质的区别在于时序电路具有记忆功能。

时序电路的特点是:输出不仅取决于当时的输入值,而且还与电路过去的状态有关。它类似于含储能元件的电感或电容的电路,如触发器、锁存器、计数器、移位寄存器、存储器等电路都是时序电路的典型器件,时序逻辑电路的状态是由存储电路来记忆和表示的。

时序电路和组合电路的区别:
时序电路具有记忆功能。时序电路的特点是:输出不仅取决于当时的输入值,而且还与电路过去的状态有关。组合逻辑电路在逻辑功能上的特点是任意时刻的输出仅仅取决于该时刻的输入,与电路原来的状态无关

时序电路是 时序 逻辑 电路。时序,时间 顺序,是在时钟的推动下工作的,cpu就是一个复杂的时序电路。

组合逻辑电路和时序逻辑电路的最根本区别在于:组合逻辑电路的输出在任一时刻只取决于当时的输入信号;而时序逻辑电路的输出,不仅和当前的输入有关,还和上时刻的输出有关,它具有记忆元件(触发器),可以记录前一时刻的输出状态,它可以没有输入,仅在时钟的驱动下,给出输出。

时序电路的基本结构:

img

结构特征:电路由组合电路和存储电路组成,电路存在反馈

0x 05 缓冲区漏洞实验

#include <stdio.h> //bomb.c

void echo()
{
	char buffer[4];
	gets(buffer); //缓冲区溢出的关键
	puts(buffer);
}

int main()
{
	puts("pls input: ");
	echo();
	return 0;
}
操作步骤:
1. gcc bomb.c -o main -fno-stack-protector -g
# -fno-stack-protector取消栈保护?
# -g调试模式,因为后面还需要调试

2. gdb main
2.1 在echo函数的gets函数加上一个断点:b 6
# echo函数位于main.c的第六行
2.2 r
# run运行程序,此时会在断点gets函数停下
2.3 info f 
# 显示栈信息,如下方图-栈信息所示
# 在这些信息中,我们需要注意三个地址:
# (1)frame at 0x7ff.f3d0
# (2)rbp at   0x7ff.f3c0
# (3)bip at.  0x7ff.f3c8
# 其中frame at的地址是函数echo占用栈的地址
# 此时,返回地址rip和旧的栈顶指针rbp已经入栈
# 由此可见,程序还没运行,返回地址和旧的栈顶指针就会入栈
2.4 p/a &buffer[0]
# 打印数组buffer的首地址
# 通过结构图,我们可以发现,数组与返回地址rip之间差了12(c8-bc)字节,如果我们gets的数组大于等于12字节,那么返回地址的数据就会被破坏,


![image-20220907100422585](/Users/epoch/Library/Application Support/typora-user-images/image-20220907100422585.png)

(图-栈信息)

![13C288AA-6A07-463D-A689-CC7FEF2DCB91](/Users/epoch/Library/Containers/com.tencent.qq/Data/Library/Application Support/QQ/Users/2407217576/QQ/Temp.db/13C288AA-6A07-463D-A689-CC7FEF2DCB91.png)

(图-数组地址)

img

(图-视频测试运行gets前的栈)

img

(图-视频测试运行gets后的栈)

0x 06 Computer English


common:注释

override:覆盖

entry:入口,条目,输入

Place holder:站位

ascending:升序

descending:降序

comma:逗号

brackets:括号

determine: 确定,决定,判定,下决心

deterministic: 确定行

finite: 有限的

infinite: 无限的

automaton: 自动机

positive: 正数

negative: 负数

decimal: 十进制

hexadecimal:十六进制

octal: 八进制

optimazation:优化

pruning:剪枝

decode:译码

instance: 例子,实例

cpu和memory 就组成了一个状态机

operand 操作数

opreator:操作符

memory:内存/存储器

recursion:递归

reduce:归约

iterate: 迭代

transistor:晶体管

complement:补充,补运算(~),辅

parse: 解析

simulator: 模拟器

simulate: 模拟,仿真,假装

converter:转换器

verbose: 冗长的,啰嗦

handler: 管理者,处理程序

illustrate: 说明

universal: 通用的

pecuilar: 特有,奇特,一场


0x 07 makefile

.1 规则

(1)make命令具有自动推导的功能,例如依赖中的.o文件,即使不存在,make会使用内部默认的构造规则生成这些.o文件。

(2)make后面不带参数默认执行第一条命令

(3)mak的时间戳规则

make 命令执行的时候会根据文件的时间戳判定是否执行 makefile 文件中相关规则中的命令。

  1. 目标是通过依赖生成的,因此正常情况下:目标时间戳 > 所有依赖的时间戳 , 如果执行 make 命令的时候检测到规则中的目标和依赖满足这个条件,那么规则中的命令就不会被执行。
  2. 当依赖文件被更新了,文件时间戳也会随之被更新,这时候 目标时间戳 < 某些依赖的时间戳 , 在这种情况下目标文件会通过规则中的命令被重新生成。
  3. 如果规则中的目标对应的文件根本就不存在, 那么规则中的命令肯定会被执行。

(4)对于不生成目标文件的目标称为伪目标,为了避免微伪目标的名字和真实的文件名重复,我们可以在伪目标的前面加上关键字:.PHONY(假) 例如:

.PHONY: clean
clean: 
	rm *.o

声明位伪目标主要是避免这种情况:

如果目标不存在规则的命令肯定被执行, 如果目标文件存在了就需要比较规则中目标文件和依赖文件的时间戳,满足条件才执行规则的命令,否则不执行。

加入目标是clean,而恰好有一个真实的clean文件,只要clean文件不更新,那么clean目标就无法执行。

(提醒)目录连接到博客中的实例6可以好好看看

标签:CSAPP,int,地址,0000000000000000,gdb,main,断点
From: https://www.cnblogs.com/ALaterStart/p/18335531

相关文章

  • CSAPP:Cache模拟器
    实验要求实现一个组相联的DataCache,达到最高命中率DataCache最大只能使用16KB的数据存储空间附加功能:实现指令Cache分析实验的框架代码已经给出(直接映射),要改成组相联的结构,无非就是修改访问DataCache的接口,确定组号后遍历组内每一行的Tag,若能与Address匹配上则hit,否则......
  • CSAPP(一)
    0x01关于补码iHATE公式对于char类型2Byte,8位,其中有1位视为符号位表示最大值2^72^62^52^42^32^22^12^001111111UMax:-2^7*0+2^6+2^5+2^4+2^3+2^2+2^1+1=127转为16进制表示即:7FTMax:-2^7+2^6+2^5+2^4+2^3+2^2+2......
  • HIT计算机系统CSAPP期末大作业
                                            计算机系统大作业题    目  程序人生-Hello’sP2P 专      业     数据科学与大数据技术                  学  号     202......
  • HIT CSAPP 计算机系统大作业 程序人生-Hello’s P2P From Program to Process
    摘 要本文借助hello.c跌宕起伏的一生——P2P(FromProgramToProcess)、020(FromZero-0toZero-0)从源代码到可执行程序以及和计算机系统硬件的配合,从计算机系统的角度阐述从源代码到可执行程序的转变,以及在计算机系统当中作为众多进程中的一员的运行过程。源程序首先经......
  • CSAPP Lab04——Cache Lab大师手笔,匠心制作
    浮沉浪似人潮哪会没有思念你我伤心到讲不出再见——讲不出再见完整代码见:CSAPP/cachelab-handoutatmain·SnowLegend-star/CSAPP(github.com)PartA:CacheSimulator这个lab描述背大锅,开始我是真有点没看懂题目的描述。特别是“M20,1”“L10,1”,这种描述二......
  • CSAPP
    感悟:原来读名校和非名校的区别是这样的在以前的211的时候,我上一门叫《你应该知道的数学》的课程,那时老师给我们介绍各种历史留名的大数学家,言语之间流露出“你们只能读这个水平的学校,自然也很难做出什么大成就”。现在到了top3,在上CSAPP的时候,老师对我们的期待就变成了——你们......
  • CSAPP Lab02——Bomb Lab完成思路详解
    看见的看不见的瞬间的永恒的青草长啊大雪飘扬——月亮之上完整代码见:CSAPP/bombatmain·SnowLegend-star/CSAPP(github.com)01字符串比较简单的把输入的字符串和地址“0x402400”内早已存储的字符串相比较。如果两个字符串相等则函数返回,否则炸弹爆炸。这里有......
  • HIT-CSAPP大作业——程序人生-Hello‘s P2P
    计算机系统大作业题    目  程序人生-Hello’sP2P 专      业        信息安全        学号       2022******        班    级          22*****        ......
  • CSAPP 第五章 优化程序性能
    5-1&2优化程序性能保守性编译器优化是保守的,只要有矛盾就不会激进的优化。CPECPE表示每个元素执行所需要的周期数。如368+6*k,6就是CPE。一个优化的例子这个代码每一次迭代要读两次内存,写入一次。这个只用读一次。以上优化会有一定的效果,读写内存是占用时间的。5-3......
  • CSAPP(datalab)解析
    操作符的解释右移操作符>>算术右移(通常用符号>>表示)保留符号位。对于正数,算术右移和逻辑右移的效果相同,即在左边填充0。对于负数,算术右移会在左边填充1,保持符号位的1不变。对于正数5(二进制表示00000101),右移1位:00000101>>1=00000010对于负数-5(二进制补......