我正在尝试将GNU as
用作与nasm
类似的通用汇编程序。我制作了这样的模板源:
.section .text
.globl _start
.intel_syntax noprefix
_start:
call 0xb77431c0 # the instruction I want to assemble
然后我像这样运行汇编命令:
as --32 -o test.o test.s
ld -m elf_i386 -Ttext 0xb77431d9 --oformat binary -o test.bin test.o
一切都适用于binutils 2.24。但似乎来自binutils 2.22的as
(Ubuntu Precise中的那个)将.text
部分与4字节边界对齐,因此不是预期的反汇编我得到错误的结果:
# expected and working in binutils 2.24
$ ndisasm -b 32 -o 0xb77431d9 test.bin
B77431D9 E8E2FFFFFF call dword 0xb77431c0
# actual in binutils 2.22
$ ndisasm -b 32 -o 0xb77431d9 test.bin
B77431D9 90 nop
B77431DA 90 nop
B77431DB 90 nop
B77431DC E8DFFFFFFF call dword 0xb77431c0
问题出在as
命令中(即不是ld
):readelf -S
为as
2.22的结果提供了以下内容:
$ readelf -S test.o | grep ' \.text'
[ 1] .text PROGBITS 00000000 000034 000005 00 AX 0 0 4
对于2.24我有
$ readelf -S test.o | grep ' \.text'
[ 1] .text PROGBITS 00000000 000034 000005 00 AX 0 0 1
所以问题确实是.text
部分的对齐。我尝试在源中的不同位置放置.align 0
和.align 1
,但它没有更改输出。
现在我的问题:如何在GNU汇编程序中明确指定ELF目标的节对齐?
答案 0 :(得分:2)
可能默认的链接描述文件 LD 会导致某种强制对齐。我使用原点创建一个基本的链接描述文件,并告诉它你想要哪些部分(指定对齐方式),以及将出现的部分顺序。
<强> linker.ld 强>
SECTIONS
{
. = 0xb77431d9;
.text . : SUBALIGN(0)
{
*(.text)
}
}
此脚本使用SUBALIGN指令覆盖输出对象中显示的.text
部分的对齐方式。从GNU Linker文档中可以看出这种效果:
3.6.8.4强制输入对齐
您可以使用SUBALIGN强制输出节中的输入节对齐。该 指定的值将覆盖输入节给出的任何对齐,无论是更大还是更小。
然后使用:
as --32 -o test.o test.s
ld -T linker.ld -m elf_i386 --oformat binary -o test.bin test.o
我得到的输出是:
ndisasm -b 32 -o 0xb77431d9 test.bin
B77431D9 E8E2FFFFFF call dword 0xb77431c0
如果目标文件中的某个部分未被链接描述文件中的部分处理,则仍会发出输入部分。所有未处理的输入节将按照链接器遇到的顺序在末尾输出。
答案 1 :(得分:1)
受answer by Michael Petch (v3)的启发,我找到了一种方法,使工作的链接描述文件能够使输出部分对齐:
SECTIONS
{
. = 0xb77431d9;
.text . : SUBALIGN(0)
{
*(.text)
}
}
现在我有以下结果:
$ as --32 -o test.o test.s
$ ld -m elf_i386 -T linker.ld --oformat binary -o test.bin test.o
$ ndisasm -b 32 -o 0xb77431d9 test.bin
B77431D9 E8E2FFFFFF call dword 0xb77431c0
这正是所需的输出,具有正确的调用目标,没有无关的对齐。