Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 堆栈和寄存器如何在汇编程序中工作?_Assembly - Fatal编程技术网

Assembly 堆栈和寄存器如何在汇编程序中工作?

Assembly 堆栈和寄存器如何在汇编程序中工作?,assembly,Assembly,我知道有EBP、ESP、EAX等等,使用这些寄存器,就可以进行堆栈和所有的堆栈。如果某个寄存器(即EBP)是堆栈,而ESP和其他寄存器则堆叠在EBP的顶部,以堆叠在EBP上,我会感到困惑 或者堆栈只是内存分配(边界)的可视化,以便更好地理解内存,寄存器才是真正的内存 让我困惑的是,当main函数调用函数时: 在main中,在调用函数之前,函数的任何参数都会从EAX推送到ESP,然后对函数执行“调用”,将返回地址(main中“调用”之后的下一个地址)推送到堆栈(我认为返回地址与函数的参数一起堆叠在

我知道有EBP、ESP、EAX等等,使用这些寄存器,就可以进行堆栈和所有的堆栈。如果某个寄存器(即EBP)是堆栈,而ESP和其他寄存器则堆叠在EBP的顶部,以堆叠在EBP上,我会感到困惑

或者堆栈只是内存分配(边界)的可视化,以便更好地理解内存,寄存器才是真正的内存

让我困惑的是,当main函数调用函数时:

在main中,在调用函数之前,函数的任何参数都会从EAX推送到ESP,然后对函数执行“调用”,将返回地址(main中“调用”之后的下一个地址)推送到堆栈(我认为返回地址与函数的参数一起堆叠在ESP上,以便在调用函数时堆叠在EBP上。我认为这是错误的吗?),然后将EIP移动到函数的开头

然后,当调用函数时,EBP被推送(再次?这是因为在函数内部,EBP什么都不是?但EBP寄存器不是已经包含了一些主值吗?),ESP值被推送到EBP上(这就是为什么我认为EBP是堆栈。在这一点上,EBP上的所有内容都被堆叠,不是吗?),然后,ESP是“sub”使用一些值为函数的局部变量提供空间。(当在函数入口将ESP推到EBP上时,ESP是否具有ESP值?还是它已清空?)

在函数结束时,函数会执行“离开”和“ret”,这会删除函数的堆栈帧(EBP?或ESP?或只是“堆栈帧”,它既不是EBP也不是ESP?如果它会删除EBP或ESP,那么main的EBP会发生什么情况?我读到EBP是从堆栈指针重新初始化的,但堆栈指针何时被推到堆栈上的?)然后执行“ret”,对于该地址,EIP将移动到返回地址,该地址在执行函数“call”之前被推入“main”中


所以我很困惑,因为我不确定“堆栈”是一个特定的寄存器还是一个灵活的内存边界,以便更好地理解。我也不确定堆栈指针被推到堆栈上的位置和时间。

您的理解是正确的,堆栈只是内存中的一个位置。堆栈与寄存器相比是相当大的

你可以看看这个堆栈,就像一堆煎饼。堆栈的属性是,你只能从顶部添加或删除元素

有两个寄存器有助于组织这种内存结构。第一个是(E)SP,它是堆栈指针的缩写。另一个是(E)BP,它是基指针

为了理解为什么我们需要这两个寄存器,我们需要查看堆栈允许的操作。有PUSH和POP

推送有两个功能:

SUB ESP,4
MOV [ESP],REGISTER,
这将减少堆栈指针,并将寄存器保存到新位置

POP的作用正好相反:

MOV REGISTER,[ESP]
ADD ESP,4
这会将堆栈顶部的内容移动到寄存器,并相应地移动指针

现在让我们看看函数使用参数的方式

在函数开始时,我们可以通过[ESP+4]、[ESP+8]访问参数。但是当我们想要一些局部变量时会发生什么?更改ESP将使上述语句无效

这就是基本指针的作用。在每个函数的开头,我们都有所谓的prolog:

PUSH EBP
MOV EBP,ESP
这将保存上一个基指针,并保存堆栈指针,这样我们就可以获得参数的偏移量,而不用担心堆栈指针的变化

在函数的末尾,您将看到一个epilog,其中包括弹出EBP的旧值。

堆栈只是内存。处理器中的某个地方有一个“堆栈指针”.关于堆栈的事情是,你不关心它在内存中的确切位置,一切都是相对于堆栈指针的,堆栈指针加上或减去一些内存位置

希望/假设你的堆栈有足够的空间来完成你的程序需要做的事情(这是另一个主题)。因此,在这方面,堆栈只是一堆内存,而不仅仅是一个寄存器值的数据

把堆栈想象成一堆东西,实际上是一堆内存位置,但可能是一堆索引卡,你可以在上面写各种东西。图片通常会有帮助

[     ]  <- sp
在我们推b之前

[stuff] <-sp
[  b  ] <- sp
[stuff] 

[stuff]使用EBP作为基指针或帧指针是可选的。某些编译器(如Microsoft)可以选择禁用帧指针,在这种情况下,EPB被释放用作通用寄存器,所有堆栈相对引用都作为ESP的偏移量


在16位实模式下,SP不能用作内存操作数的基址寄存器或索引,因此BP必须用于堆栈相对引用。

堆栈是内存中的一个区域,ESP和EBP不是堆栈,它们只是用作指向它的指针(在堆栈上保存内存地址的值).您的困惑可能来自这样一个事实,即我们使用堆栈临时存储“old”调用层次结构上层的指针。干净如天空。我希望我能无限次地回答这个问题。你彻底打破了我的沉默。非常感谢。所以SFP只是一个容易找到参数的偏移量,堆栈和寄存器不一样。再次感谢。堆栈指针和帧指针可能有dif取决于处理器的不同名称只是用来保存地址的寄存器。有些处理器是通用的,有些仅用于此目的,有些帧指针只是常规寄存器。有些体系结构通常不在堆栈上传递项(除非项太多)同样地,有些人也不使用堆栈作为返回值,但不管是哪种处理器,你都可以画出这样的图片来保持事情的有序性在x86的好日子里,也许还有一些剩余的东西,你有远近调用或内存模型,小的,小的,中的,小的
[  b  ] <- sp
[stuff] 
[  a  ] <- sp
[  b  ] 
[stuff] 
[retadd] <- sp
[  a  ] 
[  b  ] 
[stuff] 
[retadd] <- sp + 0
[  a  ]  <- sp + 4
[  b  ]  <- sp + 8
[stuff]  <- sp + 12
push fp since we are going to modify it we don't want to mess up the callers fp register
fp = sp;  (Frame pointer (ebp) = stack pointer (esp));


[  fp ]  <- sp + 0  <- fp + 0
[retadd] <- sp + 4  <- fp + 4
[  a  ]  <- sp + 8  <- fp + 8
[  b  ]  <- sp + 12 <- fp + 12
[stuff]  <- sp + 16 <- fp + 16
[  x  ]  <- sp + 0  <- fp - 8
[  x  ]  <- sp + 4  <- fp - 4
[  fp ]  <- sp + 8  <- fp + 0
[retadd] <- sp + 12 <- fp + 4
[  a  ]  <- sp + 16 <- fp + 8
[  b  ]  <- sp + 20 <- fp + 12
[stuff]  <- sp + 24 <- fp + 16
[  fp ]  <- sp + 0  <- fp + 0
[retadd] <- sp + 4  <- fp + 4
[  a  ]  <- sp + 8  <- fp + 8
[  b  ]  <- sp + 12 <- fp + 12
[stuff]  <- sp + 16 <- fp + 16
[retadd] <- sp + 0
[  a  ]  <- sp + 4
[  b  ]  <- sp + 8
[stuff]  <- sp + 12
[  a  ]  <- sp + 0
[  b  ]  <- sp + 4
[stuff]  <- sp + 8
[stuff]  <- sp + 0