使用 GAS AT&T 指令计算引导扇区的填充长度?

2023-12-06

所以我想在引导扇区添加填充。比方说,目前只有一个无限循环:jmp .。该扇区的长度需要为 512 字节。还有,神奇的数字0xaa55需要在最后添加。

jmp .
.skip 508, 0
.word 0xaa55

但是,如果我想打印一些内容,但不想计算所有字节以将其填充到正确的大小,该怎么办?
在 Intel/NASM 语法中它将是:

; print something
times 510-($-$$) db 0
dw 0xaa55

但在 AT&T 语法中呢?那么一个循环(.rept)在这里不起作用,因为.没有给出这里需要的绝对值。我们有同样的问题.skip/.space,他们也需要一个绝对值。

有没有一种方法可以使用某种循环/添加填充.align/.skip/etc?

编辑: 我用as构建和链接ld -Ttext 0x7c00 --oformat binary until yasm对于 AT&T 语法来说足够稳定。


使用 AT&T 语法,您可以在引导加载程序的开头放置一个标签,然后使用如下所示的内容:

.global _start
.text
.code16
_start:
    jmp .

.space 510-(.-_start)
.word 0xaa55

Period .是相对于当前节开头的当前位置计数器。时期之间的差异. and _start是一个绝对值,因此应该适用于此表达式。

您可以使用GCC(这将调用LD)使用如下命令将其组装到引导加载程序:

gcc -Wl,--oformat=binary -Wl,-Ttext=0x7c00 -Wl,--build-id=none \
    -nostartfiles -nostdlib -m32 -o boot.bin boot.s

选项-Wl,--oformat=binary将此选项传递给链接器,这将强制其输出到平面二进制文件。-Wl,-Ttext=0x7c00会将此选项传递给链接器,该链接器将有效地将原点设置为 0x07c00。-Wl,--build-id=none告诉链接器不要使用 GCC 可能生成的构建 ID。 0x7c00 是代码预计加载的偏移量。因为我们不能使用标准库或C运行时我们排除它们-nostartfiles -nostdlib

如果您打算将多个文件链接在一起,您将无法使用此方法。在这种情况下,您需要将启动签名保留在代码之外,并让链接器使用特制的链接器脚本来处理它。如果您将引导加载程序包含在单个程序集文件中,则上述方法将起作用。


我有一些通用的引导加载程序提示用于编写引导加载程序代码。人们通常遇到的一大问题是没有设置段寄存器。如果您使用原点 0x7c00,那么您至少需要确保DSregister us 设置为 0。如果您编写的代码使用引用代码中标签的内存操作数,那么这一点很重要。

使用 GNU 汇编器进行汇编时,请确保设置了所需的正确指令编码。.code16将使汇编器假定目标处理器正在 16 位模式下运行。.code32对于 32 位编码,.code64假设采用 64 位编码。默认为as一般不会.code16.


具有多个目标文件的引导加载程序

正如我上面提到的,使用多个目标文件来创建引导加载程序会带来汇编指令无法克服的挑战。为此,您可以创建一个特殊的链接器脚本,将 Origin 点设置为 0x7c00,并让链接器将引导签名放置在输出文件中。使用此方法,您不需要执行任何填充,链接器将为您完成此操作。处理传统部分的基本链接器脚本,例如.text, .data, .rodata如下所示。您可能永远不会使用该部分的某些部分,但我将它们添加为示例:

File bootloader.ld

OUTPUT_FORMAT("elf32-i386");
ENTRY(_start);
SECTIONS
{
    . = 0x7C00;
    /* Code section, .text.bootentry code before other code */
    .text : SUBALIGN(0) {
        *(.text.bootentry);
        *(.text)
    }

    /* Read only data section with no alignment */
    .rodata : SUBALIGN(0) {
        *(.rodata)
    }

    /* Data section with no alignment */
    .data : SUBALIGN(0) {
        *(.data)
    }

    /* Boot signature at 510th byte from 0x7c00 */
    .sig : AT(0x7DFE) {
        SHORT(0xaa55);
    }

    /DISCARD/ : {
        *(.eh_frame);
        *(.comment);
        *(.note*);
    }
}

File boot.s包含引导加载程序的主入口点:

# Section .text.bootentry is always placed before all other code and data
# in the linker script. If using multiple object files only specify
# one .text.bootentry as that will be the code that will start executing
# at 0x7c00

