如何使用 GNU 汇编器 (as) 将汇编文件编译为原始二进制(如 DOS .com)格式? [复制]

2024-04-13

我想在 Windows 中编译这个源代码(这只是一个例子):

start:
NOP
NOP

当我使用 NASM 或 FASM 编译它时,输出文件长度为 2 个字节。但是当我用 GNU 汇编器(as)编译它时,输出文件长度是 292 字节!

如何使用 GNU 汇编器 (as) 将汇编文件编译为原始二进制(如 DOS .com)格式?


我为什么这样做?

我想编写自己的简单操作系统,我用 C 编写代码(不使用任何 C 标准库,甚至 stdio.h 或 math.h)并将其转换为汇编:

gcc -S my_os.c -o my_os.asm -masm=intel

然后,我将汇编文件编译为原始二进制文件:

as my_os.asm

然后我重命名a.out(汇编器的输出)到my_os.flp最后用 VMWare 启动我的操作系统:)


ld --oformat binary

对于快速和肮脏的测试,你可以这样做:

as -o a.o a.S
ld --oformat binary -o a.out a.o
hd a.out

Gives:

00000000  90 90                                             |..|
00000002

不幸的是,这给出了一个警告:

ld: warning: cannot find entry symbol _start; defaulting to 0000000000400000

这没有多大意义binary。它可以通过以下方式静音:

.section .text
.globl start
start:
nop
nop

and:

ld -e start --oformat binary -o a.out a.o

或者简单地使用:

ld -e 0 --oformat binary -o a.out a.o

这告诉ld入口点不是_start但地址处的代码0.

遗憾的是,两者都没有as nor ld可以从 stdin / stdout 获取输入/输出,因此无需管道。

正确的引导扇区

如果您要做更严肃的事情,最好的方法是生成一个干净的最小链接器脚本。linker.ld:

SECTIONS
{
    . = 0x7c00;
    .text :
    {
        *(.*)
        . = 0x1FE;
        SHORT(0xAA55)
    }
}

在这里,我们还将魔术字节与链接描述文件一起放置。

链接描述文件对于控制重定位后的输出地址至关重要。了解有关搬迁的更多信息:https://stackoverflow.com/a/30507725/895245 https://stackoverflow.com/a/30507725/895245

将其用作:

as -o a.o a.S
ld --oformat binary -o a.img -T linker.ld a.o

然后你可以启动为:

qemu-system-i386 -hda a.img

此存储库上的工作示例:https://github.com/cirosantilli/x86-bare-metal-examples/blob/d217b180be4220a0b4a453f31275d38e697a99e0/Makefile https://github.com/cirosantilli/x86-bare-metal-examples/blob/d217b180be4220a0b4a453f31275d38e697a99e0/Makefile

