程序计数器PC和寄存器EIP有什么关系吗,为什么它们都是存放下一条指令的地址

程序计数器PC和寄存器EIP有什么关系吗,为什么它们都是存放下一条指令的地址,第1张

先明白定义再说区别和原理: 1、程序存储器(program storage) 在计算机的主存储器中专门用来存放程序、子程序的一个区域。 2、指令寄存器(IR ):用来保存当前正在执行的一条指令。当执行一条指令时,先把它从内存取到数据寄存器(DR)中,然后再传送至IR。指令划分为 *** 作码和地址码字段,由二进制数字组成。为了执行任何给定的指令,必须对 *** 作码进行测试,以便识别所要求的 *** 作。指令译码器就是做这项工作的。指令寄存器中 *** 作码字段的输出就是指令译码器的输入。 *** 作码一经译码后,即可向 *** 作控制器发出具体 *** 作的特定信号。 3、程序计数器(PC):为了保证程序(在 *** 作系统中理解为进程)能够连续地执行下去,CPU必须具有某些手段来确定下一条指令的地址。而程序计数器正是起到这种作用,所以通常又称为指令计数器。在程序开始执行前,必须将它的起始地址,即程序的一条指令所在的内存单元地址送入PC,因此程序计数器(PC)的内容即是从内存提取的第一条指令的地址。当执行指令时,CPU将自动修改PC的内容,即每执行一条指令PC增加一个量,这个量等于指令所含的字节数,以便使其保持的总是将要执行的下一条指令的地址。由于大多数指令都是按顺序来执行的,所以修改的过程通常只是简单的对PC加1。 当程序转移时,转移指令执行的最终结果就是要改变PC的值,此PC值就是转去的地址,以此实现转移。有些机器中也称PC为指令指针IP(Instruction Pointer) 4、地址寄存器:用来保存当前CPU所访问的内存单元的地址。由于在内存和CPU之间存在着 *** 作速度上的差别,所以必须使用地址寄存器来保持地址信息,直到内存的读/写 *** 作完成为止 。 当CPU和内存进行信息交换,即CPU向内存存/取数据时,或者CPU从内存中读出指令时,都要使用地址寄存器和数据缓冲寄存器。同样,如果我们把外围设备的设备地址作为像内存的地址单元那样来看待,那么,当CPU和外围设备交换信息时,我们同样使用 地址寄存器和数据缓冲寄存器 基本上定义就是区别和应用。蓝屏

CPU存储器是微处理器中存放数据和各种程式的装置。CPU存储器是微处理器的一个重要的组成部分,由存储单元集合体,地址暂存器,解码驱动电路。读出放大器以及时序控制电路等几部分组成。

