【问题标题】:Assembly code compiled from gcc not running从 gcc 编译的汇编代码未运行
【发布时间】:2022-01-12 07:15:14
【问题描述】:

今天,我决定制作一个(非常)简单的操作系统。我不想直接使用汇编,因为我认为它对我来说太乱了。但是,我知道一点C,我渴望学习更多。我做了一个简单的程序来打印一个字符串,我想把它编译成汇编。我用这个命令编译成程序集:

gcc -S foo.c

这是我的 C 代码:

#include<stdio.h>

int main() {
        printf("Hi!!!");
}

但是当我尝试运行输出文件 (foo.s) 时,出现以下错误:

foo.s:1: error: parser: instruction expected
foo.s:2: warning: label alone on a line without a colon might be in error [-w+label-orphan]
foo.s:3: error: parser: instruction expected
foo.s:5: error: parser: instruction expected
foo.s:6: warning: label alone on a line without a colon might be in error [-w+label-orphan]
foo.s:7: error: parser: instruction expected
foo.s:8: error: parser: instruction expected
foo.s:11: warning: label alone on a line without a colon might be in error [-w+label-orphan]
foo.s:12: error: parser: instruction expected
foo.s:13: error: parser: instruction expected
foo.s:14: error: parser: instruction expected
foo.s:15: error: expression syntax error
foo.s:16: error: parser: instruction expected
foo.s:17: error: parser: instruction expected
foo.s:18: error: parser: instruction expected
foo.s:20: error: label `movl' inconsistently redefined
foo.s:18: info: label `movl' originally defined here
foo.s:20: error: parser: instruction expected
foo.s:21: error: parser: instruction expected
foo.s:22: error: parser: instruction expected
foo.s:24: warning: label alone on a line without a colon might be in error [-w+label-orphan]
foo.s:26: error: parser: instruction expected
foo.s:27: error: parser: instruction expected
foo.s:28: error: parser: instruction expected

这是我为编译汇编代码而运行的命令:

nasm -f bin -o foo.bin foo.s

这是foo.s中的汇编代码:

        .file   "foo.c"
        .text
        .section        .rodata
.LC0:
        .string "Hi!!!"
        .text
        .globl  main
        .type   main, @function
main:
.LFB0:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        leaq    .LC0(%rip), %rdi
        movl    $0, %eax
        call    printf@PLT
        movl    $0, %eax
        popq    %rbp
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE0:
        .size   main, .-main
        .ident  "GCC: (Debian 10.2.1-6) 10.2.1 20210110"
        .section        .note.GNU-stack,"",@progbits

有人请帮帮我!

【问题讨论】:

  • 你想用foo.bin做什么?
  • @littleadv 我将使用:dd.bin 文件转换为foo.flp,这样我就可以使程序可启动。
  • 您的程序将无法启动,因为它使用了标准库。
  • @DYZ 实际上我只是测试了它。我怎样才能让它启动呢?
  • 当你说你“试图运行输出文件 foo.s”时,你到底做了什么?您不能“运行” .s 文件,因为它是源文件。它必须首先组装和链接。

标签: c assembly gcc nasm


【解决方案1】:

gcc 输出不使用 NASM 语法。您应该使用as 将其组装成一个目标文件,然后与标准库链接:

> as -o foo.o foo.s
> gcc foo.o # Link
> ./a.out
Hi!!!

【讨论】:

  • 谢谢!!!!!!!!!我终于想出了如何将 gcc 创建的程序集编译为 .bin 文件!!!!!
  • as 的输出不是平面二进制文件,因此.bin 是一个误导性的扩展;使用as -o foo.o 而不是as -o foo.bin
  • @PeterCordes 我使用与 OP 相同的名称以避免混淆。
  • 这实际上增加了混乱,因为nasm -fbin 确实制作了一个平面二进制文件; GAS 没有这样的模式。你需要ld 和/或objcopy 来使用GNU 工具链:Writing / linking a flat binary using NASM + LD 是谷歌的第一个热门。当然,您不能只在任何可执行文件上执行此操作,尤其是不能动态链接到 libc 且不设计为可引导的可执行文件。即使你解决了这个问题,让部分正确也很棘手:GCC create flat binary with correctly linked data section
  • @SaishShankar:编写 UEFI 应用程序。传统的 BIOS 平面二进制 MBR 引导加载程序基本上至少需要一些 asm,并且过于狭窄(510 字节)而无法容纳 C 库。从应该在 Linux 下运行的普通 C 程序获取编译器输出并将该机器代码 + 数据放入平面二进制文件中是行不通的。除非你知道足够多的 asm + inline-asm 来让 C 编译器发出正确的机器码字节,否则这永远不会奏效,在这种情况下,你需要知道足够多的知识才能可以刚刚编写 asm首先。
猜你喜欢
  • 2023-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-22
  • 2015-12-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多