2

我正在尝试使用 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 操作”错误。

问题是:

  1. 为什么它定位到 0xffc01000?即使在 Windows 程序的上下文中,这似乎也没有意义。
  2. 有没有办法正确定位程序?
  3. 我是否需要使用不绑定到 Windows 的 i386 gcc 构建?

谢谢,

斯科特·摩尔

4

0 回答 0