【问题标题】:Assembly - lea and arithmetic汇编 - lea 和算术
【发布时间】:2023-04-02 08:10:01
【问题描述】:

上下文:

  • 组装
  • 气体
  • x86_64

我的组件有点生锈了,我试图让它再次变得更好。

显示意图的 C 代码:

void ask_me(int * data){

    (*data)++;

}

这是故意愚蠢的,但符合上下文。

我的工作程序集:

_ask_me:
   addq $1, (%rdi)
   ret

问题:

我想使用lea 指令作为培训。 但我无法让它工作:

_ask_me:
    leaq 1(%rdi), %rdi

    ret

最差:

_ask_me:
    movq (%rdi), %rcx
    leaq 1(%rcx), %rdi

    ret

你能提醒我怎么做吗?

谢谢

【问题讨论】:

    标签: assembly x86-64 att pointer-arithmetic


    【解决方案1】:

    原始程序集从/向内存读取和写入。那就是:

    addq $1, (%rdi) 
    

    执行操作:

    *(rdi) += 1
    

    您无法使用LEA 实现相同的效果,因为LEA 将结果存储在寄存器中,而不是存储在内存中。所以你可以用它做rdi += 1(就像你第一次尝试一样),但不能用*(rdi) += 1

    【讨论】:

    • 对我不利 :) 我记不清它的用途了。
    【解决方案2】:

    inc 可以采用内存操作数,如果您要保存 insn 字节。通常,使用lea 进行数学运算的重点是非破坏性操作(导致与源代码不同的 reg),和/或组合移位、加法和加法立即数。

    lea 17(%rax, %rbx, 4), %rcx   # rcx = 17 + rax + rbx*4
    

    替换 4 条指令(包括一个 mov)。

    【讨论】:

    • 我对“不碰标志”这件事很感兴趣 :)
    • 对,不影响标志的数学运算是LEA 的另一个主要用途。通过 ALU 操作和jcc 之间的宏融合,通常最好将分支放在设置标志的操作旁边,但有时您还需要在分支之前完成另一个相关计算。
    猜你喜欢
    • 2012-02-27
    • 2016-06-07
    • 1970-01-01
    • 2020-09-22
    • 1970-01-01
    • 1970-01-01
    • 2021-08-26
    • 2017-10-23
    • 1970-01-01
    相关资源
    最近更新 更多