【问题标题】:mov instructions & registers - confusion !mov 指令和寄存器 - 混乱!
【发布时间】:2011-05-04 20:40:25
【问题描述】:

我正在阅读“计算机系统:程序员视角”,第 3 章解释了mov 指令,而书中给出的解释让我感到困惑。

给出一个函数(第142页第1版)

int exchange( int *xp, int y)
{
    int x = *xp;
    *xp = y;
    return x;
} 

函数体汇编代码

movl 8(%ebp), %eax  //Get xp  
movl 12(%ebp), %edx //Get y  
movl (%eax), %ecx   //Get x at *xp  
movl %edx, (%eax)   //Store y at *xp  
movl %ecx, %eax     //Set x as return value

让我感到困惑的是,要存储什么以及存储在哪里
我是这样理解的:

movl 8(%ebp), %eax  //Get xp  

CPU 将 +8 字节向上移动堆栈(从帧指针 %ebp),获取存储在该位置的值,并将该值存储在寄存器 %eax(强调 - 存储值,而不是地址)

我是对的? 谢谢!

【问题讨论】:

    标签: assembly


    【解决方案1】:

    是的,这是使用 AT&T 语法,格式为:

    instruction     source, dest
    

    英特尔程序集是the opposite order

    8(%ebp) 从帧指针向上移动 8 个字节也是正确的。具体来说,它移动 8 个字节的原因是因为参数以相反的顺序被压入堆栈(在查看典型的函数调用时,从“右”到“左”)。因此,y 首先被推送,然后是 xp,最后是调用函数的返回地址(这就是为什么你移动 8 个字节而不是 4 个字节的原因)。

    【讨论】:

    • 我还是不明白。如果堆栈看起来像这样:(ret_addr) -> *xp -> y,堆栈指针指向堆栈顶部 (ret_addr),你不应该通过 movl 4(%ebp), %eax 得到 *xp 吗?
    【解决方案2】:

    是的,听起来你做对了。恕我直言,AT&T 8(%ebp) 语法不如英特尔 [ebp+8] 直观,后者更清晰。括号表示您使用的是寄存器中地址处的值,而数字是您实际想要的地址的偏移量。

    【讨论】:

    • 因此换句话说,因为%ebp 存储指针,我们在其名称周围使用括号,以指定我们获取存储的值距%ebp +8 个字节。在这种情况下,8(%ebp) 包含指针 *xp。稍后,在movl (%eax), %ecx 行中,我们取消引用xp 的方式与我们在第一行汇编代码中所做的相同
    • 现在,一切都理顺了。括号是混乱的根源!谢谢!
    【解决方案3】:

    您需要了解什么是堆栈帧。了解 pushpop 指令的确切作用。 在该代码之前有一个

       push y_val
       push xp_ptr
       call exchange
    .cont    
    ...
    .exchange
       push ebp
       mov ebp, esp
    // .. rest of code
    // stack frame: 
       old_ebp_val  ; [ebp] points here
       .cont        ; [ebp + 4]
       xp_ptr       ; [ebp + 8]
       y_val
    

    【讨论】:

    • 我的问题不在于堆栈,甚至认为涉及堆栈。它是关于存储在寄存器和内存中的值
    • @user 尝试实现 RTTI。始终跟踪值的类型。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-01
    • 2019-09-12
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 2019-01-02
    • 2018-09-13
    相关资源
    最近更新 更多