相关疑难解决方法(0)

在ESP下面写下是否有效?

对于32位Windows应用程序,使用ESP下面的堆栈内存进行临时交换空间而不显式减少ESP是有效的吗?

考虑一个返回浮点值的函数ST(0).如果我们的价值目前在EAX,我们会,例如,

PUSH   EAX
FLD    [ESP]
ADD    ESP,4  // or POP EAX, etc
// return...
Run Code Online (Sandbox Code Playgroud)

或者不修改ESP寄存器,我们可以:

MOV    [ESP-4], EAX
FLD    [ESP-4]
// return...
Run Code Online (Sandbox Code Playgroud)

在这两种情况下都会发生同样的事情,除了在第一种情况下我们注意在使用内存之前递减堆栈指针,然后在之后递增它.在后一种情况下,我们没有.

尽管有任何实际需要在堆栈上持久保存这个值(重入问题,在PUSH返回值和读取值之间的函数调用等),有没有任何根本原因,为什么写入ESP下面的堆栈这样会无效?

windows x86 assembly abi

11
推荐指数
3
解决办法
447
查看次数

返回地址预测堆栈缓冲区与堆栈存储的返回地址?

一直在阅读Agner Fog的"Intel,AMD和VIA CPU的微架构"和第34页,他描述了"返回地址预测":

http://www.agner.org/optimize/microarchitecture.pdf

3.15返回(除P1外的所有处理器)

返回使用更好的方法.每次执行调用指令时,一个称为返回堆栈缓冲区的后进先出缓冲区会记住返回地址,并使用它来预测相应返回的去向.当从几个不同的位置调用相同的子例程时,此机制可确保正确预测返回指令.

鉴于返回地址仍然存储在堆栈中,我有点不清楚对此的需求是什么?

那么如果还有这种技术,在堆栈上存储返回地址的目的是什么?堆栈存储值是否仅在此预测技术不起作用时使用?

architecture cpu performance x86 intel

8
推荐指数
1
解决办法
2868
查看次数

7
推荐指数
1
解决办法
1万
查看次数

什么是pushl/popl%esp的汇编级表示?

C++

ATT大会

我试图理解以下两条指令的行为:

pushl %esp
Run Code Online (Sandbox Code Playgroud)

和:

popl %esp
Run Code Online (Sandbox Code Playgroud)

请注意,它们将计算出的值存储回来%esp.

我正在独立地考虑这些指令,而不是按顺序.我知道存储的值%esp总是递增/递减之前的值,但是我怎么能用汇编语言表示行为呢?这是我到目前为止所提出的:

推送:

movl %esp, %edx     1. save value of %esp
subl  $4, %esp      2. decrement stack pointer
movl %edx, (%esp)   3. store old value of %esp on top of stack
Run Code Online (Sandbox Code Playgroud)

对于pop:

movl (%esp), %esp   You wouldn’t need the increment portion. 
Run Code Online (Sandbox Code Playgroud)

它是否正确?如果没有,我哪里错了?谢谢.

x86 assembly stack att

7
推荐指数
1
解决办法
9187
查看次数

编译器为什么在子程序之间插入INT3指令?

在调试某些软件时,我注意到在很多情况下,子程序之间插入了INT3指令.

这是一个例子.

我假设这些技术上并没有在'之间'插入函数,而是在它们之后,为了暂停执行,如果子程序retn在最后没有执行,无论出于何种原因.

我的假设是否正确?如果不是,这些说明的目的是什么?

compiler-construction x86 assembly

5
推荐指数
2
解决办法
870
查看次数

x86 和 x64 中的 ret 指令有什么区别?

我最近在 x64 上尝试堆栈溢出练习。在 x86 上执行此操作时,我预计垃圾覆盖地址会出现以下情况(例如“AAAA”):

  1. 我提供的数据溢出缓冲区,并覆盖返回地址
  2. 之后ret,(覆盖的)返回地址将(有效)弹出到 EIP 寄存器中
  3. 意识到该地址无效,并引发分段错误

在 x64 中,这似乎有所不同(除了上述步骤中 EIP 与 RIP 的互换之外)。当提供“AAAAAAA”垃圾地址时,处理器似乎会在弹出该地址之前进行一些有效性检查。通过观察,在加载地址之前,似乎要求地址的两个最高有效字节为空。否则,会发生段错误。我相信这是由于 x64 中使用了 48 位寻址,但我的印象是以 0xFFFF 开头的地址也是有效的,但这也会产生段错误。

这是对差异的准确描述吗?为什么这个检查是在数据加载到RIP寄存器之前执行的,而另一个有效性检查是在数据加载到RIP寄存器之后执行的?这些说明之间还有其他差异吗?

编辑:为了澄清我的观察,我注意到当提供 8 字节返回地址时,RIP 仍然指向指令的地址ret,并且 RSP 仍然指向段错误时被覆盖的返回地址。当提供 6 字节返回地址时,当观察到段错误时,覆盖的地址已被弹出到 RIP 中。

x86 assembly return x86-64

4
推荐指数
1
解决办法
3158
查看次数

在x86程序集中的过程中调用ret指令的位置是否重要?

我目前正在学习x86程序集.但是当我使用堆栈进行函数调用时,我仍然不清楚某些事情.我知道调用指令将涉及在堆栈上推送返回地址,然后加载程序计数器和要调用的函数的地址.ret指令将该地址加载回程序计数器.

我的困惑是,在过程/函数中调用ret指令时是否重要?它是否总能找到存储在堆栈中的正确返回地址,或者堆栈指针当前是否必须指向存储返回地址的位置?如果是这种情况,我们不能只使用push和pop而不是call和ret吗?

例如,下面的代码可能是进入函数的第一个代码,如果我们在堆栈上推送不同的寄存器,则必须在以相反的顺序弹出寄存器之后才调用ret指令,以便在pop%ebp指令之后,堆栈指针将指向返回地址所在的堆栈上的正确位置,或者无论它在何处被调用,它仍会找到它?提前致谢

push %ebp
mov %ebp, %esp
//push other registers

...
//pop other registers
mov %esp, %ebp
(could ret instruction go here for example and still pop the correct return address?)
pop %ebp
ret
Run Code Online (Sandbox Code Playgroud)

x86 assembly stack call

0
推荐指数
2
解决办法
724
查看次数