在 Binutils 2.24、Ubuntu 14.04 上测试。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 GNU 汇编器 (as) 将汇编文件编译为原始二进制(如 DOS .com)格式? [复制] 的相关文章

  • x86 汇编中 cmove 指令的用途?

    反汇编可执行文件时我遇到了cmove操作说明 我已经在互联网上搜索过 但我只发现这是一个有条件的移动 如果源和目的地相等mov发生 我还不明白为什么我需要它 因为它不会改变操作数 它的目的是什么 The CMOVcc指令不比较源和目标 它们
  • 大端和小端表示

    如果我写以下内容 section data align 4 X db 1 Y dw 5 Z db 0x11 section text add dword X 0xAA000101 我试图理解大端和小端表示之间的差异 但我不明白每个表示的每个
  • 什么是微编码指令?

    我看过很多参考微编码指令的文献 这些是什么以及为什么使用它们 CPU 读取机器代码并将其解码为内部控制信号 将正确的数据发送到正确的执行单元 大多数指令映射到一个内部操作 并且可以直接解码 例如 在 x86 上 add eax edx只是将
  • NOP 雪橇如何工作?

    我找不到回答这个问题的好来源 我知道 nop sled 是一种用于规避缓冲区溢出攻击中堆栈随机化的技术 但我无法理解它是如何工作的 有什么简单的例子可以说明这种方法 128 字节 nop sled 等术语是什么意思 有些攻击包括使程序跳转到
  • 在 NASM 中使用 istruc 时:“警告:尝试初始化 BSS 部分‘.bss’中的内存:忽略 [-w+other]”

    在搜索这个错误时我发现this https stackoverflow com questions 65731514 nasm attempt to initialize memory in bss section 77001709问题 但
  • 分配内存空间的宏

    我需要让一个汇编程序员来计算帕斯卡三角形 https en wikipedia org wiki Pascal 27s triangle 这样帕斯卡三角形的每一行都与其他行分开存储在内存中 我想做一个 但我不知道如何使用宏在汇编中做到这一点
  • 汇编编程语言:程序仅当输入为 ESC 时退出,并在退出前要求确认(y/n),否则循环

    我只是汇编语言编程的初学者 我们的第一个任务是让程序仅在输入为 ESC 时退出 退出之前请求确认 y n 否则循环 我知道 ESC 在 ASCII 代码中具有等效值 但我对插入位置或是否需要添加更多内容感到困惑 请帮我 这是程序 model
  • 使用 gdb 调试反汇编库

    在Linux和Mac OS X中可以使用strapi和next来调试应用程序而无需调试信息 在 Mac OS X 上 gdb 显示在库内部调用的函数 尽管有时会在每个 stepi 指令中推进多个汇编程序指令 在 Linux 上 当我进入动态
  • 为什么这个 C++ 包装类没有被内联掉?

    EDIT 我的构建系统出了问题 我还在弄清楚到底是什么 但是gcc产生了奇怪的结果 尽管它是 cpp文件 但是一旦我使用了g 然后它按预期工作 对于我一直遇到麻烦的事情来说 这是一个非常精简的测试用例 其中使用数字包装类 我认为会内联 使我
  • 编写 AMD64 SysV 程序集时使用哪些寄存器作为临时寄存器?

    我正在使用实现一个功能cpuid根据 AMD64 SysV ABI 进行组装 我需要在函数本身中使用 2 个临时寄存器 第一个用于累积返回值 第二个用作计数器 我的功能目前如下所示 zero argument function some c
  • 汇编指令陷阱有什么作用?

    当程序需要时 程序通常会发出软件陷阱 由操作系统提供服务 通用异常处理程序 操作系统确定陷阱的原因并做出响应 适当地 汇编指令 trap 和 BASIC 中的 TRAP 指令一样吗 答案似乎是肯定的 你能接受还是拒绝我的结论 不中断 的代码
  • 取消的分支与常规分支有何不同?

    特别是对于 SPARC Assembly 取消的分支与常规分支有何不同 我一直认为 当我需要填充分支指令的 nop 延迟槽时 需要取消分支指令 但是 我认为我在这一部分上是不正确的 因为您可以在不取消分支的情况下填充 nop 如果不采用分支
  • 为什么 Solaris 汇编器生成的机器代码与 GNU 汇编器在这里不同?

    我为 amd64 编写了这个小汇编文件 对于这个问题来说 代码的作用并不重要 globl fib fib mov edi ecx xor eax eax jrcxz 1f lea 1 rax ebx 0 add rbx rax xchg r
  • NASM 轮班操作员

    您将如何在寄存器上进行 NASM 中的位移位 我读了手册 它似乎只提到了这些操作员 gt gt lt lt 当我尝试使用它们时 NASM 抱怨移位运算符处理标量值 您能解释什么是标量值并举例说明如何使用 gt gt and lt lt 另外
  • 汇编基础知识:输出寄存器值

    我刚刚开始学习汇编语言 我已经陷入了 在屏幕上显示存储在寄存器中的十进制值 的部分 我使用 emu8086 任何帮助将不胜感激 model small Specifies the memory model used for program
  • 近调用/跳转表并不总是在引导加载程序中工作

    一般问题 我一直在开发一个简单的引导加载程序 并在某些环境中偶然发现了一个问题 在这些环境中 此类指令不起作用 mov si call tbl SI Call table pointer call call tbl Call print c
  • 减法进位标志

    我正在使用 MASM32 有了这个代码 mov eax 5 sub eax 10 CF 状态标志将被设置 但使用我的铅笔和纸 我实际上看到 MSB 没有任何进位 是的 我知道从较少的数字中减去大的数字集CF 但我想知道为什么 因为使用这段代
  • 从汇编程序获取命令行参数

    通读 专业汇编语言书籍 似乎它提供了用于读取命令行参数的错误代码 我纠正了一点 现在它从段错误变成了读取参数计数 然后是段错误 这是完整的代码 data output1 asciz There are d params n output2
  • 为什么 GCC 不将 a*a*a*a*a*a 优化为 (a*a*a)*(a*a*a)?

    我正在对科学应用程序进行一些数值优化 我注意到的一件事是 GCC 会优化调用pow a 2 通过将其编译成a a 但是调用pow a 6 没有优化 实际会调用库函数pow 这大大降低了性能 相比之下 英特尔 C 编译器 http en wi
  • 为什么当大小大于 50 时,该程序花费的时间会呈指数级增长?

    所以我正在为类编写一个 ARM 汇编快速排序方法 我对大部分内容都有了解 除了复杂性没有意义 我们将其与我们制作的另一种冒泡排序方法进行比较 它对于具有 1 个参数和 10 个参数的示例表现更好 然而 我什至无法比较 100 个参数测试 因

随机推荐