【发布时间】:2020-01-29 11:35:02
【问题描述】:
当我使用 gcc -S 从 C 代码创建 ARM 汇编代码时,我得到了一个我不知道的 LDR 指令变体。具体来说,我得到“ldr r3,.L5”指令,其中“.L5”是编译器定义的标签。我不清楚为什么我没有得到伪指令“ldr r3, =.L5”,这应该是在寄存器中加载任意数字的唯一方法。
更多细节:
- 我从这个C代码开始(文件名:sum_squares_C.c):
int sum;
int main(){
sum = 0;
for(int i=1; i<=n; i++){
sum = sum + i*i;
}
}
-
然后在 Raspeberry PI 上,我使用“gcc -O0 -S sum_squares_C.c”进行编译,编译器版本为 gcc (Raspbian 8.3.0-6+rpi1) 8.3.0。
李> 输出是这个ARM代码(指令“ldr r3, .L5”在标签“main”之后的第7行):
.arch armv6
.eabi_attribute 28, 1
.eabi_attribute 20, 1
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 26, 2
.eabi_attribute 30, 6
.eabi_attribute 34, 1
.eabi_attribute 18, 4
.file "sum_squares_C.c"
.text
.global n
.data
.align 2
.type n, %object
.size n, 4
n:
.word 1
.comm sum,4,4
.text
.align 2
.global main
.arch armv6
.syntax unified
.arm
.fpu vfp
.type main, %function
main:
@ args = 0, pretend = 0, frame = 8
@ frame_needed = 1, uses_anonymous_args = 0
@ link register save eliminated.
str fp, [sp, #-4]!
add fp, sp, #0
sub sp, sp, #12
ldr r3, .L5
mov r2, #0
str r2, [r3]
mov r3, #1
str r3, [fp, #-8]
b .L2
.L3:
ldr r3, [fp, #-8]
ldr r2, [fp, #-8]
mul r2, r2, r3
ldr r3, .L5
ldr r3, [r3]
add r3, r2, r3
ldr r2, .L5
str r3, [r2]
ldr r3, [fp, #-8]
add r3, r3, #1
str r3, [fp, #-8]
.L2:
ldr r3, .L5+4
ldr r3, [r3]
ldr r2, [fp, #-8]
cmp r2, r3
ble .L3
mov r3, #0
mov r0, r3
add sp, fp, #0
@ sp needed
ldr fp, [sp], #4
bx lr
.L6:
.align 2
.L5:
.word sum
.word n
.size main, .-main
.ident "GCC: (Raspbian 8.3.0-6+rpi1) 8.3.0"
.section .note.GNU-stack,"",%progbits
在我看来,gcc 使用指令“ldr r3, .L5”等同于“ldr r3, =.L5”。这是正确的吗?在哪里可以找到该指令语法的定义?是否可以强制 gcc 不使用该指令,而是使用“ldr r3, =.L5”(出于教学原因,我需要这个)?
谢谢! 弗朗切斯科
【问题讨论】:
-
而哪个值存储在
.L5? -
好像是变量sum的地址。
-
不等价的一个 ldr r3,.L5 将地址 .L5 的值(标签即地址)放入 r3,另一个 ldr r3,=.L5 将 .L5 的地址放入r3。完全不同。对于前者,汇编器将用 pc 相对负载替换它。对于后者,汇编器将尝试在附近的池中创建一个值并创建一个 pc 相对负载,然后链接器将在知道后将地址放入 .L5 中
-
最好/最好先检查拆卸,然后如果需要返回到组装。或者至少将组装和拆卸相互比较,大多数这类问题都会自己回答。
-
你没有定义n是吗?如果你优化它,那么它就是死代码,更难阅读未优化的代码。如果您要返回总和但在函数内部声明 n 并优化 gcc 应该简单地计算结果并返回而不是生成循环,如果您要将 n 作为参数传递给函数然后返回它应该优化的总和变成更简单的非循环形式,但会产生一些代码。