1、Intel现在称其指令集为IA32,即Intel 32位体系结构(Intel Architecture 32-bit),这个处理器也俗称为“x86”。
2、Linux使用了平面寻址方式(flat addressing),在这种寻址方式中,程序员将整个存储空间看做一个大的字节数组。
3、在平面寻址中,对特殊寄存器的需求已经大为降低了。在大多数情况下,前六个寄存器都可以看作是通用寄存器,对它们使用的没有限制。
4、对于C语言中比如if表示式,switch,while,for循环等对应的汇编表示,在本书都有详细描述,对于研究汇编写程序有极大帮助。此略。
5、一个过程调用包括将数据(以过程参数和返回值的形式)和控制从代码的一部分传递到另一部分。数据传递、局部变量的分配和释放是通过操纵程序栈来实现的。
6、IA32程序用程序栈来支持过程调用。栈用来传递过程参数、存储返回信息、保存寄存器以供以后恢复之用,以及用于本地存储。为单个过程分配的那部分栈称为栈帧(stack frame)。栈帧的最顶端是以两个指针定界的,寄存器%ebp作为帧指针,而寄存器%esp作为栈指针。
7、程序寄存器组是惟一一个被所有过程共享的资源。我们必须保证当一个过程(调用者)调用另一个(被调用者)时,被调用者不会覆盖某个调用者稍后会使用的寄存器的值。为些,IA32采用于一组统一的寄存器使用惯例:寄存器eax,edx,ecx被分为调用者保存寄存器,当过程P调用Q时,Q可以覆盖这些寄存器,而不会破坏任何P所需要的数据。另外,ebx,esi,edi分为被调用者保存寄存器,意味着覆盖他们之前,将这些寄存器的值保存在栈中,并在返回前恢复他们。
8、在大多数现代处理器模型中,乘法指令只需要3个时钟周期。
9、结构的实现类似于数组的实现,因为结构的所有组成部分都存放在存储器中连续的区域内,而指向结构的指针就是结构第一个字节的地址。
10、对齐
许多计算机系统对基本数据类型的可允许地址做出了一些限制,要求某种类型的对象的地址必须是某个值k(通常是2,4,或8)的倍数。
Linux沿用的对齐策略是:2字节数据类型(e.g short)的地址必须是2的倍数,而较大的数据类型(e.g int,int*,float,double)的地址必须是4的倍数。这意味着一个short类型对象的地址的最低位必须等于0。类似地,任何int类型的对象或指针的地址最低两位必须都是0。
Microsoft windows的对齐策略为:任何k字节对象的地址都必须是k的倍数;特别地,要求一个double的地址应该是8的倍数。
分配存储器的例程(如malloc)的设计必须使得它们返回的指针能满足最糟糕的对齐限制,通常是4或者是8。
结构体的对齐策略,考虑到分配结构体数组,要求其大小是结构体中最大字节类型的整数倍。
11、存储器越界问题
示例代码
/* Implementation of library function gets() */ char* gets(char *s) { int c; char *dest = s; while ((c = getchar()) != '\n' && c != EOF) *dest++ = c; *dest++ = '\0'; /* Terminate String */ if (c == EOF) return NULL; return s; } /* Read input line and write it back */ void echo() { char buf[4]; /* Way too small! */ gets(buf); puts(buf); }
缓冲区溢出的一个更加致命的使用就是让程序执行它本身不愿意执行的函数。通常,输入给程序一个字符串,这个字符串包含一些可执行代码的字节编码,称为expliot code,另外,还有一些字节会用一个指向缓冲区中那些可执行代码的指针覆盖掉返回指针,所以执行ret指令的效果就是跳转到expliot code(plus some extra bytes that overwrite the return pointer with a pointer to the code in the buffer. The effect of executing the ret instruction is then to jump to the exploit code)。
在一种攻击形式中,expliot code会使用系统调用启动一个shell程序,提供给攻击者一组操作系统的函数(providing the attacker with a range of operating system functions.)。另一种攻击形式中,expliot code会执行一些未授权的任务,修复对栈的破坏,然后第二次执行ret指令(看上去好像)正常返回给调用者。(the exploit code performs some otherwise unauthorized task, repairs the damage to the stack, and then executes ret a second time, causing an (apparently) normal return to the caller.)。
12、蠕虫(worm)是这样一个程序,它可以自己运行,并且能够将一个完全有效的自己传播到其他机器。病毒(virus)是这样一段代码,它能将自己添加到包括操作系统在内的其他程序中,但它不能独立运行。
13、浮点运算单元(FPU),IA32浮点寄存器的宽都是80位。浮点运算器的行为可能依赖于值是保存在寄存器中,还是存储器中。
<Computer Systems:A Programmer's Perspective>