- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
这段代码:
const char padding[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
const char myTable[] = { 1, 2, 3, 4 };
int keepPadding() {
return (int)(&padding);
}
int foo() {
return (int)(&myTable); // <-- this is the part I'm looking at
}
为 thumb 指令集编译为以下程序集(为清楚起见缩写)。特别注意 adds
作为 foo
的第二条指令:
...
foo:
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
@ link register save eliminated.
ldr r0, .L5
@ sp needed
adds r0, r0, #10
bx lr
.L6:
.align 2
.L5:
.word .LANCHOR0
.size foo, .-foo
.align 1
.global bar
.syntax unified
.code 16
.thumb_func
.type bar, %function
...
myTable:
.ascii "\001\002\003\004"
看起来它正在将指针 (ldr
) 加载到 .rodata 的顶部,然后以编程方式偏移到 myTable
的位置(adds
).但为什么不直接加载表本身的地址呢?
注意:当我删除 const
时,它似乎没有 ADDS
指令(在 .data 中使用
)myTable
问题的上下文是我正在尝试手动优化一些 C 固件,并注意到这个 adds
指令似乎是多余的,所以我想知道是否有重组的方法我的代码摆脱它。
注意:这都是针对 ARM thumb 指令集编译如下(使用 arm-none-eabi-gcc 版本 11.2.1):
arm-none-eabi-gcc -Os -c -mcpu=cortex-m0 -mthumb temp.c -S
另请注意:此处的示例代码旨在表示较大代码库的片段。如果 myTable
是唯一编译的东西,那么它会落在 .rodata
中的偏移量 0 处,并且 adds
指令会消失,但这不是典型情况一个真实的场景。为了表示生成此程序集的典型真实场景,我在表格前添加了填充。
最佳答案
问题最初只包含这个:
const char myTable[] = { 1, 2, 3, 4 };
int foo() {
return (int)(&myTable);
}
arm-none-eabi-gcc -Os -c -mthumb so.c -o so.o
arm-none-eabi-objdump -D so.o
但它没有产生添加:
Disassembly of section .text:
00000000 <foo>:
0: 4800 ldr r0, [pc, #0] ; (4 <foo+0x4>)
2: 4770 bx lr
4: 00000000 andeq r0, r0, r0
Disassembly of section .rodata:
00000000 <myTable>:
0: 04030201 streq r0, [r3], #-513 ; 0xfffffdff
问题已被编辑以显示可重复的示例,因此此答案已被编辑。但我将只留下答案以寻求相同的解决方案。可能有趣的是,到达 anchor 需要一些组件以避免问题被优化。
所以从你的问题和这个:
const char padding[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
const char myTable[] = { 1, 2, 3, 4 };
int foo() {
return (int)(&myTable);
}
很明显为什么 myTable 的偏移量为 10。
但是填充被优化了,所以你最终还是会得到相同的结果。
所以:
const char padding[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
const char myTable[] = { 1, 2, 3, 4 };
int keepPadding() {
return (int)(&padding);
}
int foo() {
return (int)(&myTable);
}
该函数的名称暗示您已经知道所有这些,并且知道如何制作一个最小示例等。
arm-none-eabi-gcc -Os -c -mthumb so.c -S
foo:
@ Function supports interworking.
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
@ link register save eliminated.
ldr r0, .L5
@ sp needed
adds r0, r0, #10
bx lr
.L6:
.align 2
.L5:
.word .LANCHOR0
.size foo, .-foo
.global myTable
.global padding
.section .rodata
.set .LANCHOR0,. + 0
.type padding, %object
.size padding, 10
padding:
.space 10
.type myTable, %object
.size myTable, 4
myTable:
.ascii "\001\002\003\004"
.ident "GCC: (GNU) 11.2.0"
它正在生成一个 anchor ,然后从 anchor 引用而不是直接引用标签。
我怀疑这是为了优化 ldr。让我们试试:
arm-none-eabi-gcc -Os -c -mthumb -mcpu=cortex-m4 so.c -S
foo:
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
@ link register save eliminated.
ldr r0, .L5
bx lr
.L6:
.align 2
.L5:
.word .LANCHOR0+10
.size foo, .-foo
00000008 <foo>:
8: 4800 ldr r0, [pc, #0] ; (c <foo+0x4>)
a: 4770 bx lr
c: 0000000a .word 0x0000000a
是的,所以修复了它,但是链接它呢
Disassembly of section .rodata:
00000000 <padding>:
...
0000000a <myTable>:
a: 04030201 streq r0, [r3], #-513 ; 0xfffffdff
Disassembly of section .text:
00000010 <keepPadding>:
10: 4800 ldr r0, [pc, #0] ; (14 <keepPadding+0x4>)
12: 4770 bx lr
14: 00000000 andeq r0, r0, r0
00000018 <foo>:
18: 4801 ldr r0, [pc, #4] ; (20 <foo+0x8>)
1a: 300a adds r0, #10
1c: 4770 bx lr
1e: 46c0 nop ; (mov r8, r8)
20: 00000000 andeq r0, r0, r0
不,希望链接器能够替换 pc-relative 负载并将其转换为 mov r0,#0...节省负载,这(可能)是对非 cortex-m 系统的优化(甚至 cortex-m)。
注意:这也行
arm-none-eabi-gcc -Os -c -mthumb -fno-section-anchors so.c -o so.o
00000008 <foo>:
8: 4800 ldr r0, [pc, #0] ; (c <foo+0x4>)
a: 4770 bx lr
c: 00000000 andeq r0, r0, r0
foo:
@ Function supports interworking.
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
@ link register save eliminated.
ldr r0, .L5
@ sp needed
bx lr
.L6:
.align 2
.L5:
.word myTable
.size foo, .-foo
.global myTable
.section .rodata
.type myTable, %object
.size myTable, 4
myTable:
.ascii "\001\002\003\004"
.global padding
.type padding, %object
.size padding, 10
没有使用 anchor ,直接使用myTable的地址。
从我的角度来看,“为什么”是因为使用了 anchor ,前面的填充导致 myTable 与 anchor 有偏移。因此加载加载 anchor 地址,然后将您从 anchor 地址添加到表中。
为什么是主播?为读者或其他人练习。
关于assembly - 为什么 GCC 在 LDR 之后产生额外的 ADDS 指令以在 ARM thumb 指令集上加载 .rodata 指针?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72483177/
我最近不得不调试一个 MachO 二进制文件,我遇到了以下指令:- ldr.w r4, [r1, r0, lsl #2] 我明白 ldr r4, [r1, r0, lsl #2]将 r0 向左移动两次
在ARM汇编中做ldr r0,[r0]合法吗? 最佳答案 如有疑问,请始终参阅 ARM 体系结构引用手册,该手册可在 arm.com 上找到。它说: The destination register.
最近受朋友的委托,想自己实现Matlab里的一个HDR转LDR的函数,函数名是tonemapfarbman,乘着十一假期,稍微浏览下这个函数,并做了一点C++的实现和优化。 为了看到这个函数
我知道如何在 ARM 中使用 LDR 指令加载立即数。 例如: LDR R0,=0x0804c088该指令将值 (0x0804c088) 加载到寄存器 r0。当我尝试使用 gdb 访问存储在 x/x
我正在使用带有 microchip v8.63 和 c 编译器的 picdem 18F4550。我使用的组件是:- 3 个 LED(红、绿、蓝);- LDR(327700 NORPS-12 法内尔)。
我正在调试一些 C++ 代码(ARM 平台上的 WinCE 6),我发现有些行为很奇怪: 4277220C mov r3, #0x93, 30 42772210
我正在尝试使用 devkitpro 创建匹配的 GBA 反汇编,但我遇到了 THUMB 指令 LDR R1, =0x3FF 的问题。 我想让它把 0x3FF 放在文字池中并生成一个 PC 相对地址,这
这段代码在 gcc 上编译得很好,但是当使用 llvm (llvm-gcc) 时,它说 "constant expression expected"在线与ldr 问题在于语法:如何指定数组所在的位置?
我正在尝试调试我在我的应用程序中遇到的崩溃。堆栈跟踪指向具有以下格式的 LDR 指令(感谢反汇编程序): LDR R3, [R0,#4] 我的问题是关于源组件。第二个参数中的#4 是什么意思?我假设它
在谷歌上搜索了一段时间,但我找不到任何与此相关的文档。我一直在尝试学习 ARM,并且一直在查看我编写的一个简单的calculator.c 程序的编译后的 ARM 汇编代码,以查看我是否能理解发生了什么
我正在阅读 Cortex M4 TRM 以了解指令执行周期。但是,那里有一些令人困惑的描述 在 Table of Processor Instuctions , STR需要 2 个周期 . 稍后在 L
我有一个简单的 C 程序: int main(){ unsigned int counter = 0; ++counter; ++counter; ++count
假设我已经有一个名为 int* binToArrayInOrder(TreeRoot* tr) 的函数,它创建一个排序的树值数组(因为它是有序的)。 有没有办法从给定的有序数组中构造树,没有其他信息,
浏览 Windows Hotfixes and Updates 上的信息时网站,我了解到 Windows 维护两个不同的分支来提供更新和修补程序,并且根据描述, GDR -> 所有 Windows 更
所以我知道 ldr/str on arm 的问题数不胜数。也许这是另一个转折(不太可能),或者我只是错过了一些东西(更有可能。) 所以这是裸机,我想在内存中加载/存储一些变量。因为我坚持我想给它一个名
我在尝试将最新的 ffmpeg 迁移到 iOS 平台时遇到了一些编译错误。 这些错误来自 GNU 汇编器(gas),它似乎无法处理最新 ffmpeg 中的一些 asm 指令。 例如: libavcod
我在任何地方都找不到这个问题的直接答案。 ARM的寄存器是32位的,我知道LDRB将一个字节大小的值加载到寄存器中,并将剩余的3个字节清零,即使你给它提供一个大于一个字节的值,它也只会取第一个字节的值
我将 picdem 18F4550 与微芯片 v8.63 和 C18 编译器一起使用。 我将启用 PortA 设置为输入,我将在端口 RA0 上连接一个 LDR。如下(我认为) TRISAbits.T
我今天第一次遇到 LDTR ARMv8 指令。 我在 ARMv8 DB 上阅读了它的描述手册部分C3.2.5“非特权加载/存储”,据我了解,它基本上允许EL1在EL0限制下进行内存访问。 此功能的应用
我正在浏览本教程:http://www.cl.cam.ac.uk/freshers/raspberrypi/tutorials/os/ok01.html 第一条组装线是: ldr r0,=0x2020
我是一名优秀的程序员,十分优秀!