這段代碼:
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
then 時,它似乎沒有ADDS
說明(使用myTable
in .data
)
問題的背景關系是我正在嘗試手動優化一些 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
是唯一編譯的東西,那么它會落在偏移量 0 處.rodata
并且adds
指令消失,但這不是典型的真實場景。為了表示生成此程式集的典型真實場景,我在表格前添加了填充。
另請參閱此處它在 Godbolt 上復制
uj5u.com熱心網友回復:
這個:
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
這不是您的問題所包含的內容。一般來說,即使使用您的外部鏈接,我也會停下來放棄。請回傳并在問題中添加正確的示例,文本不是評論中的鏈接。
所以從你的問題和這個:
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"
它正在生成一個錨點,然后從錨點參考而不是直接參考標簽。
我懷疑這是為了優化 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 相對負載并將其轉換為 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
沒有使用錨點,所以直接使用了 myTable 的地址。
從我的角度來看,“為什么”是因為使用了錨點并且前面的填充導致 myTable 與錨點發生偏移。因此,負載加載錨地址,然后添加將您從錨點添加到表中。
為什么是錨?為讀者或其他人練習。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/486325.html
標籤:部件 海合会 手臂 拇指 arm-none-eabi-gcc
上一篇:如何將AVXymm暫存器中的所有值設定為相同(均為0/1/特定值)?
下一篇:訪問跨越MMU頁面邊界的變數