【问题标题】:Assembly multiply simplification?装配乘法简化?
【发布时间】:2017-06-01 02:56:58
【问题描述】:

Say Hello to Assembly - Part 3 的帖子中,作者想要在堆栈上打印一个字符串(转换后的整数)。 r12 包含字符串中的位数。

;;; Find length of string
mov rax, 1                    
mul r12
mov r12, 8                    ; 8 times num digits to get len in bytes
mul r12
mov rdx, rax                  ; length of string int rdx


;;;; print sum
mov rax, SYS_WRITE
mov rdi, STD_OUT
mov rsi, rsp
syscall

我的问题是我们可以简化为:

;;; Find length of string
mov rax, 8                    ; 8 times num digits
mul r12
mov rdx, rax                  ; length of string int rdx

或者我缺少作者的方法的一些微妙之处?

在我看来,他将 1 放入 rax 乘以 r12,然后将 8 放入 r12,然后再次相乘。我的方法看起来更干净,而且似乎有效。

【问题讨论】:

  • 请注意,rdx 必须是 sys_WRITE 调用的 rsi 中字符串的长度。

标签: assembly nasm x86-64 elf


【解决方案1】:

我认为你的代码是等价的,但为什么不只是

imul rdx,r12,8

或者替代(虽然可能是一个更胖的操作码)

lea rdx,[r12*8]

【讨论】:

  • 两条指令都是四个字节长。
  • 我看到 imul rdx,r12,8 是四个字节,但 lea rdx,[r12*8] 似乎是 8 个字节,因为没有基址寄存器。如果它是 lea rdx,[rax+r12*8] 之类的东西,那么 lea 将是 4 个字节。
  • 哦,是的,我完全忘记了。而imul 在现代平台上也相当快,可能与带有 sib 操作数的 lea 一样快。
  • LEA 仍然比IMUL 快,即使在现代处理器上也是如此,但这是一个非常接近的电话。在这些情况下,您将看到生成 IMUL 的唯一编译器是 Clang,我不知道它为什么会这样做。如果你能加入一个基址寄存器,LEA 是一个决定性的胜利。 SHL+MOV 也值得研究,尤其是在现代处理器(Haswell 及更高版本)上,MOVs 通过重命名被前端省略。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-11
  • 1970-01-01
  • 2022-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多