处理器是计算机的核心,处理器包括一套寄存器、一套指令集、一套内存访问的寻址方式,以及不同的工作模式,不同的工作模式决定了指令是如何被解释和执行的。所有这一切就是处理器的架构。英特尔处理器的架构简称IA,intel architecture。
处理器内部的寄存器和算数逻辑部件的宽度决定了处理器的字长。32位的处理器拥有32位的寄存器和算术逻辑部件。英特尔32位处理器所使用的架构称为IA-32。
物理地址,地址线发出的地址称为物理地址,可直接用于物理内存访问的地址
有效地址,就是段内偏移
线性地址,段地址加上段内偏移就构成了线性地址。
8086处理器,地址线20根
80386处理器,地址线32根
1.x64架构的工作模式
AMD的64位处理器架构称为AMD64,英特尔的64位处理器架构称为Intel64,书中统称它们为x64架构。x64架构是指兼容x86架构的64位架构。
x86处理器的工作模式:实地址模式、保护模式、系统管理模式
x64处理器支持x86处理器的全部工作模式,并且对x64架构来说实地址模式和保护模式统称为传统模式。
x64架构引入了自己独有的工作模式,AMD公司称之为长模式,英特尔公司称之为IA-32e模式。
IA-32e模式包含了2个子模式 ,它们是兼容模式和64位模式。兼容模式类似于32位保护模式,允许多数16位或者32位程序不用重新修改和编译就可以直接运行在64位操作系统上。64位模式用来运行64位操作系统和应用程序。
计算机启动后,处理器需要从实模式进入保护模式,再从保护模式进入并激活IA-32e模式。激活之后,它当前执行的那个代码段的描述符决定了它可能位于哪个子模式。如果代码段描述符的L位是0,则按兼容模式执行,如果代码段描述符的L位是1,则按64位模式执行。
2.x64架构的寄存器
2.1 x64架构对通用寄存器的扩展
16位处理器的时候,通用寄存器有:AX, BX, CX, DX, SI, DI, SP, BP,其中前4个可以拆分成2个8位的寄存器使用。
32位处理器的时候,通用寄存器有:EAX, EBX, ECX, EDX, ESI, EDI, ESP, EBP
64位处理器的时候,通用寄存器有:RAX, RBX, RCX, RDX, RSI, RDI, RSP, RBP, R8~R15
2.2 x64架构的通用寄存器的访问规则
处理器工作在保护模式或者兼容模式下时,可以访问的寄存器
8位:AH, AL, BH, BL, CH, CL, DH, DL
16位:AX, BX, CX, DX, SI, DI, SP, BP
32位:EAX, EBX, ECX, EDX, ESI, EDI, ESP, EBP
处理器工作在64位模式下时,可以访问的寄存器
8位:AH, AL, BH, BL, CH, CL, DH, DL, SIL, DIL, SPL, BPL, R8B~R15B
16位:AX, BX, CX, DX, SI, DI, SP, BP, R8W~R15W
32位:EAX, EBX, ECX, EDX, ESI, EDI, ESP, EBP, R8D~R15D
64位:RAX, RBX, RCX, RDX, RSI, RDI, RSP, RBP, R8~R15
3.传统模式的内存访问
x64架构的处理器兼容实地址模式,即支持将16位的段地址左移4位再加上16位的偏移地址的方式计算出物理地址,当实际的地址线大于20的时候,在左边补零。
x64架构的处理器兼容保护模式,即支持使用16位的段段选择子从描述符表中获取到描述符,进而获取到段的基地址,再用基地址加上32位的段内偏移的方式计算出物理地址,当实际的地址线大于32的时候,在左边补零。
传统模式下的32位分页技术分为以下4种,4KB分页技术,4MB分页技术,PAE-4KB分页技术,PAE-2MB分页技术。传统模式下32位分页技术是指,被转换的线性地址是32位的。
传统模式下32位4KB分页技术是分两级的,也就是通过页目录表和页表来完成。这种分页方式最多只能访问32位地址
传统模式下32位4MB分页技术只使用一个页目录表,不再使用页表。这种分页方式下,段部件发送过来的线性地址被分成2个部分,前10bit用作页目录表的索引,后22 bit用作页内偏移。物理页的大小为4MB,物理页是4MB对齐的,那么页的物理地址的低22位为全零,不需要记录,页目录项中记录了页物理地址的23位到M位的值,M大于等于32,小于等于40。M是处理器地址线的数量。这种分页方式最多可以访问40位地址
PAE,physical address extension,物理地址扩展技术。在PAE分页方式下,页目录项和页表项的大小被扩展到64位,由于页目录表和页表的大小是固定的,为4KB,所以PAE分页方式下的页目录表和页表只有512个表项。
传统模式下32位PAE-4KB分页技术用到了3个表格,页目录指针表、页目录表和页表。页目录指针表项中记录了页目录表物理地址的位12位M-1,以及属性值。页目录表项中记录了页表物理地址的位12位M-1,以及属性值。页表项中记录了页物理地址的位12~位M-1,以及属性值。
传统模式下32位PAE-2MB分页技术用到了2个表格,页目录指针表、页目录表。页目录指针表项中记录了页目录表物理地址的位12位M-1,以及属性值。页目录表项中记录了页物理地址的位21位M-1,以及属性值。
分页方式 使用的表 转换方式 引入的目的
4KB 页目录表、页表 线性地址前10 bit用作页目录表的索引,中间10bits用作页表的索引,最后12 bits用作页内偏移
4MB 页目录表 线性地址前10 bit用作页目录表的索引,后22 bits用作页内偏移 为了利用超过4GB的物理内存,方法是,在页目录项中保存页地址的位22到位M,M是处理器的地址线数量,最多可以是40。
PAE-4KB 页目录指针表、页目录表、页表 线性地址前2 bits用作页目录指针表的索引,中间9 bits用作页目录表的索引,后续9 bits用作页表的索引,最后12 bits用作页内偏移 为了可以利用超过40 bits的线性地址空间。在页目录项中保存页地址的位12到位M,M是处理器的地址线数量,最多可以是52。
PAE-2MB 页目录指针表、页目录表 线性地址前2 bits用作页目录指针表的索引,中间9 bits用作页目录表的索引,最后21 bits用作页内偏移
分页方式对比
4.IA-32e模式的内存访问
x64架构兼容传统的32位保护模式,在保护模式下可以拥有32位的线性地址空间。x64架构有自己的IA-32e模式,这种模式具有64位的线性地址空间。为了将64位的线性地址空间转换成物理地址,还引入了4级和5级分页方式。
对于x64处理器来说,不需要用到全部64位地址空间,实际有效的部分只有低48位,这样只需要4个级别的分页系统表格。对于高16位的处理是扩高,即将符号位的值扩展到高16位,符号位是位47。由于扩高地址的特点,因此有效地址范围只有0~0x7FFF FFFF FFFF和0xFFFF 8000 0000 0000 ~ 0xFFFF FFFF FFFF FFFF
兼容模式下的内存访问是这样的,段选择子选择一个段描述符,取出线性基地址,加上段内偏移地址,得到一个32位的线性地址,然后将高32位补零得到一个64位的线性地址,然后通过4级分页机制将这个线性地址转换成物理地址。
64位模式下段寄存器CS、DS、ES、SS的基地址都强制为0,所以有效地址就是线性地址,线性地址会送到页部件进行转换。
4级分页机制要转换的线性地址空间是48位的,采用了4个分页系统表,分别是4级头表、页目录指针表、页目录表和页表,当页的大小是4KB的时候,48位的线性地址被分成5段,第一段9 bits,用作4级投标的索引,第二段9 bits,用作页目录指针表的索引,第三段9 bits,用作页目录表的索引,第四段9 bits,用作页表的索引,第五段12 bits,用作页内偏移。
5.x64架构的系统表和系统描述符
系统表有GDT、IDT、LDT、TSS
描述符分为存储器的描述符和系统描述符。存储器的描述符包括代码段描述符和数据段描述符。系统描述符包括段描述符和门描述符,段描述符包括LDT和TSS,门描述符包括调用门、中断门、陷阱门和任务门。
5.1x64架构的GDTR
GDT表的表基地址64位,表界限16位,表最大尺寸64KB
GDTR中保存的GDT表的基地址部分占64位,表界限部分占12位
在IA-32e兼容模式下,lgdt加载的是32位的基地址部分和16位的段界限部分。
在IA-32e 64位模式下,lgdt加载的是64位的基地址部分和16位的段界限部分。
在IA-32e兼容模式下,sgdt存储的是32位的基地址部分和16位的段界限部分。
在IA-32e 64位模式下,sgdt存储的是64位的基地址部分和16位的段界限部分。
5.2 x64架构的IDTR
IDT表的表基地址64位,表界限16位,表最大尺寸64KB
IDTR中保存的IDT表基地址部分占64位,表界限部分占12位
在IA-32e兼容模式下,lidt加载的是32位的基地址部分和16位的段界限部分。
在IA-32e 64位模式下,lidt加载的是64位的基地址部分和16位的段界限部分。
在IA-32e兼容模式下,sidt存储的是32位的基地址部分和16位的段界限部分。
在IA-32e 64位模式下,sidt存储的是64位的基地址部分和16位的段界限部分。
5.3 x64架构的LDT和LDTR
LDT表的表基地址64位,表界限16位,表最大尺寸64KB
LDTR中保存的是LDT表的描述符选择子,LDTR还有一个隐藏部分,里面保存了LDT的基地址、界限和属性。
在兼容模式下,lldt将32位的LDT基地址和16位的段界限,以及属性值加载到LDTR的隐藏部分。
在64位模式下,lldt将64位的LDT基地址和16位的段界限,以及属性值加载到LDTR的隐藏部分。
在兼容模式下,sldt将32位的LDT基地址和16位的段界限,以及属性值加载到LDTR的隐藏部分。
在64位模式下,sldt将64位的LDT基地址和16位的段界限,以及属性值加载到LDTR的隐藏部分。
5.4 x64架构的TSS和TR
TSS的基地址64位,表界限16位,最大尺寸64KB
TR中保存的是TSS的描述符选择子,TR还有一个隐藏部分,里面保存了TSS的基地址、界限和属性。
在兼容模式下,ltr将32位的tss基地址和16位的段界限,以及属性值加载到TR的隐藏部分。
在64位模式下,ltr将64位的tss基地址和16位的段界限,以及属性值加载到TR的隐藏部分。
在兼容模式下,str将32位的tss基地址和16位的段界限,以及属性值加载到TR的隐藏部分。
在64位模式下,str将64位的tss基地址和16位的段界限,以及属性值加载到TR的隐藏部分。
6.x64架构的标志寄存器和指令指针寄存器
16位处理器时代,标志寄存器是FLAGS
32位处理器时代,标志寄存器是EFLAGS
64位处理器时代,标志寄存器是RFLAGS。只使用低32位,高32位保留。
低32位也有一些位是保留的,可使用的位及其医院如下:
位0,CF,进位标志
位2,PF,奇偶标志
位4,AF,辅助进位标志
位6,ZF,零标志
位7,SF,符号标志
位8,TF,陷阱标志
位9,IF,中断标志
位10,DF,方向标志
位11,OF,溢出标志
位12~13,IOPL
位14,NT,嵌套
位16,RF,恢复标志,可临时禁止指令断点起作用
位17,VM,虚拟8086模式标志
位18,AC,对齐检查位
位19,VIF,虚拟中断标志位
位20,VIP,虚拟中断挂起
位21,ID,cpuid命令可用指示位
7.x64架构的寻址方式
7.1x64架构下传统模式的寻址方式
16位处理器时,内存寻址可以使用(基址+变址+偏移)的方式,其中基址只能使用BX和BP指定,变址只能使用SI和DI指定,偏移可以是8位或者16位的立即数。
32位处理器时,内存寻址可以也使用(基址+变址*比例因子+偏移)的方式,其中基址可以使用任意通用寄存器指定,即可以使用EAX, EBX, ECX, EDX, ESI, EDI, ESP, EBP中的任意一个,变址可以使用除ESP之外的任意通用寄存器指定,比例因子可以是1,2,4,8中的任意一个,偏移可以是8位或者32位的立即数。
64位处理器时,如果工作在传统模式,则寻址方式和传统模式一样。
7.2 x64架构下IA-32e模式的寻址方式
64位处理器时,如果工作在IA-32e的兼容模式,则和32位保护模式时的寻址方式一样。
64位模式时,内存寻址可以也使用(基址+变址*比例因子+偏移)的方式,其中基址可以使用任意通用寄存器指定,即可以使用EAX, EBX, ECX, EDX, ESI, EDI, ESP, EBP,R8~R15中的任意一个,变址可以使用除ESP之外的任意通用寄存器指定,比例因子可以是1,2,4,8中的任意一个,偏移可以是8位或者64位的立即数。
7.3 64位模式的RIP相对寻址方式
mov [data], eax
上述语句的作用是把eax的值传输到data指定的内存地址处。
首先要获取data的线性地址,data是一个标号,编译之后会被它的有效地址替代,有效地址就是它相对于程序开头的偏移量,在实模式和保护模式时,因为CS中保存了段基址,因此只需要这个有效地址就可以获取到data的线性地址。
获取了线性地址之后,就可以取得data处的值,然后这个值作为有效地址,加上数据段的基地址,得到一个线性地址,eax的值就被复制到这个线性地址处。
x64处理器的64位模式强制使用平坦模型,即不分段,所有段的基址都是0。那么只使用有效地址计算不出data的线性地址。此时可以使用RIP相对寻址来找到data的位置,方式如下
mov [rel data], eax
编译的时候[rel data]被相对距离替换,相对距离就是目标位置的汇编地址减去当前这个语句的下一个语句的汇编地址
指令执行的时候,用指令指针寄存器的值加上相对距离,即RIP + Offset。
问题
1.什么是指令断点?
在进行程序调试的时候,一般会采用设置断点的方式。执行到某一条指令时,断点异常被处罚,这个断点就称为指令断点
程序运行到指令断点时,会先跳转到异常处理程序执行,执行完毕后继续回到断点处,执行刚才断点处的指令。
如果在异常处理程序中没有将断点移除,则又会进入到异常处理程序中执行,从而围绕这个断点形成一个循环。
2.进入中断或者异常处理之前,压入栈中的有哪些?
CS,指令指针寄存器和标志寄存器
3.16位处理器和32位处理器的寻址方式有哪些?
8086处理器的寻址方式有寄存器寻址、立即寻址和内存寻址。内存寻址又分为直接寻址、基址寻址、变址寻址和基址变址寻址
32位处理器可以兼容全部8086处理器的寻址方式,并且进行了扩展。在进行基址寻址、变址寻址和基址变址寻址的时候,可以使用的寄存器变多了。8086的时候基址寻址的基址只能用BX和BP指定,变址寻址的变址只能用SI和DI指定。但是32位处理器上,基址可以使用全部8个通用寄存器,变址可以使用除ESP之外的全部通用寄存器,且变址可以乘以一个比例因子,包括1,2,4,8。
4.低端字节序是什么意思?
对于Intel处理器来说,如果访问内存中的一个字,它规定高字节在高地址处,低字节在低地址处,这称为低端字节序。
5.8086处理器的过程调用方式有哪些?
16位相对近调用
call near proc_1
编译的时候proc_1被替换成相对地址,执行的时候用IP加上这个相对地址。
16位间接绝对近调用
call [addr]
跳转到addr指定的位置
16位直接绝对远调用
call 段内偏移:段基址
16位间接绝对远调用
call far [addr]
从addr处获取4个字节,前2个字节是段内偏移,后2个字节是段基址
6.8086处理器的无条件转移方式有哪些?
相对短转移
jmp short inifinite
操作数是相对于目标位置的偏移量,大小为1字节,是个有符号数,转移的范围是-128~127
16位相对近转移
jmp near infinite
操作数是相对于目标位置的偏移量,大小为2字节,是个有符号数,转移的范围是-32768~32767
16位间接绝对近转移
jmp [addr]
跳转到addr指定的位置
16位直接绝对远转移
jmp 段内偏移:段基址
16位间接绝对远转移
jmp far [addr]
从addr处获取4个字节,前2个字节是段内偏移,后2个字节是段选择子