Skip to content

可执行文件


从 FreeBASIC 源文件生成二进制可执行文件。

前言:

二进制文件只是一种二进制(即非文本)格式的文件:

  • 二进制格式意味着文件内容不应因平台特定原因而被转换(例如,将换行符从 \n 替换为 \r\n)。

  • 二进制文件不一定是可执行文件,例如编译为 '*.dll''*.a' 形式的库是二进制文件,但不是可执行文件。

  • 可执行文件不一定是二进制文件,例如文本形式的脚本可以在操作系统上设置为可执行文件。

可执行文件是可以被执行的文件(可以通过在命令行中写入文件名本身作为命令来运行)。

在 Windows 上,文件扩展名必须是固定可执行文件扩展名集合之一,包括 '*.exe'

在 Unix 系统上,文件的"可执行"标志也必须设置。

FreeBASIC 由 fbc(命令行编译器/链接器)、运行库和第三方库的 FreeBASIC 头文件组成。

为了生成可执行文件,fbc 使用 GNU binutils(汇编器、链接器)。当为 32 位 x86 以外的架构编译时,fbc 依赖 gcc 生成汇编代码。

FreeBASIC 提供 FreeBASIC 编译器/链接器程序(fbc 或 fbc.exe),以及它使用的工具和库:

  • fbc 是一个命令行程序,接受 FreeBASIC 源/包含文件('*.bas'/'*.bi')和目标/库文件('*.o'/'*.a'),然后将它们编译为可执行文件。

  • fbc 通常由集成开发环境(IDE)或文本编辑器调用,从终端或命令提示符调用,或通过构建系统(如 makefile)调用。

  • fbc 本身不是图形化代码编辑器或 IDE!

默认情况下,FreeBASIC 程序与各种系统和/或支持库链接,具体取决于平台。

这些库包括 FreeBASIC 用于 DOS 的 DJGPP 库和 FreeBASIC 用于 Windows 的 MinGW/GCC 库。

编译可执行文件(概述)

fbc 是一个编译器,将 fbc 源代码转换为可被操作系统加载和执行(运行)的文件。

fbc 并不独立完成这一过程。它使用一些中间文件和其他工具来完成这种转换。

可执行文件的"main"入口点

可执行文件需要一个起始点。

这个起始点(我们称之为"main"函数或"main"入口点)需要记录在可执行文件中,以便操作系统在加载可执行文件时知道从哪里开始执行程序。

默认情况下,"main"函数或起始点将是命令行中第一个 basic 源文件的第一行:

$ fbc program.bas module1.bas module2.bas

"program" 成为主模块,因为它排在第一位,fbc 将生成一个隐式的"main"函数,该函数在加载可执行文件时首先执行。

可以使用 '-m module' 选项覆盖此默认行为,以指定不是命令行中第一个源文件的主模块:

$ fbc -m program module1.bas module2.bas program.bas

"-m program" 选项告诉 fbc 将 "program.bas" 用作主模块,即使 "program.bas" 未排在第一位。

如果没有其他影响编译过程的选项,这个"main"函数由 fbc 隐式生成。

一个可执行文件只能有一个"main"函数。不可能有多个"main"函数。

可执行文件的编译过程

当 fbc 编译 basic 源代码时,它将源代码转换为另一种格式,该格式可被其他工具使用,最终创建可执行文件。

默认情况下,fbc 会自动使用这些其他工具:

vb
'     .-------------------------------------.
'     |              COMPILER               |
'     '------.----------------------.-------'
'            | GAS backend          | GCC backend
'            |                      |
'     .------V-----.    gcc     .---V----.
'     |  ASM CODE  |<-----------| C CODE |
'     | .s or .asm |  compiler  |   .c   |
'     '------.-----'            '--------'
'            | (G)AS assembler
'            |
'     .------V------.
'     | OBJECT CODE |
'     | .o or .obj  |-------------.
'     '------.------'             |
'            | (G)AR archiver     |
'            |                    |
'    .-------V--------.           |
'    | STATIC LIBRARY |           |
'    |   .a or .lib   |---------->|
'    '----------------'           | (G)LD linker
'                                 |
'                                 |----------------------------.
'                                 |                            |
'                      .----------V-----------.    .-----------V-----------.
'                      |        BINARY        |    |    SHARED LIBRARY     |
'                      | no extension or .exe |    | .so or .dll or .dylib |
'                      '----------------------'    '-----------------------'
'
'
'      Extensions are Unix convention vs Windows (ld does .lib too nowadays).
'      In the case of shared libs, the name for Mac deviates (.dylib).

要查看 fbc 使用的所有步骤,请在命令行中指定 '-v' 以查看这些步骤。

例如,在 win32 上:

