【问题标题】:Where to put assembly subroutines in boot sector file在引导扇区文件中放置汇编子程序的位置
【发布时间】:2022-01-06 00:23:04
【问题描述】:

我有以下用 nasm 编写的引导扇区:

[org 0x7c00]

my_print_function:
    mov ah, 0x0e
    int 0x10
    ret

_start:
    mov al, 'A'
    call my_print_function
    call my_print_function

_boot:
    jmp $
    times 510-($-$$) db 0
    dw 0xaa55

我用nasm -f bin boot.asm -o boot.bin 编译,然后运行qemu boot.bin,我只看到打印了一个字符,它是垃圾字符'U',而不是'A'。如果我更改my_print_function_start 的顺序,它会按预期工作,但子例程也会在没有我调用的情况下自行运行一次,因此它会打印'A' 3 次。

通常如果我正在编写程序集,我会在我的section .text 之前定义my_print_function,并在我的section .text 中添加一个global _start,但它似乎在这里没有任何作用。如何定义和使用这样的子例程,而不会因为我定义它而额外运行它?

【问题讨论】:

  • 加载引导扇区的 BIOS 不知道您的_start。它将控制权转移到物理地址0x7c00。所以你应该把你的主要放在那里。你可以把你的函数放在它后面。
  • 是的,我意识到了这一点,但感谢您的评论!
  • 另一种方法是将jmp _start放在开头(地址0x7C00),然后将主代码放在您喜欢的任何位置。这在某些情况下是必要的(当存在“BIOS 参数块”时 - 请参阅en.wikipedia.org/wiki/BIOS_parameter_block
  • @Brendan 这也是一种聪明的做法!谢谢,将其添加到我的武器库中
  • 您的第二段显示了关于如何组装成 ELF 目标文件的严重混淆。 .text 是 NASM 源文件顶部的默认部分;如果您尚未切换到其他部分,section .text 无效。 global _start 是相关的,因为它允许链接器在 ELF 元数据中看到该符号,默认情况下它正在寻找该符号。 IDK,如果您认为您的可执行机器代码不在 .text 部分内,则该 IDK 是 NASM 默认可执行的唯一部分:nasm.us/doc/nasmdoc8.html#section-8.9

标签: assembly nasm x86-16 bootloader subroutine


【解决方案1】:

当我尝试做其他事情时,我想通了,我意识到我做错了什么。子程序需要在无限跳转之后来,例如:

[org 0x7c00]

mov al, 'A'
call my_print_function
mov al, 'B'
call my_print_function

jmp $
my_print_function:
    mov ah, 0x0e
    int 0x10
    ret

times 510-($-$$) db 0
dw 0xaa55


【讨论】:

  • 自学好。不要忘记在两天后将您的答案标记为已接受。
  • 是的,我会的,谢谢你的赞美:)
  • 您可以使用 GDB 单步执行您的代码(作为 gdb-remote 连接到 QEMU)。这应该使这样的问题(以及许多其他问题)显而易见,例如当您看到文件顶部开始执行时,无论那里有什么。 (事后看来应该很明显:一个 512 字节的平面二进制 MBR 没有指示入口点的元数据,只有末尾的 2 字节签名。)在更改段寄存器或切换到保护模式的代码中,Bochs 很好;与 GDB 不同的是,它的内置调试器可以识别分段。
猜你喜欢
  • 2021-09-03
  • 2010-10-08
  • 1970-01-01
  • 1970-01-01
  • 2012-07-25
  • 2018-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多