我正在玩arm-none-eabi-as
,试图理解它是如何对齐部分的。我有以下来源:
; source.s
.text
.byte 0xff
.byte 0xff
.byte 0xff
我正在检查生成的对象文件:
$ arm-none-eabi-as -mthumb -o source.o source.s
$ arm-none-eabi-readelf -S source.o
There are 8 section headers, starting at offset 0xec:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 00000000 000034 000003 00 AX 0 0 1
[ 2] .data PROGBITS 00000000 000037 000000 00 WA 0 0 1
[ 3] .bss NOBITS 00000000 000037 000000 00 WA 0 0 1
[ 4] .ARM.attributes ARM_ATTRIBUTES 00000000 000037 000014 00 0 0 1
[ 5] .symtab SYMTAB 00000000 00004c 000060 10 6 6 4
[ 6] .strtab STRTAB 00000000 0000ac 000004 00 0 0 1
[ 7] .shstrtab STRTAB 00000000 0000b0 00003c 00 0 0 1
.text
部分是字节对齐的,包含3个字节。
现在,我向source.s
添加一条指令:
; source.s
.text
.byte 0xff
nop
.byte 0xff
.byte 0xff
查看对象文件,现在突然.text
部分是半字对齐的:
There are 8 section headers, starting at offset 0x114:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 00000000 000034 000006 00 AX 0 0 2
[ 2] .data PROGBITS 00000000 00003a 000000 00 WA 0 0 1
[ 3] .bss NOBITS 00000000 00003a 000000 00 WA 0 0 1
[ 4] .ARM.attributes ARM_ATTRIBUTES 00000000 00003a 000014 00 0 0 1
[ 5] .symtab SYMTAB 00000000 000050 000080 10 6 8 4
[ 6] .strtab STRTAB 00000000 0000d0 000007 00 0 0 1
[ 7] .shstrtab STRTAB 00000000 0000d7 00003c 00 0 0 1
在第二种情况下,是什么导致汇编程序决定填充该节?我感到困惑,因为:
1.如果该部分是.data
,那么汇编程序无论如何都不会填充它,这是有意义的,但是
1.即使区段是.text
,汇编程序也不会填充它,除非它看到一条指令(我可以有尽可能多的数据指令,区段不会在没有指令的情况下被填充),最后
nop
指令肯定没有对齐,汇编器对此没有问题,但它仍然决定关心段对齐。
装配工是如何决定在这里进行填充的?即使我有指令,我是否可以强制汇编程序不填充.text
部分?
2条答案
按热度按时间d5vmydt91#
以下是我与binutils人员讨论后了解到的内容:
汇编程序并不关心是否在任何特定部分中编码未对齐的指令。但是,它关心两个方面:
1.任何节的总体节对齐与该节内最对齐的元素匹配,以及
1.用eXecute标志标记的每个部分都被填充以匹配其对齐。
汇编器执行(2),因为稍后这些部分可能需要合并,合并之后所有元素必须保持对齐(因此它填充部分以确保该属性)。
原帖中显示的两种情况的区别在于:
.byte
,对齐方式为1
,因此整个部分的对齐方式为1
,而nop
thumb指令成为最对齐的元素,并且该部分现在是2
对齐的。由于示例中的节是
.text
节,并且设置了X
标志,汇编器将在第二种情况下填充节以匹配其对齐方式。尽管如此,nop
指令仍然在节内未对齐。83qze16e2#
装配工是如何决定在这里进行填充的?
thumb(2)模式下的指令必须以16位偏移量开始。如果使用
.arm
,您将看到填充到32位。它是伊萨的一部分。你的NOP
指令将不起作用(如果你以某种方式直接跳转到NOP
)。当然,流的其余部分都是垃圾。对于文本部分中的NOP
是代码的正常情况,您希望它对齐。指针中的低位通常用于表示“Thumb”或“ARM”模式例程。即使我有一个指令,我可以强制汇编程序不填充.text部分吗?
将NOP作为数据将是一个奇怪的情况;如果是,如果不需要填充,请自己定义。
你正在以一种完全错误的方式使用工具。如果需要数据,请使用“.rodata”部分。汇编程序的工作是将人类助记符转换为二进制。对于文本部分中的
NOP
的正常情况,您希望它是可执行的。如果你的用例不支持这些工具,那么会有几十个其他的用例被破坏。比如说