在汇编的情况下,编程模型与程序计数器和堆栈指针之间有区别吗?

use*_*312 1 x86 assembly mips program-counter stack-pointer

处理器型号 I

 ? Registers  
   ? PC – Program Counter  
   ? Single data register (accumulator) without name  
   ? We will use symbol A to describe operations on this register  
 ? Stack with an unspecified implementation  
 ? Data specified by name or value  
   ? More realistic model will follow later 

  Instruction     Action         Description  
  ---------------------------------------------------------------------
  load data       A = data       Load data to accumulator  
  store data      data = A       Store data from accumulator to memory  
  add data        A += data      Add data to accumulator  
  push data                      Push data onto stack  
  call addr       Push PC        Jump and store return trace on the stack 
                  PC = addr
                  Pop PC 
  return          Pop PC         Return – jump to the previously stored trace addr  
  create data                    Allocate data on stack  
  destroy data                   Deallocate data from stack   
Run Code Online (Sandbox Code Playgroud)

处理器型号 II

? More realistic version of model I  
? Stack explicitly implemented in memory  
? Stack Pointer register - SP  
? Stack operations defined explicitly using SP  
? Allocation and deallocation of local data implemented 
   by changing the value of SP (no data transfer occurs)
? Arguments and local variables accessed by names  
   ? Still unrealistic  

  Instruction    Action               Description
  ---------------------------------------------------------------------
  load data      A = data             Load data to accumulator (constant or variable)
  store data     data = A             Store data from accumulator to memory
  add data       A += data            Add data to accumulator (constant of variable)
  push data      *--SP = data         Place data on the stack (constant of variable)
  call addr      *--SP = data         Jump storing the return trace on the stack
                 PC = addr            
  return         PC = *SP++           Return to the previously stored trace address
  Create data    SP -= sizeof(data)   Allocate data on the stack
  Destroy data   SP += sizeof(data)   Deallocate data from the stack
Run Code Online (Sandbox Code Playgroud)

以上两张幻灯片是在 x86/MIPS 的演讲中展示的。我没太明白。

我唯一理解的是,有两种使用堆栈调用函数和分配/释放堆的模型。一个使用PC,另一个使用SP。

它是在讨论两种不同处理器 (x86/MIPS) 的模型吗?哪个是给谁的?

有好心人能解释一下吗?

Pet*_*des 5

两者都是类似 x86 的,其中call将返回地址 (PC) 压入堆栈。注意,call指令执行期间的 PC指向指令的结束/下一条指令的开始,所以 PC 是ret从 a之后应该执行的指令的地址call

第二个模型只是更加明确栈是如何工作的,匹配的x86 push/ pop/ call/ ret。这就是它改变的全部

MIPSjal将返回地址放入寄存器(链接寄存器$lr是 MIPS 上的 32 个通用整数寄存器之一)。软件可以手动将其压入堆栈(例如在非叶函数中),但 ISA 不知道/不关心这一点。

MIPS 甚至在架构上都没有隐式用于任何事物的“堆栈指针”。调用堆栈是一种软件约定,尽管它非常有用,基本上所有软件以与 x86 基本相同的方式使用它,只是没有结合修改 SP 和加载或存储的单个指令。

我唯一理解的是,有两种使用堆栈调用函数和分配/释放堆的模型。一个使用PC,另一个使用SP。

不,这在所有层面上都是完全错误的。

首先,没有一个例子显示任何关于堆内存的内容,只是在堆栈中为局部变量(自动存储)保留空间。函数返回时将释放的存储空间。

“堆”内存是分开的。它通常不是一回事,例如静态和动态分配在现代操作系统中通常是分开的。但无论如何,动态堆分配之类的malloc会给你一个指向内存的指针,该指针在add sp, 16或之后仍然有效并ret拆除当前函数的堆栈帧。

第二,PC根本不参与存储分配。细节只显示 PC 被读取为返回地址,并由跳转/调用/ret 指令写入。它也被称为 IP,即指令指针。在 x86 上,32 位和 64 位版本的 IP 寄存器分别是 EIP/RIP。