基本介绍 中文名 :CPU存储器 外文名 :CPU memory 别名 :记忆装置 来自 :微处理器 用途 :存放数据 数据暂存器,变址暂存器,指针暂存器,段暂存器,指令暂存器,标志暂存器, 数据暂存器 数据暂存器主要用来保存运算元和运算结果等信息,从而节省读取运算元所需占用汇流排和访问存储器的时间。 32位CPU有4个32位的通用暂存器EAX、EBX、ECX和EDX。对低16位数据的存取,不会影响高16位的数据。这些低16位暂存器分别命名为:AX、BX、CX和DX,它和先前的CPU中的暂存器相一致。 4个16位暂存器又可分割成8个独立的8位暂存器(AX:AH-AL、BX:BH-BL、CX:CH-CL、DX:DH-DL),每个暂存器都有自己的名称,可独立存取。程式设计师可利用数据暂存器的这种“可分可合”的特性,灵活地处理字/位元组的信息。 暂存器AX和AL通常称为累加器(Aumulator),用累加器进行的 *** 作可能需要更少时间。累加器可用于乘、除、输入/输出等 *** 作,它们的使用频率很高; 暂存器BX称为基地址暂存器(Base Register)。它可作为存储器指针来使用; 暂存器CX称为计数暂存器(Count Register)。在循环和字元串 *** 作时,要用它来控制循环次数;在位 *** 作中,当移多位时,要用CL来指明移位的位数; 暂存器DX称为数据暂存器(Data Register)。在进行乘、除运算时,它可作为默认的运算元参与运算,也可用于存放I/O的连线埠地址。 在16位CPU中,AX、BX、CX和DX不能作为基址和变址暂存器来存放存储单元的地址,但在32位CPU中,其32位暂存器EAX、EBX、ECX和EDX不仅可传送数据、暂存数据保存算术逻辑运算结果,而且也可作为指针暂存器,所以,这些32位暂存器更具有通用性。详细内容请见第38节——32位地址的定址方式。 变址暂存器 32位CPU有2个32位通用暂存器ESI和EDI。其低16位对应先前CPU中的SI和DI,对低16位数据的存取,不影响高16位的数据。 暂存器ESI、EDI、SI和DI称为变址暂存器(Index Register),它们主要用于存放存储单元在段内的偏移量,用它们可实现多种存储器运算元的定址方式(在第3章有详细介绍),为以不同的地址形式访问存储单元提供方便。 变址暂存器不可分割成8位暂存器。作为通用暂存器,也可存储算术逻辑运算的运算元和运算结果。 它们可作一般的存储器指针使用。在字元串 *** 作指令的执行过程中,对它们有特定的要求,而且还具有特殊的功能。具体描述请见第5211节。 指针暂存器 32位CPU有2个32位通用暂存器EBP和ESP。其低16位对应先前CPU中的SBP和SP,对低16位数据的存取,不影响高16位的数据。 指针暂存器不可分割成8位暂存器。作为通用暂存器,也可存储算术逻辑运算的运算元和运算结果。 它们主要用于访问堆叠内的存储单元,并且规定: BP为基指针(Base Pointer)暂存器,用它可直接存取堆叠中的数据; SP为堆叠指针(Stack Pointer)暂存器,用它只可访问栈顶。 段暂存器 段暂存器是根据记忆体分段的管理模式而设定的。记忆体单元的物理地址由段暂存器的值和一个偏移量组合而成的,这样可用两个较少位数的值组合成一个可访问较大物理空间的记忆体地址。 CPU内部的段暂存器: CS——代码段暂存器(Code Segment Register),其值为代码段的段值; DS——数据段暂存器(Data Segment Register),其值为数据段的段值; ES——附加段暂存器(Extra Segment Register),其值为附加数据段的段值; SS——堆叠段暂存器(Stack Segment Register),其值为堆叠段的段值; FS——附加段暂存器(Extra Segment Register),其值为附加数据段的段值; GS——附加段暂存器(Extra Segment Register),其值为附加数据段的段值。 在16位CPU系统中,它只有4个段暂存器,所以,程式在任何时刻至多有4个正在使用的段可直接访问;在32位微机系统中,它有6个段暂存器,所以,在此环境下开发的程式最多可同时访问6个段。 32位CPU有两个不同的工作方式:实方式和保护方式。在每种方式下,段暂存器的作用是不同的。有关规定简单描述如下: 实方式: 前4个段暂存器CS、DS、ES和SS与先前CPU中的所对应的段暂存器的含义完全一致,记忆体单元的逻辑地址仍为“段值:偏移量”的形式。为访问某记忆体段内的数据,必须使用该段暂存器和存储单元的偏移量。 保护方式: 在此方式下,情况要复杂得多,装入段暂存器的不再是段值,而是称为“选择子”(Selector)的某个值。段暂存器的具体作用在此不作进一步介绍了,有兴趣的读者可参阅其它科技资料。 指令暂存器 32位CPU把指令指针扩展到32位,并记作EIP,EIP的低16位与先前CPU中的IP作用相同。 指令指针EIP、IP(Instruction Pointer)是存放下次将要执行的指令在代码段的偏移量。用来提供指令在存储器中的地址。在具有预取指令功能的系统中,下次要执行的指令通常已被预取到指令伫列中,除非发生转移情况。所以,在理解它们的功能时,不考虑存在指令伫列的情况。 在实方式下,由于每个段的最大范围为64K,所以,EIP中的高16位肯定都为0,此时,相当于只用其低16位的IP来反映程式中指令的执行次序。 标志暂存器 一、运算结果标志位 1、进位标志CF(Carry Flag) 进位标志CF主要用来反映运算是否产生进位或借位。如果运算结果的最高位产生了一个进位或借位,那么,其值为1,否则其值为0。 使用该标志位的情况有:多字(位元组)数的加减运算,无符号数的大小比较运算,移位 *** 作,字(位元组)之间移位,专门改变CF值的指令等。 2、奇偶标志PF(Parity Flag) 奇偶标志PF用于反映运算结果中“1”的个数的奇偶性。如果“1”的个数为偶数,则PF的值为1,否则其值为0。 利用PF可进行奇偶校验检查,或产生奇偶校验位。在数据传送过程中,为了提供传送的可靠性,如果采用奇偶校验的方法,就可使用该标志位。 3、辅助进位标志AF(Auxiliary Carry Flag) 在发生下列情况时,辅助进位标志AF的值被置为1,否则其值为0: (1)、在字 *** 作时,发生低位元组向高位元组进位或借位时; (2)、在位元组 *** 作时,发生低4位向高4位进位或借位时。 对以上6个运算结果标志位,在一般编程情况下,标志位CF、ZF、SF和OF的使用频率较高,而标志位PF和AF的使用频率较低。 4、零标志ZF(Zero Flag) 零标志ZF用来反映运算结果是否为0。如果运算结果为0,则其值为1,否则其值为0。在判断运算结果是否为0时,可使用此标志位。 5、符号标志SF(Sign Flag) 符号标志SF用来反映运算结果的符号位,它与运算结果的最高位相同。在微机系统中,有符号数采用补码表示法,所以,SF也就反映运算结果的正负号。运算结果为正数时,SF的值为0,否则其值为1。 6、溢出标志OF(Overflow Flag) 溢出标志OF用于反映有符号数加减运算所得结果是否溢出。如果运算结果超过当前运算位数所能表示的范围,则称为溢出,OF的值被置为1,否则,OF的值被清为0。 “溢出”和“进位”是两个不同含义的概念,不要混淆。如果不太清楚的话,请查阅《计算机组成原理》课程中的有关章节。 二、状态控制标志位 状态控制标志位是用来控制CPU *** 作的,它们要通过专门的指令才能使之发生改变。 1、追踪标志TF(Trap Flag) 当追踪标志TF被置为1时,CPU进入单步执行方式,即每执行一条指令,产生一个单步中断请求。这种方式主要用于程式的调试。 指令系统中没有专门的指令来改变标志位TF的值,但程式设计师可用其它办法来改变其值。 2、中断允许标志IF(Interrupt-enable Flag) 中断允许标志IF是用来决定CPU是否回响CPU外部的可禁止中断发出的中断请求。但不管该标志为何值,CPU都必须回响CPU外部的不可禁止中断所发出的中断请求,以及CPU内部产生的中断请求。具体规定如下: (1)、当IF=1时,CPU可以回响CPU外部的可禁止中断发出的中断请求; (2)、当IF=0时,CPU不回响CPU外部的可禁止中断发出的中断请求。 CPU的指令系统中也有专门的指令来改变标志位IF的值。 3、方向标志DF(Direction Flag) 方向标志DF用来决定在串 *** 作指令执行时有关指针暂存器发生调整的方向。具体规定在第5211节——字元串 *** 作指令——中给出。在微机的指令系统中,还提供了专门的指令来改变标志位DF的值。 三、32位标志暂存器增加的标志位 1、I/O特权标志IOPL(I/O Privilege Level) I/O特权标志用两位二进制位来表示,也称为I/O特权级栏位。该栏位指定了要求执行I/O指令的特权级。如果当前的特权级别在数值上小于等于IOPL的值,那么,该I/O指令可执行,否则将发生一个保护异常。 2、嵌套任务标志NT(Nested Task) 嵌套任务标志NT用来控制中断返回指令IRET的执行。具体规定如下: (1)、当NT=0,用堆叠中保存的值恢复EFLAGS、CS和EIP,执行常规的中断返回 *** 作; (2)、当NT=1,通过任务转换实现中断返回。 3、重启动标志RF(Restart Flag) 重启动标志RF用来控制是否接受调试故障。规定:RF=0时,表示“接受”调试故障,否则拒绝之。在成功执行完一条指令后,处理机把RF置为0,当接受到一个非调试故障时,处理机就把它置为1。 4、虚拟8086方式标志VM(Virtual 8086 Mode) 如果该标志的值为1,则表示处理机处于虚拟的8086方式下的工作状态,否则,处理机处于一般保护方式下的工作状态。

