intel x86寄存器及其汇编指令
intel x86架构,复杂指令集,intel公司最成功的cpu架构。
x86代表32位架构
我们平时装计算机所说的64位,32位代表寻址能力不同,一些地方说是支持的内存,其本质还是寻址能力
32位最大寻址内存范围是2的32次方,即4GB
1B=1024K=2^10K 1GB=1024B=2^10B ∴4GB=2^2*2^10*2^10*2^10 =2^(2+10+10+10)=2^32```
64位的最大寻址能力是2的64次方,即16384GB
但是,实际上限于种种原因,目前Windows 7 64位版仅能使用最大为192GB内存。
intel 系列向下兼容
具体发展历史和一些细节:https://baike.baidu.com/item/Intel%20x86/1012845?fr=aladdin
寄存器
八个通用寄存器:EAX,EBX,ECX,EDX,ESP,EBP,ESI,EDI
一个标志寄存器:EFLAGS
五个控制寄存器:分别为CR0-CR4
八个调试寄存器:分别为DR0-DR7
四个系统地址寄存器:GDTR、IDTR、LDTR和TR
其他寄存器:EIP、TSC等
通用寄存器
八个通用寄存器大多时候可以通用,但是某些寄存器有隐含用法。
EAX
累加器,很多加法乘法指令的缺省寄存器。
EBX
基地址(base)寄存器, 在内存寻址时存放基地址。
ECX
是计数器(counter), 是重复(REP)前缀指令和LOOP指令的内定计数器。
EDX
总是被用来放整数除法产生的余数。
ESI/EDI
分别叫做”源/目标索引寄存器(source/destination index),因为在很多字符串操作指令中, DS:ESI指向源串,而ES:EDI指向目的串.
源串和目的串(也有的叫目标串):
如在strcpy(*d, *s);
这里s指向的字符串就是源字符串,d指向的为目的字符串
EBP
是基址指针(BASE POINTER),它最经常被用作高级语言函数调用的”框架指针”(frame pointer)
ESP
专门用作堆栈指针,被形象地称为栈顶指针,堆栈的顶部是地址小的区域,压入堆栈的数据越多,ESP也就越来越小。在32位平台上,ESP每次减少4字节。
一般esp到ebp这段空间就是当前栈
标志寄存器
包含一组状态标志,系统标志以及一个控制标志
CF
若算术操作产生的结果在最高有效位(most-significant bit)发生进位或借位则将其置1,反之清零。
PF
如果结果的最低有效字节(least-significant byte)包含偶数个1位则该位置1,否则清零。
AF
如果算术操作在结果的第3位发生进位或借位则将该标志置1,否则清零。
ZF
若结果为0则将其置1,反之清零。
SF
该标志被设置为有符号整型的最高有效位。(0指示结果为正,反之则为负)
OF
如果整型结果是较大的正数或较小的负数,并且无法匹配目的操作数时将该位置1,反之清零。这个标志为带符号整型运算指示溢出状态。
DF
控制串指令(MOVS, CMPS, SCAS, LODS以及STOS)。设置DF标志使得串指令自动递减(从高地址向低地址方向处理字符串),清除该标志则使得串指令自动递增。STD以及CLD指令分别用于设置以及清除DF标志。
TF
将该位设置为1以允许单步调试模式,清零则禁用该模式。
IF
该标志用于控制处理器对可屏蔽中断请求的响应。置1以响应可屏蔽中断,反之则禁止可屏蔽中断。
IOPL
指示当前运行任务的I/O特权级,正在运行任务的当前特权级(CPL)必须小于或等于I/O特权级才能允许访问I/O地址空间。这个域只能在CPL为0时才能通过POPF以及IRET指令修改。
NT
这个标志控制中断链和被调用任务。若当前任务与前一个执行任务相关则置1,反之则清零。
RF
控制处理器对调试异常的响应。
VM
置1以允许虚拟8086模式,清除则返回保护模式。
AC
标志以及在CR0寄存器中的AM位置1时将允许内存引用的对齐检查,以上两个标志中至少有一个被清零则禁用对齐检查。
VIF
该标志是IF标志的虚拟镜像,与VIP标志结合起来使用。使用这个标志以及VIP标志,并设置CR4控制寄存器中的VME标志就可以允许虚拟模式扩展
VIP
该位置1以指示一个中断正在被挂起,当没有中断挂起时该位清零,与VIF标志结合使用。
ID
程序能够设置或清除这个标志指示了处理器对CPUID指令的支持。
控制寄存器
CR0
PE:CR0的位0是启用保护标志。当设置该位时即开启了保护模式;当复位时即进入实地址模式。这个标志仅开启段级保护,而并没有启用 分页机制。若要启用 分页机制,那么PE和PG标志都要置位。
PG:CR0的位31是分页标志。当设置该位时即开启了分页机制;当复位时则禁止分页机制,此时所有线性地址等同于 物理地址。在开启这个标志之前必须已经或者同时开启PE标志。即若要启用分页机制,那么PE和PG标志都要置位。
WP:对于Intel 80486或以上的CPU,CR0的位16是 写保护(Write Proctect)标志。当设置该标志时,处理器会禁止 超级用户程序(例如 特权级0的程序)向用户级只读页面执行写操作;当该位复位时则反之。该标志有利于UNIX类操作系统在创建进程时实现写时复制(Copy on Write)技术。
NE:对于Intel 80486或以上的CPU,CR0的位5是 协处理器错误(Numeric Error)标志。当设置该标志时,就启用了x87 协处理器错误的内部报告机制;若复位该标志,那么就使用PC形式的x87协处理器 错误报告机制。当NE为复位状态并且CPU的IGNNE输入引脚有信号时,那么数学协处理器x87错误将被忽略。当NE为复位状态并且CPU的IGNNE输入引脚无信号时,那么非屏蔽的数学协处理器x87错误将导致处理器通过FERR引脚在外部产生一个中断,并且在执行下一个等待形式浮点指令或WAIT/FWAIT指令之前立刻停止指令执行。CPU的FERR引脚用于仿真外部 协处理器80387的ERROR引脚,因此通常连接到中断控制器输入请求引脚上。NE标志、IGNNE引脚和FERR引脚用于利用外部逻辑来实现PC形式的外部 错误报告机制。
启用保护模式PE(Protected Enable)位(位0)和开启 分页PG(Paging)位(位31)分别用于控制分段和分页机制。PE用于控制分段机制。如果PE=1,处理器就工作在开启分段机制环境下,即运行在保护模式下。如果PE=0,则处理器关闭了分段机制,并如同8086工作于实地址模式下。PG用于控制 分页机制。如果PG=1,则开启了 分页机制。如果PG=0, 分页机制被禁止,此时 线性地址被直接作为 物理地址使用。
如果PE=0、PG=0,处理器工作在实地址模式下;如果PG=0、PE=1,处理器工作在没有开启 分页机制的保护模式下;如果PG=1、PE=0,此时由于不在保护模式下不能启用分页机制,因此处理器会产生一个一般保护异常,即这种标志组合无效;如果PG=1、PE=1,则处理器工作在开启了分页机制的保护模式下。
当改变PE和PG位时,必须小心。只有当执行程序至少有部分代码和数据在线性地址空间和物理地址空间中具有相同地址时,我们才能改变PG位的设置。此时这部分具有相同地址的代码在 分页和未分页世界之间起着桥梁的作用。无论是否开启分页机制,这部分代码都具有相同的地址。另外,在开启分页(PG=1)之前必须先刷新页高速缓冲TLB。
在修改该了PE位之后程序必须立刻使用一条跳转指令,以刷新处理器执行管道中已经获取的不同模式下的任何指令。在设置PE位之前,程序必须初始化几个系统段和控制寄存器。在系统刚上电时,处理器被复位成PE=0和PG=0(即实模式状态),以允许引导代码在启用分段和分页机制之前能够初始化这些寄存器和数据结构。
CR2和CR3
CR2和CR3用于分页机制。CR3含有存放页目录表页面的物理地址,因此CR3也被称为PDBR。因为页目录表页面是页对齐的,所以该寄存器只有高20位是有效的。而低12位保留供更高级处理器使用,因此在往CR3中加载一个新值时低12位必须设置为0。
调试寄存器
GDTR
全局描述符表寄存器,用于存放全局描述符表GDT的32位的线性基地址和16位的表限长值。基地址指定GDT表中字节0在线性地址空间中的地址,表长度指明GDT表的字节长度值。指令LGDT和SGDT分别用于加载和保存GDTR寄存器的内容。在机器刚加电或处理器复位后,基地址被默认地设置为0,而长度值被设置成0xFFFF。在保护模式初始化过程中必须给GDTR加载一个新值。
IDTR
中断描述符表寄存器,与GDTR的作用类似,IDTR寄存器用于存放中断描述符表IDT的32位线性基地址和16位表长度值。指令LIDT和SIDT分别用于加载和保存IDTR寄存器的内容。在机器刚加电或处理器复位后,基地址被默认地设置为0,而长度值被设置成0xFFFF。
LDTR
用于存放局部描述符表LDT的32位线性基地址、16位段限长和描述符属性值。指令LLDT和SLDT分别用于加载和保存LDTR寄存器的段描述符部分,包含LDT
EIP
存储我们cpu要读取指令的地址
TSC
一个用于时间戳计数器的64位的寄存器,它在每个时钟信号到来时加一
指令集
数据传送指令
MOV
mov指令将第二个操作数(可以是寄存器的内容、内存中的内容或值)复制到第一个操作数(寄存器或内存)。mov不能用于直接从内存复制到内存
push
push指令将操作数压入内存的栈中
pop
与push相反,将操作数从栈中取出
lea
lea实际上是一个载入有效地址指令,将第二个操作数表示的地址载入到第一个操作数(寄存器)中 lea实际上是一个载入有效地址指令,将第二个操作数表示的地址载入到第一个操作数(寄存器)中。
算术和逻辑指令
ADD
将两个操作数相加,且将相加后的结果保存到第一个操作数中。
SUB
第一个操作数减去第二个操作数,并将相减后的值保存在第一个操作数。
INC和DEC
inc,dec分别表示将操作数自加1,自减1。
IMUL
整数相乘指令,它有两种指令格式,一种为两个操作数,将两个操作数的值相乘,并将结果保存在第一个操作数中,第一个操作数必须为寄存器;第二种格式为三个操作数,其语义为:将第二个和第三个操作数相乘,并将结果保存在第一个操作数中,第一个操作数必须为寄存器
IDIV
idiv指令完成整数除法操作,idiv只有一个操作数,此操作数为除数,而被除数则为EDX:EAX中的内容(一个64位的整数)。
AND, OR, XOR
逻辑与、逻辑或、逻辑异或操作指令,用于操作数的位操作,操作结果放在第一个操作数中。
NOT
位翻转指令,将操作数中的每一位翻转,即0->1, 1->0。
NEG
取负指令。
SHL, SHR
位移指令,有两个操作数,第一个操作数表示被操作数,第二个操作数指示位移的数量。
控制转移指令
JMP
控制转移到label所指示的地址。
jcondition
条件转移指令,条件转移指令依据机器状态字中的一些列条件状态转移。机器状态字中包括指示最后一个算数运算结果是否为0,运算结果是否为负数等。
je
CMP
cmp指令比较两个操作数的值,并根据比较结果设置机器状态字中的条件码。此指令与sub指令类似,但是cmp不用将计算结果保存在操作数中。
CALL, RET
这两条指令实现子程序(过程、函数等意思)的调用及返回。call指令首先将当前执行指令地址入栈,然后无条件转移到由标签指示的指令。与其它简单的跳转指令不同,call指令保存调用之前的地址信息(当call指令结束后,返回到调用之前的地址)。
ret指令实现子程序的返回机制,ret指令弹出栈中保存的指令地址,然后无条件转移到保存的指令地址执行。