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
Assembly 我是否正确理解此Y86汇编代码中的堆栈?_Assembly_Stack_Y86 - Fatal编程技术网

Assembly 我是否正确理解此Y86汇编代码中的堆栈?

Assembly 我是否正确理解此Y86汇编代码中的堆栈?,assembly,stack,y86,Assembly,Stack,Y86,我创建了这个简单而无意义的汇编(Y86)代码,以查看当使用指令调用、push、popl和ret时,我是否理解堆栈中发生的所有事情 正如我所说,这段代码是毫无意义的,它只是为了测试/学习的目的。尽管如此,所有内存地址的计算都是正确的(有希望的),并且不是随机的 装配代码如下所示: | .pos 0 0x00 | irmovl Stack, %esp 0x06 | rrmovl %esp, %ebp 0x08 | irmovl $5, %eax 0x0E | call fu

我创建了这个简单而无意义的汇编(Y86)代码,以查看当使用指令调用、push、popl和ret时,我是否理解堆栈中发生的所有事情

正如我所说,这段代码是毫无意义的,它只是为了测试/学习的目的。尽管如此,所有内存地址的计算都是正确的(有希望的),并且不是随机的

装配代码如下所示:

     | .pos 0
0x00 |   irmovl Stack, %esp
0x06 |   rrmovl %esp, %ebp
0x08 |   irmovl $5, %eax
0x0E |   call func
0x13 |   halt
0x14 | func:
0x14 |   pushl %ebp
0x16 |   rrmovl %esp, %ebp
0x18 |   pushl %eax
0x1A |   popl %eax
0x1C |   popl %ebp
0x1E |   ret
     | .pos 50
0x32 | Stack: .long 0
下面是我绘制堆栈并解释每个步骤(指令)对堆栈的作用的最佳方法。请注意,我使用SP和BP分别表示%esp和%ebp,因为它们使用得很多,因此更易于阅读

我想知道的是,我是否把一切都做好了,或者我是否错过了什么。请随意复制/粘贴您想要的任何内容,并在您的答案中修改一些步骤

还请注意,我对这一点的理解非常重要,我周一有一个考试,我需要准备,我希望你能给我最好的答案。根据您的回答,我可能(或不是)有一些相关问题,我们将在评论部分注意

- INSTRUCTION: irmovl Stack, %esp
- INSTRUCTION: rrmovl %esp, %ebp
  1) Point %esp (SP) and %ebp (BP) to Stack

     |  ...  |
0x2E |-------|
     |       |
0x32 |-------| <--- SP & BP

- INSTRUCTION: irmovl $5, %eax
  1) Sets %eax = 5

- INSTRUCTION: call func
  1) Decrements SP by 4 (0x32 -> 0x2E)
  2) Saves return address (0x13) in memory location pointed by SP (0x2E)
  3) Jumps to "func" memory address (0x14)

     |  ...  |
0x2A |-------|
     | 0x13  |
0x2E |-------| <--- SP
     |       |
0x32 |-------| <--- BP

- INSTRUCTION: pushl %ebp
  1) Decrements SP by 4 (0x2E -> 0x2A)
  2) Saves BP value (0x32) in memory location pointed by SP (0x2A)

     |  ...  |
0x26 |-------|
     | 0x32  |
0x2A |-------| <--- SP
     | 0x13  |
0x2E |-------|
     |       |
0x32 |-------| <--- BP

- INSTRUCTION: rrmovl %esp, %ebp
  1) Sets BP = SP (0x32 -> 0x2A)

     |  ...  |
0x26 |-------|
     | 0x32  |
0x2A |-------| <--- SP & BP
     | 0x13  |
0x2E |-------|
     |       |
0x32 |-------|

- INSTRUCTION: pushl %eax
  1) Decrements SP by 4 (0x2A -> 0x26)
  2) Saves %eax value (5) in memory location pointed by SP (0x26)

     |  ...  |
0x22 |-------|
     |   5   |
0x26 |-------| <--- SP
     | 0x32  |
0x2A |-------| <--- BP
     | 0x13  |
0x2E |-------|
     |       |
0x32 |-------|

- INSTRUCTION: popl %eax
  1) Saves value (5) in memory location pointed by SP (0x26) in %eax
  2) Increments SP by 4 (0x26 -> 0x2A)

     |  ...  |
0x22 |-------|
     |   5   |
0x26 |-------|
     | 0x32  |
0x2A |-------| <--- SP & BP
     | 0x13  |
0x2E |-------|
     |       |
0x32 |-------|

- INSTRUCTION: popl %ebp
  1) Saves value (0x32) in memory location pointed by SP (0x2A) in %ebp
  2) Increments SP by 4 (0x2A -> 0x2E)

     |  ...  |
0x22 |-------|
     |   5   |
0x26 |-------|
     | 0x32  |
0x2A |-------|
     | 0x13  |
0x2E |-------| <--- SP
     |       |
0x32 |-------| <--- BP

- INSTRUCTION: ret
  1) Jumps to memory address (0x13) in memory location pointed by SP (0x2E)
  2) Increments SP by 4 (0x2E -> 0x32)
-指令:irmovl堆栈,%esp
-说明:rrmovl%esp,%ebp
1) 指向堆栈的点%esp(SP)和%ebp(BP)
|  ...  |
0x2E|-------|
|       |
0x32 |-----| 0x2E)
2) 将返回地址(0x13)保存在SP(0x2E)指向的内存位置中
3) 跳转到“func”内存地址(0x14)
|  ...  |
0x2A|-------|
|0x13|

据我所知,你一切都好

我可以提出的一个小观点是,将地址写在这些地址的值之上可能更直观。即:

0x2E |-------|
     | 0x13  |
0x32 |-------|
原因是覆盖该值的地址范围(
0x2E
0x2F
0x30
0x31
)指向下一个地址
0x32

当然,你可能希望在考试时使用老师期望的符号。

你答对了

您所做的是使用标准的调用者-被调用者约定执行函数调用,为被调用者创建一个框架。然后,在返回到调用者之前,对寄存器执行简单的推送和弹出操作。这是完全正确的,您的理解是正确的(详情请参阅)


一切看起来都很好。唯一的建议是不需要在堆栈上定义0x0000字。简单地定义堆栈标签就可以了。

实际上我不知道使用的“符号”:在那个例子中,我一直认为0x13将保存在[0x2E,0x2D,0x2C,0x2B]中,这对我来说更有意义。如果有人回答我“你做得很好”,这会让我想到另一个问题:为什么我们要在[0x32,0x31,0x30,0x2F]中留下一个空块?这解释了为什么你要像你那样演示它,但请注意堆栈只会/增长/向下(即新元素在最后一个元素的下方)这并不意味着元素本身也是向后存储的。x处的(4字节)元素始终存储在x、x+1、x+2、x+3处。对堆栈反转这一点也意味着您无法在“正常”代码中轻松使用堆栈中的地址。关于堆栈底部的空块:这是由于pushl v将v存储在%esp-4而不是%esp。当然,在许多情况下,您可以通过更改%esp的初始值来避免此情况。欢迎使用堆栈溢出!谢谢你的回复!请务必仔细阅读本手册。还请注意,每次链接到自己的网站/产品时,都需要发布免责声明。