典型的堆栈不平衡嘛。这样肯定会有问题,想都不要想。

就像楼上说的,如果在retn前没有平衡堆栈,那么retn的时候,返回地址是错的,程序会跑哪去都有可能。

call的时候会将下一条指令地址压栈,retn的时后会pop一次,d出之前保存的eip,然后将当前eip的值还原,这样才能实现整个call的正常调用。

如果调用的时候堆栈没平衡好,就比如lz说的push之后忘了pop,那么程序执行retn的时候,还是会认为栈顶是保存的eip值,照样会设置eip的值,这样程序就乱套了,给什么样的错误提示就看系统心情了。

寄存器是CPU内部重要的数据存储资源,是汇编程序员能直接使用的硬件资源之一。

由于寄存器的存取速度比内存快,所以,在用汇编语言编写程序时,要尽可能充分利用寄存器的存储功能。

寄存器一般用来保存程序的中间结果,为随后的指令快速提供 *** 作数,从而避免把中间结果存入内存,再读取内存的 *** 作。在高级语言(如:C/C++语言)中,也有定义变量为寄存器类型的,这就是提高寄存器利用率的一种可行的方法。

另外,由于寄存器的个数和容量都有限,不可能把所有中间结果都存储在寄存器中,所以,要对寄存器进行适当的调度。根据指令的要求,如何安排适当的寄存器,避免 *** 作数过多的传送 *** 作是一项细致而又周密的工作。

