假设我在x86程序集中编写例程,比如"add",它添加了两个作为参数传递的数字.
在大多数情况下,这是一个非常简单的方法:
push ebp
mov ebp, esp
mov eax, [ebp+8]
add eax, [ebp+12]
mov esp, ebp
pop ebp
ret
Run Code Online (Sandbox Code Playgroud)
但是,有没有什么方法可以重写这个方法来避免使用"ret"指令并仍然产生完全相同的结果?
对于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下面的堆栈这样会无效?
我正在阅读http://www.realworldtech.com/sandy-bridge/,我在理解一些问题时面临一些问题:
专用堆栈指针跟踪器也存在于Sandy Bridge中并重命名堆栈指针,消除了串行依赖性并删除了多个uop.
什么是dedicated stack pointer tracker实际?
对于Sandy Bridge(和P4),英特尔仍然使用术语ROB.但重要的是要理解,在这种情况下,它只引用了飞行中uops的状态数组
事实上它意味着什么?请说清楚.
我对pop组装中的实际操作感到困惑.是否pop将值PUSHed最后移动到堆栈上(意味着如果我们MOV在最后一个元素之后的值,它不适用PUSH)或者它只是弹出堆栈中最后一个值(因此,应用于两个MOV和PUSH),或者它会弹出堆栈指针指向的值吗?请考虑以下代码:
push $4
mov $5, -4(%esp)
add $4, %esp (esp pointing to an unknown value)
pop %ebp
Run Code Online (Sandbox Code Playgroud)
所以在这段代码中,值的值ebp是4,5,还是指向的未知值esp?
在x86架构中,可以做什么EAX但不能用ESP?忘了push和pop和call.
目前在我看来,我们拥有像“Push”这样的指令的唯一原因是用一条指令替换多个 MOV 和算术指令。
有没有更原始的指令不能完成的“PUSH”?
“PUSH”只是一个编译成多个机器代码指令的助记符吗?
我是 x86 汇编的新手,并且已经阅读了这篇讨论 NASM x86 中的使用的文章scanf。这很有启发性,但是大多数答案都resd在本节中使用了全局变量.bss。相反,我想scanf通过以下 C 程序进入局部变量:
#include <stdio.h>
int main(void) {
int x;
scanf("%d", &x);
return x;
}
Run Code Online (Sandbox Code Playgroud)
x86 代码:
#include <stdio.h>
int main(void) {
int x;
scanf("%d", &x);
return x;
}
Run Code Online (Sandbox Code Playgroud)
我遵循 CDECL 调用约定,并使用 C 32 位运行时以及 C 32 位标准库进行链接。
; demo.asm
global main
extern scanf
section .data
fmt: db "%d", 0x00
section .text
main:
; prologue
push ebp
mov ebp, esp
; body
; allocate int …Run Code Online (Sandbox Code Playgroud) 我正在检查 C 代码,其中我必须计算出特定程序跟踪中使用的寄存器数量。每当遇到推送或弹出命令时,代码都会忽略存储 ESP 寄存器。我还引用了 X86 指令,它那里写着“ESP,堆栈指针,不应该使用”。为什么?
我想通过将 CPU 标志压入堆栈来读取它们,然后将它们弹出到寄存器中,如下所示:
uint32_t getEflags() {
uint32_t eflags;
asm ("pushf");
asm ("pop %eax");
asm ("mov %%eax, %0" : "=r"(eflags));
return eflags;
}
Run Code Online (Sandbox Code Playgroud)
现在我发现这是一个错误,因为Pushf只压入 EFLAGS 的低 16 位,然后我将它们弹出到 32 位寄存器中(我需要Pushfd)。
这意味着我弹出的内容基本上比最初推送的要多 - 返回这里时我的堆栈会发生什么情况?
好吧,堆栈是如何工作的?例如说明:
push ax
Run Code Online (Sandbox Code Playgroud)
等于:
sub sp, 4
mov sp, ax
Run Code Online (Sandbox Code Playgroud)
其中sp是堆栈指针.是对的吗?
我的问题是 - 如果片刻后我将其更改为完全不同的值,那么从sp寄存器中减去4是什么意思?