- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我没有清楚地理解 LEAVE 函数,它是这两条指令的浓缩:
MOV ESP, EBP
POP EBP
因此,MOV ESP, EBP
将 ESP 向下移动到 EBP 的级别(堆栈的开头)。
然后POP EBP
,将ESP指向的值移动并影响到EBP,同时将ESP向下移动一步。
但我真的不明白,这两个操作如何与离开函数的事实联系起来(这是 LEAVE
的目的)。
您能帮我澄清一下吗?
最佳答案
在 32 位和 16 位时代,常见的序言是例程开始时的指令序列
push ebp
mov ebp, esp
sub esp, <local_var_size>
push <clobbered_reg1>
push <clobbered_reg2>
...
这里没有什么是随意的,指令的顺序很重要,我们最终得到
|parN | <-- EBP + 04 + n*4 par1..parN = Routine parameters
... ... ra = Return address
|par2 | <-- EBP + 0ch o ebp = Original (caller) EBP
|par1 | <-- EBP + 08h lvar1..lavarM = Local variables
|ra | <-- EBP + 04h creg1..cregK = Clobbered registers
|o ebp| <-- EBP
|lvar1| <-- EBP - 04h
|lvar2| <-- EBP - 08h
... ...
|lvarM| <-- EBP - m*4
|creg1|
|creg2|
...
|cregK| <-- ESP
看看如何使用 ebp
中的合适指针轻松访问所有数据。 (参数作为连续的正偏移量大于或等于 8,局部变量作为负偏移量小于或等于 4)以及该模型对于更多数量的局部变量或参数的扩展效果如何。
为此ebp
称为帧指针。
尾声必须消除这一切。
一种可能的变体是
pop <clobbered_regK>
...
pop <clobbered_reg1>
add esp, <local_var_size>
pop ebp
ret n*4
然而,这涉及重复<local_var_size>
- 很容易忘记保持两个版本同步。
我们可以利用ebp
这一事实值为 esp
在分配本地变量之前,因此通过恢复该值,我们可以有效地取消分配它们。
pop <clobbered_regK>
...
pop <clobbered_reg1>
mov esp, ebp
pop ebp
ret n*4
但是从最后开始的第三条和第二条指令是leave
指令确实如此。所以:
pop <clobbered_regK>
...
pop <clobbered_reg1>
leave
ret n*4
是等效的序言。
<小时/> enter
是一条非常慢的指令( https://agner.org/optimize ),因此编译器从不使用它,但 leave
可用于优化代码空间,对性能影响很小(可以通过节省代码大小来平衡)。 GCC 使用leave
当 pop ebp
其本身是不够的,大多数 -mtune=
设置。
在当前的 Intel CPU(例如 Skylake)上,leave
总共花费 3 个 uop,而 mov esp, ebp
则需要 2 个 uop/pop ebp
。在真实的测试用例中,通过调用(从重复循环)一个实际的小函数来解释堆栈同步微指令中可能存在的差异,该函数将 EBP 设置为帧指针并分配一些堆栈空间,然后将其拆除,测量的硬件性能计数器left 函数每次调用比 mov/pop 函数多占用 1 个前端 uop。但由于某种未知的原因,leave 函数运行得稍微快一些,即使两者都对齐了 32。(@petercordes 运行了这个测试。)
关于assembly - 需要一些关于汇编语言中 LEAVE 指令的解释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41907672/
我不确定 cbw命令实际上可以。我有一段代码: mov ax,0FF0h cbw idiv ah cbw后ax的值如何变化? 最佳答案 cbw指令将一个字节符号扩展为一个字。在这种情况下,它将采用
MIPS 架构中的.s 和.asm 有什么区别? 最佳答案 .s 和.asm 之间没有天生的区别 如果你愿意,你可以用 .s 命名文本文件,用 .asm 命名十六进制文件,但这只是为了让它们保持正直。
我正在业余时间学习汇编语言,以成为更好的开发人员。 我在概念层面上理解基于堆栈的机器和基于寄存器的机器之间的区别,但我想知道基于堆栈的机器实际上是如何实现的。如果是虚拟机,例如JVM 或 .NET,在
几周后我开始上大学(软件工程学位),并且知道我将在第一年学习的一个模块是“建筑基础”或类似的东西;基本上它是在学习“汇编”中的编程。 我想做一些背景学习,所以我为此做好了准备(我在其他一些单元上做了同
我是汇编语言的新手。我目前正在经历这个 Assembly Guide .我对 LEA 指令有疑问。我对LEA指令的理解是LEA用source operand的有效地址加载destination ope
x86 汇编中是否有模运算符或指令之类的东西? 最佳答案 如果您的模数/除数是一个已知常数,并且您关心性能,请参阅 this和 this .对于直到运行时才知道的循环不变值,乘法逆甚至是可能的,例如见
我是汇编语言的新手。我目前正在经历这个 Assembly Guide .我对 LEA 指令有疑问。我对LEA指令的理解是LEA用source operand的有效地址加载destination ope
我相信这对大多数人来说非常简单,但我对 x86 汇编语言不是很熟悉。我只是想自学。 我在 window 里。在我读到的任何地方,我都被告知要使用 INT 21返回操作系统。这退出了程序,但我收到一条错
我正在尝试输入一个字符串,然后查看该字符串中的最后一个值是否为 EOL 字符。我想我会使用读入的字符串的长度,然后将它添加到缓冲区的地址以找到最后一个元素。这似乎不起作用。 编辑:很抱歉我没有包含更多
; This program checks for even or odd parities inside of an array. Displays 1 if even or 0 if odd. I
我一直在努力掌握 x86 汇编语言,并且想知道是否有一个与 movl $1, %eax 等效的快速简短的语言。就在那时,我认为列出该语言中经常使用的习语可能是个好主意。 这可能包括首选使用 xorl
有人知道如何在 ARMv6 汇编语言中开始注释(例如“#”、“;”、“/”、“/*”)吗? 最佳答案 应该是“;”根据我在 wikipedia article: 上找到的一些示例代码 loop
; This program checks for even or odd parities inside of an array. Displays 1 if even or 0 if odd. I
我是一名利用业余时间学习汇编语言的大学生。我注意到虽然有像 add 和 mul 这样的指令,但算术运算符经常在指令中使用。例如: mov eax,[ebx+ecx] 它等价于以下吗? add ebx,
我真的是学习汇编语言的新手,并且刚刚开始研究汇编语言,所以我想知道也许有些人可以帮助我解决一个问题。我有一个作业,告诉我将汇编语言指令与C代码进行比较,并告诉我哪些C代码与汇编指令等效。所以这是组装说
假设我有以下代码: C++ 代码和内联汇编代码如下: 方程式: X=40+5 Y=3*12 ---> X=45 Y=36 测试 if x < y - print x+y else print x-y
我正在编写一个程序,其中的要求如下: 有一个名为 Name 的字符串变量,该变量设置为您的全名,包括空格。 只清除 AL 寄存器,不清除 EAX 寄存器的其余部分。 遍历 Name 变量中的每个字符。
我有一个任务,描述如下: - Reads printable characters (20h-7Fh) from the keyboard without echoing - Uppercase le
我正在查看 switch 语句的汇编语言代码。 我了解代码的工作原理以及情况。我的问题是如何决定案例名称? 下面是汇编语言代码,下面是我的解释。我基本上只需要使用跳转表并填写案例名称。 1 8
我是汇编语言新手,我想到了这个问题:构建代码、宏或过程哪个是更好的解决方案?虽然宏中包含的代码只是复制到所需的部分,并且允许执行代码而无需昂贵的跳转,但它确实添加了必须在程序执行时加载的额外指令。此外
我是一名优秀的程序员,十分优秀!