我正在尝试使用 gcc 生成嵌入式程序。gcc 来自 Mingw 工具集,与我在 Windows 下用于生成常规应用程序的 gcc 相同。我正在尝试生成一个位于 0x1000 的直接二进制文件,用于嵌入式 i386/32 位系统。它在 Bochs 下进行了测试。
我的链接器文件如下所示:
/* a list of files to link */
INPUT(test.o)
/* output format */
OUTPUT_FORMAT("pe-i386")
/* output filename */
/* OUTPUT_FILENAME("test.out") */
/* list of our memory sections */
MEMORY
{
ram : o = 0x1000, l = 256k
}
/* place sections */
SECTIONS
{
/* code and constants */
.text :
{
__text_start = .;
*(.text)
*(.strings)
__text_end = .;
} > ram
/* initialized data */
.data :
{
__data_start = .;
*(.data)
__data_end = .;
} > ram
/* uninitialized data */
.bss :
{
__bss_start = . ;
*(.bss)
*(COMMON)
__bss_end = . ;
} > ram
}
基本上,这意味着将所有内容连接到 ram 中 0x1000 的目标地址。
如果我选择除 PE 文件之外的任何目标,我会得到:
无法对非 PE 文件执行 PE 操作...
这里所说的其他消息是 ld 在 Windows 上的一个已知问题。所以我执行另一个步骤来使用 objcopy 创建一个二进制文件,它工作正常。
以下是输出部分:
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000038 ffc01000 ffc01000 00001000 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .rdata 00000010 ffc02000 ffc02000 00002000 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .eh_frame 00000038 ffc03000 ffc03000 00003000 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
所以这些部分在我喜欢的页框地址(4kb)上对齐。这是 .text 框架的反汇编:
test.pe: file format pe-i386
Disassembly of section .text:
ffc01000 <_crap>:
ffc01000: 55 push ebp
ffc01001: 89 e5 mov ebp,esp
ffc01003: 83 ec 10 sub esp,0x10
ffc01006: c7 45 f8 00 20 00 00 mov DWORD PTR [ebp-0x8],0x2000
ffc0100d: c7 45 fc 00 80 0b 00 mov DWORD PTR [ebp-0x4],0xb8000
ffc01014: eb 14 jmp ffc0102a <_crap+0x2a>
ffc01016: 8b 45 f8 mov eax,DWORD PTR [ebp-0x8]
ffc01019: 8a 00 mov al,BYTE PTR [eax]
ffc0101b: 66 98 cbw
ffc0101d: 8b 55 fc mov edx,DWORD PTR [ebp-0x4]
ffc01020: 66 89 02 mov WORD PTR [edx],ax
ffc01023: 83 45 fc 02 add DWORD PTR [ebp-0x4],0x2
ffc01027: ff 45 f8 inc DWORD PTR [ebp-0x8]
ffc0102a: 83 7d f8 00 cmp DWORD PTR [ebp-0x8],0x0
ffc0102e: 75 e6 jne ffc01016 <_crap+0x16>
ffc01030: b8 00 00 00 00 mov eax,0x0
ffc01035: c9 leave
ffc01036: c3 ret
ffc01037: 90 nop
所以我不知道它如何或为什么将代码定位在 0xffc01000,这不是我在链接器指令文件中指定的。
考虑到这是 PE 文件格式的一些产物,我尝试选择其他输出格式,例如 elf,但如果这样做,我会遇到“无法对非 PE 输出文件执行 PE 操作”错误。
问题是:
- 为什么它定位到 0xffc01000?即使在 Windows 程序的上下文中,这似乎也没有意义。
- 有没有办法正确定位程序?
- 我是否需要使用不绑定到 Windows 的 i386 gcc 构建?
谢谢,
斯科特·摩尔