为什么编译器将 RDI 复制到另一个寄存器,然后在循环内将其复制回 RDI?
Why does the compiler copy RDI to another register, and then copy it back to RDI inside a loop?
我正在分析一段低效的代码,但其中的一些代码是如此混乱?
原代码:
#include <string.h>
void lowwer(char *str) {
for (int i = 0; i < strlen(str); ++i) {
str[i] -= ('A' - 'a');
}
}
汇编代码(由带有 -Og 选项的 clang 13 生成):
lowwer:
pushq %r14 # use saved-registers
pushq %rbx
pushq %rax
# guard do while
cmpb [=11=], (%rdi) # compare &str with null (check if strlen(str) == 0)
je .LBB0_3
# loop initialization
movq %rdi, %r14 # %r14 = str
xorl %ebx, %ebx # clear %rbx (for more compact encoding)
.LBB0_2: # =>This Inner Loop Header: Depth=1
addb , (%r14,%rbx) # subtract -32 from str[i] ('A' - 'a' = -32)
addq , %rbx # ++i
movq %r14, %rdi # seems meaningless here?
callq strlen@PLT
cmpq %rbx, %rax # check i < strlen(str)
ja .LBB0_2
.LBB0_3: # end
addq , %rsp # ???
popq %rbx # free registers
popq %r14
retq
- 指令
movq %r14, %rdi
在做什么?这似乎毫无意义,因为 %r14
持有字符串指针和 rdi
是相同的。
- 指令的意图是什么
addq , %rsp
。一脸懵逼
rdi
是一个 caller-saved 寄存器,因此被调用 strlen
破坏了。为了保留其内容,编译器发出代码以将其内容移动到 r14
,每次迭代将其复制一次作为 strlen
.
的参数
addq , %rsp
指令释放之前由 pushq %rax
分配的堆栈 space。分配此堆栈 space 以满足 amd64 SysV ABI 强加的堆栈对齐要求。
请参阅 amd64 SysV ABI 补充,了解完整的调用约定和 caller/callee 保存的寄存器列表。
我正在分析一段低效的代码,但其中的一些代码是如此混乱?
原代码:
#include <string.h>
void lowwer(char *str) {
for (int i = 0; i < strlen(str); ++i) {
str[i] -= ('A' - 'a');
}
}
汇编代码(由带有 -Og 选项的 clang 13 生成):
lowwer:
pushq %r14 # use saved-registers
pushq %rbx
pushq %rax
# guard do while
cmpb [=11=], (%rdi) # compare &str with null (check if strlen(str) == 0)
je .LBB0_3
# loop initialization
movq %rdi, %r14 # %r14 = str
xorl %ebx, %ebx # clear %rbx (for more compact encoding)
.LBB0_2: # =>This Inner Loop Header: Depth=1
addb , (%r14,%rbx) # subtract -32 from str[i] ('A' - 'a' = -32)
addq , %rbx # ++i
movq %r14, %rdi # seems meaningless here?
callq strlen@PLT
cmpq %rbx, %rax # check i < strlen(str)
ja .LBB0_2
.LBB0_3: # end
addq , %rsp # ???
popq %rbx # free registers
popq %r14
retq
- 指令
movq %r14, %rdi
在做什么?这似乎毫无意义,因为%r14
持有字符串指针和rdi
是相同的。 - 指令的意图是什么
addq , %rsp
。一脸懵逼
rdi
是一个 caller-saved 寄存器,因此被调用 strlen
破坏了。为了保留其内容,编译器发出代码以将其内容移动到 r14
,每次迭代将其复制一次作为 strlen
.
addq , %rsp
指令释放之前由 pushq %rax
分配的堆栈 space。分配此堆栈 space 以满足 amd64 SysV ABI 强加的堆栈对齐要求。
请参阅 amd64 SysV ABI 补充,了解完整的调用约定和 caller/callee 保存的寄存器列表。