gpt4 book ai didi

c - 为什么编译器将 RDI 复制到另一个寄存器,然后在循环内将其复制回 RDI?

转载 作者:行者123 更新时间:2023-12-01 23:05:02 26 4
gpt4 key购买 nike

我正在分析一段低效的代码,但其中有些代码是如此困惑?

原代码:

#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 $0, (%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 $32, (%r14,%rbx) # subtract -32 from str[i] ('A' - 'a' = -32)
addq $1, %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 $8, %rsp # ???
popq %rbx # free registers
popq %r14
retq
  1. movq %r14, %rdi 指令在做什么?这似乎毫无意义,因为 %r14 持有字符串指针和 rdi 是相同的。
  2. 指令addq $8, %rsp 的意图是什么。看起来毫 headless 绪。

最佳答案

rdi 是调用者保存的寄存器,因此被 strlen 的调用破坏了。为了保留其内容,编译器发出代码以将其内容移动到 r14,每次迭代将其复制一次作为 strlen 的参数。

addq $8, %rsp 指令释放先前由 pushq %rax 分配的堆栈空间。分配此堆栈空间是为了满足 amd64 SysV ABI 强加的堆栈对齐要求。

请参阅 amd64 SysV ABI 补充,了解完整的调用约定和调用者/被调用者保存的寄存器列表。

关于c - 为什么编译器将 RDI 复制到另一个寄存器,然后在循环内将其复制回 RDI?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71083308/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com