2016-12-16 72 views
0

当调用POP时,CPU如何知道将什么值放回寄存器?推送和弹出寄存器内容时如何存储相关数据

如果例如我们PUSH ECX,调用一些修改ECX内容的程序,然后调用POP ECX,指令pushpop之间的ECX之间的原始值是如何关联的?

是否有自动生成的附加指令来存储此值并将其绑定到指令?

+1

推动和弹出是单独的说明。他们只是存储或加载和修改ESP。在insn set ref中查找它们:http://www.felixcloutier.com/x86/。他们除了在“操作”部分中看到的内容外没有其他更多的事情。 –

+1

它使用内存区域作为堆栈。所以'push'只是写入内存,'pop'读回它。唯一的链接是堆栈指针,并且你弹出到同一个地方。 '推eax; pop ecx'是合法的,当然会将'ecx'设置为'eax'。 'push eax'基本上等价于:'lea esp,[esp-4]; mov [esp],eax' – Jester

+0

啊,所以弹出只是弹出堆栈顶部的任何内容到目的地? – jarryd

回答

3

PUSHPOP是非常简单的说明。他们只是存储或加载和修改ESP。

您可以POP用不同的存储指令写入的东西,反之亦然。

它们什么都不做,也不比在“操作”部分看到的内容更少(请参阅英特尔指令集引用的HTML提取文件的链接,这是您在任何时候想知道指令一样)。有关更完整的索引,请参阅here;有关更多链接,请参阅标记wiki。

由您决定什么都不会覆盖堆栈内存,您在其中推入您想要稍后检索的内容。请注意,允许函数修改堆栈中的参数,因此您需要重新存储参数以使用相同的参数再次调用相同的函数(除非您编写了函数,并且可以保证它不会破坏该内存) 。


有没有产生额外的指令自动

标准的x86汇编语法没有任何伪指令,组装到多个机器指令。

典型的RISC系统可以轻松生成将任意32位常量放入寄存器所需的一对指令。 MIPS asm语法甚至具有隐式使用寄存器的伪指令!相反,x86的CISC设计使得硬件可以处理所有这些复杂性。您可以将一个64位常量放入一个10字节的寄存器中mov rcx, 0x123456789ABCD

1

推动和弹出只是访问堆栈的方式,因此理解堆栈是关键。堆栈就是RAM。例如,对于全局变量,RAM中有一个内存位置(为了参数)专用于该变量。所以当你访问变量的RAM版本时,你正在读写一个固定的地址。但是使用局部变量(对于支持递归的语言),对于该函数的每个实例,您需要该变量的新副本。要递归地调用十个调用,您需要十个内存位置来存储该变量的十个副本。一个堆栈使这个微不足道。您可以将其视为分配和释放内存,如malloc()free(),但非常简单。

push和pop是喜欢做的在C以下:

sp--; 
*sp = x; 
x = *sp; sp++; 

的CPU什么都不知道,也不关心保护你的原始值什么。程序员(间接通过编译器)要求完成任务,并且在使用堆栈保存寄存器值的情况下,如果使用汇编语言,编译器或者直接使用push来“保存堆栈中的值“,并弹出”从堆栈中恢复值“。

由编程人员或编译器来确保对堆栈指针的push和pops以及其他修改确保push ecxpop ecx在同一个RAM地址上运行。如果这样做,那么“CPU如何知道”是ecx被写入到地址X,并且在某个时间点之后地址X被读取并且值被放置在ecx中。对于全局变量,该变量的地址M是程序生命周期的固定地址。如果由于某种原因该变量的内容需要在寄存器中,则从M中读取它,然后将其返回给M.但是,在使用堆栈时,可以在一段时间内快速分配内存,比如说一个函数 - 输入函数,如果你想要32字节,那么你只需要sp = sp-32,而你现在只分配了32个字节。然后,您可以通过推送(另外分配4个字节)将ecx“保存在堆栈中”,或将其保存在某个地址,如sp+8。然后,在离开函数之前,您可以读取sp+8并将该值返回ecxsp+8是地址X,其中ecx已保存。

,你可以代替,在任何时候,push ecx进入功能或者说真的,分配4个字节,写ecx到该地址,X.如果你再push edx,这将是在地址X-4。后来(如果你保持堆栈指针访问正确配对),那么当你pop edx它将来自地址X-4,然后来自X的pop ecx。那么写入地址X的地址 - 你原来的值ecx - 现在被读取返回并且ecx返回到其原始值。

相关问题