有关“寄存器的分配策略”在《编译原理》中会有详细的介绍。

1、 16位寄存器组

16位CPU所含有的寄存器有(见图21中16位寄存器部分):

4个数据寄存器(AX、BX、CX和DX)

2个变址和指针寄存器(SI和DI) 2个指针寄存器(SP和BP)

4个段寄存器(ES、CS、SS和DS)

1个指令指针寄存器(IP) 1个标志寄存器(Flags)

2、 32位寄存器组

32位CPU除了包含了先前CPU的所有寄存器,并把通用寄存器、指令指针和标志寄存器从16位扩充成32位之外,还增加了2个16位的段寄存器:FS和GS。

32位CPU所含有的寄存器有(见图21中的寄存器):

4个数据寄存器(EAX、EBX、ECX和EDX)

2个变址和指针寄存器(ESI和EDI) 2个指针寄存器(ESP和EBP)

6个段寄存器(ES、CS、SS、DS、FS和GS)

1个指令指针寄存器(EIP) 1个标志寄存器(EFlags)

硬件处理 我们在每条指令完成的时候,控制单元就会检查是否发生了中断。若不发生:继续执行下

确定中断的向量i。

读IDT中的第i项得到向量i的中断描述符。

2

异常处理

保存寄存器的值

高级C函数处理异常

3中断描述符结合GDT得到得到中断处理程序的段描述符。

4进程的CPL与段描述符的DPL比较,若CPL优先级比DPL的优先级高,说明中断的优先级比进程优先级低,产生异常。进程的CPL与中断描述符的DPL比较,若CPL优先级

比DPL的优先级低,说明这个门不是用户进程可以访问的,也产生异常,正常则执行下面步骤。

5检查CPL是否发生变化(这个其实就是是否是从用户态进入内核态),如果变化,则要切换栈。这个很容易弄清,因为,用户态和内核态用的栈是不一样的。

6如果发生的是故障,故障要重新执行导致异常的那条指令。所以用那条指令的地址装载cs和eip来执行那条指令。

7将eflags、cs、和eip的值圧栈。

8如果异常产生硬件出错码,则也圧栈。

9用刚才得到的段描述符中的基址和中段描述符中的偏移地址装载cs和eip。这个就可以开始执行相应的处理程序了。

有意思的“错误” 。看注解吧,太详细解释我也说不清楚,可以探讨一下

void test(void) //这个是增加的“错误调用的显示函数”

{

printf("有意思的溢出");

}

void function(char str)

