首页 文章

x86 mov / add指令和内存寻址

提问于
浏览
3

我正在学习类中的x86程序集,我很遗憾你如何区分寄存器操作数和内存引用的作用 . 我有几个想要澄清的混乱 .

以下代码是我的教科书所说的分别是推送和弹出的漫长道路:

subl $4, %esp
movl %ebp, (%esp)

movl (%esp), %eax
addl $4, %esp

那么在subl指令中,我们是否总能指望%esp保存地址值?

两个movl函数之间有什么区别?可以将第一个写成

movl (%ebp), %esp

?对于第二个movl,是移动%esp的地址还是移动%esp指向的值?

作为后续行动,我们为什么不能将源和目标作为内存引用呢?

movw (%eax), 4(%esp)

最后,对于以下代码:

movb (%esp, %edx, 4), %dh

如果源是超过1个字节(%dh的大小),那么会发生什么?它只是截断了这个值吗?

对不起,这是一大堆问题,但任何帮助将不胜感激 .

2 回答

  • 2

    以下代码是我的教科书所说的分别是推送和弹出的长路:subl $ 4,%esp
    movl%ebp,(%esp)

    movl(%esp),%eax
    addl $ 4,%esp
    那么在subl指令中,我们是否总能指望%esp保存地址值?

    是 . ESP 寄存器保存推入堆栈的最后一个值的内存地址 .

    两个movl函数之间有什么区别?第一个可以写成movl(%ebp),%esp
    ?对于第二个movl,是移动%esp的地址还是移动%esp指向的值?

    MOV 语句中的 MOV 指令需要两个操作数:源和目标 . MOV 将数据(在本例中为32位,由 L 后缀表示)从左侧写入的第一个操作数复制到右侧写入的第二个操作数 . 如果其中一个括在括号中,则表示操作数是内存操作数,括号中的值是其内存地址,而不是实际值)

    因此, movl %ebp,(%esp) 表示:将寄存器 EBP 的值复制到内存中,寄存器寄存器 ESP 的值指向的地址 .

    你对 movl (%ebp),%esp 的意思是:将从 EBP 的值指向的存储器地址开始的32位数据复制到 ESP 寄存器中 .

    所以你正在改变运动的方向 .

    作为后续行动,为什么我们不能让源和目标成为这样的内存引用? movw(%eax),4(%esp)

    简短回答:因为英特尔使用的编码不允许这样做 . 答案很长:英特尔设计ISA的方式,可用资源来计算好旧8086中的两个有效地址等

    最后,对于以下代码:movb(%esp,%edx,4),%dh
    如果源是超过1个字节(%dh的大小),那么会发生什么?它只是截断了这个值吗?

    源与目标的大小相同 . 这是由 B 后缀和目标是8位寄存器的事实强加的 . 括号中的值则是单个存储器字节的地址 . 顺便说一下,这个地址是 ESP+EDX*4

  • 1

    那么在subl指令中,我们是否总能指望%esp保存地址值?

    根据定义是,因为下一条指令将其用作地址 . 无论垃圾是什么,现在都有一个地址 . 如果它是像0xDEADBEEF那样的废话..那么现在是一个地址 . 它可能是也可能不是有效地址(希望有效,无效堆栈是一件坏事),但这是另一回事 .

    两个movl函数之间有什么区别?

    "push"中使用的那个写入内存,"pop"中使用的那个读取 . 右侧的括号表示它是一个读数 . 所以你可以切换它们吗?显然不是,它会做一些不同的事情 . movl (%ebp), %esp 将从内存中读取内容然后更改堆栈的位置 .

    作为后续行动,为什么我们不能让源和目标成为这样的内存引用?

    因为你可以't, there is no such instruction. It wouldn' t适合正常的operand encoding . 我想这样的指令可能已存在,但它并没有使用它 .

    movb(%esp,%edx,4),%dh如果源超过1个字节(%dh的大小),那么会发生什么?

    根据定义,指令不会读取1个字节 .

相关问题