.section .text.bootentry
.code16
.global _start
_start:
    # Initialize the segments especially DS and set the stack to grow down from
    # start of bootloader at _start. SS:SP=0x0000:0x7c00
    xor %ax, %ax
    mov %ax, %ds
    mov %ax, %ss
    mov $_start, %sp
    cld                   # Set direction flag forward for string instructions

    mov  $0x20, %al       # 1st param: Attribute black on green
    xor  %cx, %cx         # 2nd param: Screen cell index to write to. (0, 0) = upper left
    mov  $boot_msg, %dx   # 3rd param: String pointer
    call print_str

    # Infinite loop to end bootloader
    cli
.endloop:
    hlt
    jmp .endloop

.section .rodata
boot_msg: .asciz "My bootloader is running"

File aux.s使用一个简单的函数将字符串直接显示到屏幕上:

.global print_str         # Make this available to other modules
.section .text
.code16

# print_str (uint8_t attribute, char *str, uint16_t cellindex)
#
# Print a NUL terminated string directly to video memory at specified screen cell
# using a specified attribute (foreground/background)
#
# Calling convention:
#     Watcom
# Inputs:
#     AL = Attribute of characters to print
#     CX = Pointer to NUL terminated string to print
#     DX = Screen cell index to start printing at (cells are 2 bytes wide)
# Clobbers:
#     AX, ES
# Returns:
#    Nothing

print_str:
    push %di
    push %si

    mov  $0xb800, %di     # Segment b800 = text video memory
    mov  %di, %es
    mov  %cx, %di         # DI = screen cell index (0 = upper left corner)
    mov  %dx, %si         # SI = pointer to string (2nd parameter)
    mov  %al, %ah         # AH = attribute (3rd parameter)
    jmp  .testchar

# Print each character until NUL terminator found
.nextchar:
    stosw                 # Store current attrib(AH) and char(AL) to screen
                          # Advances DI by 2. Each text mode cell is 2 bytes
.testchar:
    lodsb                 # Load current char from string into AL(advances SI by 1)
    test %al, %al
    jne  .nextchar        # If we haven't reach NUL terminator display character
                          #     and advance to the next one

    pop %si
    pop %di
    ret

将此引导加载程序构建到名为的文件中boot.bin我们可以这样做:

as --32 aux.s -o aux.o
as --32 boot.s -o boot.o
ld -melf_i386 --oformat=binary -Tlink.ld -nostartfiles -nostdlib \
    aux.o boot.o -o boot.bin

特别的.text.bootentry由链接器脚本放置为第一个代码。该部分只能在一个目标文件中定义,因为它将是出现在引导加载程序开头的 0x7c00 处的代码。链接器脚本将 VMA(原点)调整为 0x7dfe 并写入启动签名 (0xaa55)。 0x7dfe 比前 512 字节末尾低 2 个字节。我们不再在汇编代码中进行任何填充,也不再在那里发出启动签名。

运行此示例引导加载程序时,应在显示屏的左上角打印一个绿色背景上黑色的字符串。

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

使用 GAS AT&T 指令计算引导扇区的填充长度? 的相关文章