{

char buffer[16];

strcpy(buffer, str);

}

int main(int argc, char argv[])

{

int i,p;

void (pf)(void) = test; //pf 取得test()函数的地址 或者直接得到整数地址也可以

p = (int)pf; //p 保存test()函数的地址

char string[128];

for (i=0;i<127;i++)

{

string[i] = i+1; //原程序故意误导人,换成i+1后看错误提示一下子就知道从第几个字节溢出的了

}

string[127] = '\0';

string[28] = (char)p; //将显示函数地址写入溢出的地方

string[29] = (char)(p>>8);

string[30] = (char)(p>>16);

string[31] = (char)(p>>24);

printf("add of string is : 0x%x\n",&string);

printf("add of test() is : 0x%x\n",p);

function(string);

printf("This is a test!\n");

system("PAUSE");

return 0;

}

其实想知道这些东西,单从C代码上是看不出什么来的。反汇编后看汇编代码一清二楚。当一个父函数调用子函数时,在父函数中先将子函数用到的参数压入堆栈,然后再以一个call指令调用子函数。而call指令其实要做两件事:将自己的EIP值压入堆栈;以一个jmp跳转到子函数代码的开始位置。而在子函数内,首先就是这样:

MOV EBP,ESP

SUB ESP,0x100

也就是要将当前ESP保存到EBP,然后用一个SUB指令开辟子函数所用的局部内存空间。子函数对父函数的参数的引用一般都是EBP+4,EBP+8这样的,这样刚好就能访问父函数压入堆栈的参数。而对自己申明的参数的访问,就是EBP-0,EBP-4等等。对汇编不太熟悉的只从C代码的逻辑上去分析这样的问题,而实际情况是C代码要转换成机器代码,机器代码做的一些工作只有在汇编中能看到。堆栈就是一个传递参数的内存块,编译器在编译代码时,自动生成了子函数访问父函数参数的代码。

不知道这样说能不能帮你解决问题。

通用寄存器 4个 EAX、EBX、ECX和EDX 32位

段寄存器 6个 ES、CS、SS、DS、FS和GS

变址寄存器 2个 ESI和EDI 32位

堆栈寄存器 2个 ESP和EBP 32位

指令指针寄存器 1 EIP 32位

状态标志寄存器 1 EFlags 32位

控制寄存器 CR0-CR4

调试寄存器 DR0-DR7

测试寄存器 TR3-TR5

系统地址寄存器 2个 GDTR,IDTR 48位

通用寄存器

EAX通常称为累加器(Accumulator),用累加器进行的 *** 作速度最快

EBX称为基址寄存器(Base Register),可作为存储器地址指针来使用

ECX称为计数寄存器(Count Register)。在循环和字符串 *** 作时,可用它来控制循环次数

EDX称为数据寄存器(Data Register)。在进行乘、除运算时,作为默认 *** 作数参与运算

变址寄存器

ESI 指针寄存器的一种。是内存移动和比较 *** 作的源地址寄存器;

EDI 指针寄存器的一种。是内存移动和比较 *** 作的目标地址寄存器;

堆栈寄存器

EBP 指针寄存器的一种,堆栈基址指针寄存器确定堆栈帧的起始位置,

ESP 指针寄存器的一种,总是指向当前堆栈顶位置。

段寄存器

段寄存器是根据内存分段的管理模式而设置的。内存单元的物理地址由段寄存器的值和一个偏移量组合而成的,这样可用两

个较少位数的值组合成一个可访问较大物理空间的内存地址,CPU内部的段寄存器:

CS:代码段寄存器(Code Segment Register):和IP(是用来存放下条待执行的指令在该段的偏移量)合在一起可在该内存段内取到下次要执行的指令。

DS:数据段寄存器(Data Segment Register):

SS:堆栈段寄存器(Stack Segment Register):堆栈 *** 作所用的段寄存器和偏移量一定是SS和ESP

ES:附加段寄存器(Extra Segment Register): 串 *** 作的目标 *** 作数所用的段寄存器和偏移量一定是ES和EDI

FS:附加段寄存器(Extra Segment Register):

GS:附加段寄存器(Extra Segment Register):

指令指针寄存器

EIP:EIP的低16位为代码CS段的偏移量,高16位都为0。