vb
$ fbc a.bas -v
FreeBASIC Compiler - Version 1.08.0 (2021-01-24), built for win32 (32bit)
Copyright (C) 2004-2021 The FreeBASIC development team.
standalone
target:       win32, 486, 32bit
backend:      gas
compiling:    a.bas -o a.asm (main module)
assembling:   D:\fb.git\bin\win32\as.exe --32 --strip-local-absolute "a.asm" -o "a.o"
linking:      D:\fb.git\bin\win32\ld.exe -m i386pe -o "a.exe" -subsystem console
"D:\fb.git\lib\win32\fbextra.x" --stack 1048576,1048576 -s -L "D:\fb.git\lib\win32"
-L "." "D:\fb.git\lib\win32\crt2.o" "D:\fb.git\lib\win32\crtbegin.o" "D:\fb.git\lib\win32\fbrt0.o"
"a.o" "-(" -lfb -lgcc -lmsvcrt -lkernel32 -luser32 -lmingw32 -lmingwex -lmoldname -lgcc_eh "-)"
"D:\fb.git\lib\win32\crtend.o"

工具:

  • [ fbc ] 编译器将 _.bas 转换为 _.asm 或 *.c 文件

  • [ gcc ] 编译器将 _.c 文件转换为 _.asm 文件

  • [ as ] 汇编器将 _.asm 文件转换为 _.o 目标文件

  • [ ld ] 链接器将 *.o 文件(和其他文件)合并为可执行文件

  • emscripten 后端有其他工具

  • llvm 后端有其他工具

  • GNU 汇编器 32 位后端(-gen gas):

*.bas => [ fbc ] => *.asm compile (first stage) to assembly (-r or -rr, -R or -RR)
*.asm => [ as ] => *.o assemble to object file (-c, -C)
*.o => [ ld ] => *[.exe] link to executable
  • GNU 汇编器 64 位后端(-gen gas64):
*.bas => [ fbc ] => *.asm compile (first stage) to assembly (-r or -rr, -R or -RR)
*.asm => [ as ] => *.o assemble to object file (-c, -C)
*.o => [ ld ] => *[.exe] link to executable
  • GCC 编译器后端(-gen gcc):
*.bas => [ fbc ] => *.c compile (first stage) to C (-r, -R)
*.c => [ gcc ] => *.asm compile (second stage) to assembly (-rr, -RR)
*.asm => [ as ] => *.o assemble to object file (-c, -C)
*.o => [ ld ] => *[.exe] link to executable

控制编译/汇编/链接阶段的选项

有几个选项可以控制 fbc 对中间文件的处理,以及在何处提前停止该过程。

-r, -rr, -c:在链接阶段之前的某个时间停止编译/汇编过程

编译器选项 -r:编译到第一阶段,保留文件(.asm/.c),然后停止

编译器选项 -rr:编译到第二阶段,保留文件(*.asm),然后停止

编译器选项 -c:编译到汇编阶段,保留文件(*.o),然后停止

-R, -RR, -C:保留编译/汇编阶段的中间文件,然后继续到下一阶段

编译器选项 -R:不删除编译(第一阶段)中间文件(.asm/.c)

编译器选项 -RR:不删除编译(第二阶段)中间文件(*.asm)

编译器选项 -C:不删除汇编阶段中间文件(*.o)

-r:选项覆盖 -rr、-RR、-c、-C

-rr:覆盖 -c、-C

-r 和 -rr:如果只有一个编译阶段,则行为相同

-R 和 -RR:如果只有一个编译阶段,则行为相同

-r、-rr、-c:覆盖创建隐式"main"入口点的默认行为,默认情况下不创建"main"函数。

在使用 -r、-rr、-c 选项时要有"main"入口点,需要使用 '-m module' 选项来指示哪个模块应有"main"函数。

注意:

在 fbc 版本 1.09.0 之前,-gen gas64 为汇编器生成 .a64 文件扩展名(而非 .asm)。

不同模块的执行顺序

可执行程序需要一个"main"入口点(在主模块用户代码中)。

fbc 可能会也可能不会创建隐式 main 函数,取决于选项或构建可执行文件的方法。

模块的模块构造函数在 main 之前运行,模块的模块析构函数在 main 之后运行。

其他模块(非主模块)的模块级代码被放入隐式模块构造函数中,因此在主模块的模块级代码之前执行。

但最佳实践是模块级代码只在主模块中。

更一般地说,所有模块构造函数和模块析构函数在使用时都应该注意重大警告。因为对应的代码在用户代码之外运行,fbc 的错误检查和一些运行时功能很可能无法按预期工作。

启动框架的高级描述:

  • 在编译时,为所有模块构造函数和析构函数创建地址数组。

  • 在链接时,将数组存储在可执行文件中。

  • 在运行时,启动框架将:

  • 调用数组中的所有模块构造函数,

  • 调用主模块用户代码,

  • 在退出(或错误)时,调用所有模块析构函数(通常如此,但取决于程序如何失败)。

另请参阅

返回 目录

基于 FreeBASIC 官方文档翻译 如有侵权请联系我们删除
FreeBASIC 是开源项目,与微软公司无隶属关系