随机推荐

  • mysql_real_escape_string 和 array_map 返回空白字符串?

    我还没有学会如何使用参数化查询 根据本网站上的其他一些帖子 这是我明天早上绝对需要做的第一件事 并且我想将大量表单数据放入查询中 转义 我两次遇到过这个解决方案 POST array map mysqli real escape strin
  • Amazon SES 从实例配置文件元数据服务器检索凭证时出错。 (客户端错误:404)

    在让 AWS SES 正常工作时遇到一些问题 我想从我的网站向用户发送电子邮件 看起来凭证没有经过验证 但是我使用了从 IAM 生成的正确凭证 我还尝试了服务器根密钥 但它给了我同样的错误 我已经没有关于如何进一步解决 调试的想法 因此任何
  • Spring Batch 和 Cloudera hadoop 版本不兼容

    我正在尝试 Spring Batch 字数统计程序并遇到这样的版本问题 ERROR org springframework batch core step AbstractStep
  • 函数生成;更改其他功能的默认值(部分)

    我需要一个函数生成器 它接受另一个函数和该函数的任何参数并设置新的默认值 我以为 hadley 的pryr partial这就是那个神奇的功能 它完全符合我的要求 只是您无法更改新的默认值 所以在这里我可以改变sep在我的新paste函数
  • 线程安全数据集

    我想让 DataTable DataSet 的更新操作成为线程安全的 有大约 20 个线程 每个线程使用以下命令更新大约 40 行全局 DataTableRows Find pk 数据表的方法 每个线程将更新 DataTable 的不同行
  • 如何提高 boost Interval_map 查找的性能

    我正在使用一个boost icl interval map将字节范围映射到一组字符串 该地图是从 已排序的 磁盘文件加载的 然后我使用下面的代码进行查找 问题是查找速度非常慢 在我的测试中 我在地图中插入了 66425 个范围 我分析了代码
  • 如何在多索引 Pandas 数据框中按组更新前 N 行的值?

    我正在尝试更新多索引数据框中的前 N 行 但在寻找解决方案时遇到了一些麻烦 所以我想为它创建一个帖子 示例代码如下 Imports import numpy as np import pandas as pd Set Up Data Fra
  • AWS Cloudformation 中 UserData 中的参考参数值

    我在参数部分有这个 Parameters PlatformSelect Description Cockpit platform Select Type String Default qa 1 AllowedValues qa 1 qa 2
  • 使用 javascript 播放以 Base64 编码的 .wav 声音文件

    我能够通过以下方式用 javascript 播放声音 var snd new Audio sound wav snd play 这会播放所需的声音 但有时加载速度很慢 甚至可能根本不加载 所以我用 Base 64 对声音进行编码并尝试以这种
  • 找不到添加到 xcode 7 的自定义字体的名称

    我在获取自定义字体的名称时遇到问题 我将字体添加到我的项目中 并选中 如果需要则复制 选项 我将字体名称添加到应用程序提供的 info plist 标签 Fonts 中 我将字体添加到复制捆绑资源中 该字体出现在自定义选项卡下的情节提要中
  • FileStore 4.2.1 分步示例

    我想要上传 csv 文件 验证它 然后上传到现有模型中 然而 我正在使用 ATK4 2 1 发现 google 搜索到的示例代码要么缺少一些步骤 要么与版本 4 2 1 不相关 为此 在我的第一步中 我尝试混合和匹配代码 试图让文件存储启动
  • mod_rewrite:删除尾部斜杠(只有一个!)

    我使用 mod rewrite htaccess 来获得漂亮的 URL 我使用此条件 规则来消除尾随斜杠 或者更确切地说 通过 301 重定向重写到非尾随斜杠 URL 我这样做是为了避免重复内容 因为我喜欢没有尾随斜杠的 URL更好的 Re
  • 为什么 Canvas API 在循环中使用错误的颜色填充这些路径的部分内容?

    我创建了一个JSFiddle所有代码均处于活动状态并正在运行 相关JS在这里 const canvas document getElementById base const ctx canvas getContext 2d const cW
  • Lambda 未加载加密共享库

    我正在使用 AWS Lambda 中的加密库 我已在 Amazon Linux VM 中使用 pip 编译了该包 我已将包作为图层上传 不管怎样 每次我调用库时 我都会遇到一个根本不具有描述性的错误 Unable to import mod
  • 如何在Python PyQt5中将变量分配给工作线程?

    我使用pyqt5设计了一个GUI程序 我有一个主线程和一个工作线程 当 GUI 启动时 我会从用户那里获得一些输入 例如年龄 姓名 并且我想在工作人员中处理这些输入 例如我如何发送我使用的输入self ui firstname text 给
  • Silverlight:从 silverlight 控件创建图像

    是否可以从 silverlight 控件生成图像 以便该控件将自身及其内容渲染到图像中 以便我可以对图像进行相同的像素操作 在 Silverlight 2 中无法实现此目的 我见过人们通过将 XAML 发布到服务器来解决此限制 该服务器将使
  • 如何在 C# 中反序列化包含可变数量对象的 json 对象并将它们作为键值集合?

    如何反序列化以下 JSON 对象并获取 Dictionary 的集合 其中键 字符串 应该是方法名称 对象是 C 中的详细信息 methods password 2 title Password CustomerID type passwo
  • 使用 iText 将标题添加到 pdf

    如何使用 iText 5 0 5 将页眉添加到每个 PDF 页面 这涵盖在 iText 实践 第二版第 5 章 代码示例均可在线免费获取 尤其电影国家1 and 电影史2两者都处理page页眉和页脚 归结为使用PdfPageEvent实现
  • 拼写错误:找不到合适的拼写检查程序

    虽然功能aspell标配utils包 它似乎不适合我 我不断收到同样的错误 aspell love Error in aspell love No suitable spell checker program found 有什么想法吗 gt
  • 使用 GAS AT&T 指令计算引导扇区的填充长度?

    所以我想在引导扇区添加填充 比方说 目前只有一个无限循环 jmp 该扇区的长度需要为 512 字节 还有 神奇的数字0xaa55需要在最后添加 jmp skip 508 0 word 0xaa55 但是 如果我想打印一些内容 但不想计算所有