概述
本章节内容较为杂乱,不过皆为计算机的一些基础知识
一、整数的表示虽然只能编码一个相对较小的数值范围,但是这种表示是精确的
二、浮点数虽然可以编码一个较大的数值范围,但是这种表示只是近似的
三、unix和c都是出自贝尔实验室,unix绝大部分代码也是用c语言编写的
四、c语言中一个指针的值,都是某个存储快的第一个字节的虚拟地址。c编译器还把每个指针和类型信息联系起来,这样就可以根据指针值的类型,生成不同的机器级代码来访问存储在指针所指向位置处的值
五、大端与小端法:
假设int类型的变量x,位于地址0x100处,它的16进制数为0x01234567,地址范围为0x100到0x103之间,排列顺序依赖于机器类型
大端法:
0x100 0x101 0x102 0x103
01 23 45 67
小端法:
0x100 0x101 0x102 0x103
67 45 23 01
哪种顺序都无所谓,但是人们的争论就有些不可理喻,像是一种信仰,因此争论沦为政治问题的争论
通过命令 man ascii可以得到一张ASCII字符码的表
六、机器支持两种形式的右移:逻辑右移和算数右移,逻辑右移是在左端补k个0,算数右移是在左端补k个最高有效位的值,c语言标准把那个没有明确定义应该使用那种类型的右移,然而实际上,几乎所有的额编译器/机器组合都对有符号数据使用算数右移,且许多程序员也都假设机器会使用这种右移
当移位的位数大于机器字长时,也就是假设在32位机移位33位时,会怎样?
c标准情况下,移位应该是33mod32为1,所以移动1位,不过这种行为对于c程序来说设没有保证的,所以移位数量应该保持小于字长
八、算符优先
加减法的运算优先级高于移位运算,所以这里常常会出错,如果拿不准最好加括号!
九、整数与浮点数表示:
c和c++都支持有符号(默认)和无符号数。java只支持有符号数
对于有符号数和无符号数表达式的这种处理方式,出现了一个奇特的行为。当执行一个运算时,如果它的一个运算数是有符号的而另一个是无符号的,那么c预压1会隐式的将有符号参数强制类型转换成无符号数,并假设这两个数都是非负的,来执行这个运算,这个结果当进行>或<运算时,就有可能是错误的。
从一个数据到另一个数据大小的转换,以及无符号和有符号数字之间的转换的相对顺序能够影响一个程序的行为,例如把short转换成unsigned时,我们要先改变大小,之后在完成有符号到无符号之间的转换先从2个字节转换成4个字节,然后再从有符号转换成无符号。
十、原码反码补码:
简便算法:正数按位取反+1得负数
我们根据有符号和无符号的这些发现,推出了一个安全隐患,下面是FreeBSD2002年getpeername函数的安全漏洞:
14行开始的函数copy_from_kernel是要将一些操作系统内核维护的数据复制到指定的用户可以访问的存储器区域,正常不可能让普通用户得到内核数据的,但是显示为kbuf的区域是用户可以读的。maxlen是分配给用户的缓冲区长度,16行保护他的大小最大不超过1024,但是如果黑客构造一个负数来填入maxlen,小于1024,但最后转化为size_t的无符号整形,比1024大,就可以造成缓冲区溢出!
我们避免这一漏洞的一种方法就是绝不使用无符号数,实际上除了C以外,很少有语言支持无符号整数,所以在我们进行漏洞挖掘时,可以多关注一下有符号数与无符号数之间的转换可不可能绕过。
有符号数的益处:当我们想要把字仅仅看作是位的集合,并且没有任何数字意义时,无符号整形是非常有用的。当实现模运算和多精度运算的数学包时,数字是由字的数组来表示的,无符号也会非常有用!
十一、API(Application Programming INterface)应用程序编程接口
用于16位的API称为Win16,用于32位的windowsAPI称为Win32.64位的windows API的名称和功能基本没有变化,还是使用win32的函数名,只不过是用64位代码实现的
windows运转的核心是动态链接,在早期,Windows的主要部分只需要在三个动态链接库中实现,它们分别代表Windows的三个主要子系统,叫做Kernel、User和GDI
Kernel(由KERNEL32.DLL):操作系统核心功能服务,包括进程与线程控制、内存管理,文件访问等
User(由USER32.DLL实现):负责处理用户接口,包括键盘和鼠标输入、窗口和菜单管理等
GDI(由GDI32.DLL实现):图形设备接口,允许程序在屏幕和打印机上显示文本和图形
十二、WOW64
WOW64(Windows-on-Windows 64-bit)是64位Windows操作系统的子系统,可以使大多数32位应用程序在不进行修改的情况下运行在64位操作系统上
64位的Windows,除了带有64位操作系统应有的系统文件,还带有32位系统所带有的文件。Windows的64位系统文件都放在一个叫做WindowsSystem32的文件夹中,为了兼容32位的操作系统,还增加了WindowsSysWOW64文件夹,其中存储了32位的系统文件
64位应用程序会加载System32目录下64位的kernel32.dll、user32.dll和ntdll.dll。当32位应用程序加载时,WOW64建立32位ntdll.dll所需求的启动环境,将CPU模式切换至32位,并开始执行32位加载器,就如同该进程运行在原生32位系统上一样,WOW64会对32位ntdll.dll的调用重定向ntdll.dll(64位),而不是发出原生的32位系统调用指令。WOW64转换到原生的64位模式,捕获与系统调用有关的参数,发出对应的原生64位系统调用。当原生的系统调用返回时,WOW64在返回32位模式之前将所有输出参数从64位转换成32位
WOW64既不支持16为应用程序的执行(32位Windows支持16位应用程序的执行),也不支持加载32位内核模式的设备驱动程序。WOW64进程只能加载32位的DLL,不能加载原生的64位DLL。类似的,原生的64位进程不能加载32位的DLL
十三、虚拟内存
windows是一个分时多任务的操作系统,CPU时间在被分成一个个时间片后分配给不同的程序。在一个时间片里,与这个程序的执行无关的内同不会映射到线性地址中。因此,每个程序都有自己的寻址空间,互不干扰。在物理内存中,操作系统和系统DLL代码需要共每个应用程序调用,所以他们在任意时刻必须被映射。用户的EXE程序只会在自己所属的时间片内被映射,用户DLL则有选择的被映射
简单的说,虚拟内存的实现方法和过程如下
- 当一个应用程序启动时,操作系统就创建一个进程,并给该进程分配2GB的虚拟地址(不是内存,只是地址)
- 虚拟内存管理器将应用程序的代码映射到那个应用程序的虚拟地址中的某个位置,并把当前需要的代码读入物理地址(注意:虚拟地址与应用程序代码在物理内存中的位置是没有关系的)
- 如果使用DLL,DLL也会被映射到进程的虚拟地址空间中,在需要的时候才会被读入物理内存
- 其他项目(数据、堆栈等)的空间是从物理内存分配的,并被映射到虚拟地址空间中
- 应用程序通过使用其虚拟地址空间中的地址开始执行。然后,虚拟内存管理器把每次内存访问映射到物理位置
看不明白上面的步骤也不要紧,但要明白以下几点:
- 应用程序不会直接访问物理地址
- 虚拟内存管理器通过虚拟地址的访问请求来控制所有物理地址的访问
- 每个应用程序都有独立的4GB空间,不同应用程序的地址空间时彼此隔离的
- DLL程序没有私有空间,他们总是被映射到其他应用程序的地址空间中,作为其他应用程序的一部分运行。其原因是:如果DLL程序不予其他程序处于同一地址空间,应用程序就无法调用它
使用虚拟内存的好处是:简化了内存的管理,弥补了物理内存的不足,可以防止多任务环境下应用程序之间的冲突
64位windows操作系统提供了16TB的有效寻址空间,其中的一般可用于用户模式的应用程序。
最后
以上就是淡定书包为你收集整理的基础知识的全部内容,希望文章能够帮你解决基础知识所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复