【问题标题】:Including header file in assembly file在汇编文件中包含头文件
【发布时间】:2020-02-12 15:48:25
【问题描述】:

我试图在我的主程序集文件中包含一个包含宏的头文件,但编译失败。

下面是我的main.S文件

#include "common.h"
BEGIN
    mov $0x0E40, %ax
    int $0x10
    hlt

以下是我的common.h 文件:

.macro BEGIN
    LOCAL after_locals
    .code16
    cli
    ljmp $0, $1f
    1:
    xor %ax, %ax
    /* We must zero %ds for any data access. */
    mov %ax, %ds
    mov %ax, %es
    mov %ax, %fs
    mov %ax, %gs
    mov %ax, %bp
    /* Automatically disables interrupts until the end of the next instruction. */
    mov %ax, %ss
    /* We should set SP because BIOS calls may depend on that. TODO confirm. */
    mov %bp, %sp
    /* Store the initial dl to load stage 2 later on. */
    mov %dl, initial_dl
    jmp after_locals
    initial_dl: .byte 0
after_locals:
.endm

两个文件都在同一个目录中。当我进行编译时:

$ as --32 -o main.o main.S
main.S: Assembler messages:
main.S:2: Error: no such instruction: `begin'

我错过了什么?我做了一些研究并在 SO 中得到了this answer,但它没有帮助。请帮忙。

【问题讨论】:

  • as 不会对您的文件调用 C 预处理器。只有gcc 可以。您可以手动运行它或使用gcc -c。或者您可以使用由as 自己处理的.include
  • 在没有首先运行 CPP 的纯 GAS 中,以# 开头的行是总是 cmets。
  • 谢谢小丑和彼得。这很有帮助。您能否将其发布为答案,以便我接受它并帮助未来的访问者。

标签: gcc assembly gnu gnu-assembler att


【解决方案1】:

$ as --32 -o main.o main.S

as 只是一个汇编器,它将汇编源代码转换为目标代码。它不运行应该扩展 #include 的 C 预处理器。

# 是 x86 的 GAS 语法中的注释字符,因此如果该行被汇编程序看到而不是被 CPP 替换,则该行被视为注释)

你可以做什么:

  1. 使用gcc 进行汇编,带有适当的文件后缀(.S.sx),它将在运行汇编程序之前运行C 预处理器。
    • 添加 -v 以查看 gcc 正在调用哪些命令。
    • 如果您的来源有不同的后缀,您可以-x assembler-with-cpp source.asm
    • 如果要查看预处理后的中间结果,请添加-save-temps。这将使用预处理的源写入一个.s 文件。
    • 如果您想将命令行选项传递给as,您可以例如-Wa,--32。但是,在本例中,最好使用编译器驱动程序可以理解的选项,例如 -m32-m16。驱动程序知道这些选项,例如,它还会在链接时提供适当的选项,前提是您使用gcc -m32 ... 链接,如下所述。
  2. 使用.include 汇编程序指令,该指令由汇编程序本身而非 C 预处理程序处理。

注意:如果情况 1. 通过 -I path 添加包含搜索路径可能无法按预期工作:编译器驱动程序(在本例中为 gcc)将仅将 -I path 添加到汇编器的命令行,如果它知道它是 GNU 汇编器。您可以通过 configure flag --with-gnu-as 配置编译器时告诉这一点。

注意:类似的也适用于链接。您可能不想调用链接器(手动ld),除非您正在制作静态可执行文件或平面二进制文件;如果您要在主机系统上运行正常的可执行文件,请改用gccg++。它将添加许多链接所需的选项,例如您不想手动摆弄的多库路径、搜索路径等。

(不过,int $0x10 是一个 16 位 BIOS 调用,它在现代主流操作系统下无法运行,只能在 DOS 或旧版 BIOS 引导加载程序下运行。)

【讨论】:

    【解决方案2】:

    如果您的头文件只是程序集,则在 main.S 中包含 .include "file" 指令。但是这种做法会将代码插入到其包含的位置。

    【讨论】:

      【解决方案3】:

      mov esi, 71;通缉号码 移动编辑,0 移动 ebx, 1;对于 i = 1;

          mov eax, esi
          xor edx, edx
          div ebx ; salvam rest in edx, cat in eax
          inc ebx; 
          
          cmp edx, 0;daca e 0-> divizor, altfel nu
          je divizor
      
          ; Else non-divizor
          jmp for
      
      divizor:
          inc edi
          jmp for
      
      exit:
          cmp edi, 1;
          jge prim
          jl non_prim
      
      prim:
          ; edi tine numarul de divizori
          push edi
          jmp out
      
      non_prim:
         ; push edi
          jmp out
      
      out:
          cmp edi, 2
          jg no
          jle yes
      
      no:
          push 0
          push printf_fmt_int
          call printf
          add esp, 8
          jmp next
      
      yes:
          push 1
          push printf_fmt_int
          call printf
          add esp, 8
      
      next:
      
      xor eax, eax
      leave
      ret
      

      【讨论】:

      • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
      • 这不使用任何.include 指令。不确定这应该回答什么问题,但肯定不是这个。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-30
      • 2012-05-15
      • 2021-08-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多