状态标志寄存器

运算结果标志位

1、进位标志CF(Carry Flag):

进位标志CF主要用来反映运算是否产生进位或借位。如果运算结果的最高位产生了一个进位或借位,那么,其值为1,否则其值为0。使用该标志位的情况有:多字(字节)数的加减运算,无符号数的大小比较运算,移位 *** 作,字(字节)之间移位,专门改变CF值的指令等。

2、奇偶标志PF(Parity Flag):

奇偶标志PF用于反映运算结果中“1”的个数的奇偶性。如果“1”的个数为偶数,则PF的值为1,否则其值为0。利用PF可进行奇偶校验检查,或产生奇偶校验位。在数据传送过程中,为了提供传送的可靠性,如果采用奇偶校验的方法,就可使用该标志位。

3、辅助进位标志AF(Auxiliary Carry Flag):

在发生下列情况时,辅助进位标志AF的值被置为1,否则其值为0:

(1)、在字 *** 作时,发生低字节向高字节进位或借位时;

(2)、在字节 *** 作时,发生低4位向高4位进位或借位时。

4、零标志ZF(Zero Flag):

零标志ZF用来反映运算结果是否为0。如果运算结果为0,则其值为1,否则其值为0。

5、符号标志SF(Sign Flag):

符号标志SF用来反映运算结果的符号位,它与运算结果的最高位相同。运算结果为正数时,SF的值为0,否则其值为1。

6、溢出标志OF(Overflow Flag):

运算结果超过当前运算位数所能表示的范围,OF的值被置为1,否则,OF的值被清为0

7、状态控制标志位:状态控制标志位是用来控制CPU *** 作的,它们要通过专门的指令才能使之发生改变。

1、追踪标志TF(Trap Flag):

当追踪标志TF被置为1时,CPU进入单步执行方式。

2、中断允许标志IF(Interrupt-enable Flag):

CPU外部的不可屏蔽中断所发出的中断请求,以及CPU内部产生的中断请求。具体规定如下:

(1)、当IF=1时,CPU可以响应CPU外部的可屏蔽中断发出的中断请求;

(2)、当IF=0时,CPU不响应CPU外部的可屏蔽中断发出的中断请求。

CPU的指令系统中也有专门的指令来改变标志位IF的值。

3、方向标志DF(Direction Flag):

方向标志DF用来决定在串 *** 作指令执行时有关指针寄存器发生调整的方向。在微机的指令系统中,还提供了专门的指令来改变标志位DF的值。

8、32位标志寄存器增加的标志位:

1、I/O特权标志IOPL(I/O Privilege Level):

I/O特权标志用两位二进制位来表示,也称为I/O特权级字段。该字段指定了要求执行I/O指令的特权级。如果当前的特权级别在数值上小于等于IOPL的值,那么,该I/O指令可执行,否则将发生一个保护异常。

2、嵌套任务标志NT(Nested Task):

嵌套任务标志NT用来控制中断返回指令IRET的执行。具体规定如下:

(1)、当NT=0,用堆栈中保存的值恢复EFLAGS、CS和EIP,执行常规的中断返回 *** 作;

(2)、当NT=1,通过任务转换实现中断返回。

3、重启动标志RF(Restart Flag):

重启动标志RF用来控制是否接受调试故障。规定:RF=0时,表示“接受”调试故障,否则拒绝之。在成功执行完一条指令后,处理机把RF置为0,当接受到一个非调试故障时,处理机就把它置为1。

4、虚拟8086方式标志VM(Virtual 8086 Mode):

如果该标志的值为1,则表示处理机处于虚拟的8086方式下的工作状态,否则,处理机处于一般保护方式下的工作状态。

以上就是关于程序计数器PC和寄存器EIP有什么关系吗,为什么它们都是存放下一条指令的地址全部的内容,包括:程序计数器PC和寄存器EIP有什么关系吗,为什么它们都是存放下一条指令的地址、CPU存储器详细资料大全、汇编中pop和push是成对使用的,如果我只用push不用pop,最后执行时会出现无效命令,求大神指教。等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/9574922.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-29
下一篇 2023-04-29

发表评论

登录后才能评论

评论列表(0条)

保存