【问题标题】:How to get the size of nasm-assembled instructions in boot sector?如何获取引导扇区中 nasm 汇编指令的大小?
【发布时间】:2020-10-06 22:17:15
【问题描述】:

我正在用 nasm 组装一个程序以适应引导扇区(最大 512 字节)。

例如nasm -f bin boot.asm -o boot.bin

程序的最后两行用 0 填充剩余空间并添加魔术字节:

times 510 - ($-$$) db 0 ; Pad the remaining of the first 510 bytes with 0
dw 0xaa55               ; Magic bytes required at end of boot sector

输出的boot.bin 文件始终为 512 字节(预期),因此我不能随便查看boot.bin 的大小来获得有意义的(非填充和非魔术字节)指令的大小。

我想在汇编时打印 ($-$$) 会起作用(类似于 gcc 的 #warning#pragma message),但我找不到在 nasm 汇编时打印的任何方法。

在填充之前是否有一种简洁或直接的方法来了解指令的大小?

最好避免在运行时打印或通过 boot.bin 向后搜索寻找非零值等 hacky 方法。

【问题讨论】:

  • 只需使用-l 请求列表。或者使用您的构建环境将文件填充到 nasm 之外。
  • @Jester 的评论是最佳答案。我使用-l listing.txt 生成列表文件。在列表文件中,可以清楚地看到有意义的指令的大小。

标签: assembly x86 nasm boot


【解决方案1】:

您可以使用%assign 在汇编时计算数值表达式。 (每个汇编过程也使用预处理器。这就是您可以使用预处理器对标签进行有限算术的方法。)然后use %warning to display an assemble time message。唯一的缺点是它会显示“作为警告”,但它是装配时间输出。引用手册:

[...] %warning 发出警告,但允许组装继续:

[...]

%error、%warning 或 %fatal 之后的消息字符串是否被引用是可选的。如果是not,则在其中展开单行宏,可用于向用户显示更多信息。

my boot sector loaders 我这样做:

available:
    _fill 508,38,start

signatures:
    dw 0
; 2-byte magic bootsector signature
    dw 0AA55h

%assign num signatures-available
%assign fatbits 12
%if _FAT16
 %assign fatbits 16
%endif
%warning FAT%[fatbits]: num bytes still available.
%endif

end:

_fill 来自the macro collection。这里第一个dw的含义参考my question about the zeros

示例输出:

boot.asm:1600: warning: FAT12: 10 bytes still available. [-w+user]

【讨论】:

  • 这很有趣。从名称上看,我预计“预处理器指令”会在任何组装完成或计算任何地址之前在较早的通道上执行,所以我不会猜到这会起作用。
  • @Nate Eldredge:我基本上在任何重要的程序中都使用这种集成预处理器方案的功能。这就是您不能对我的任何来源执行nasm -E(仅限预处理)的原因。提示error: symbol references not supported in preprocess-only mode
【解决方案2】:

您可以在填充之前放置一个标签并执行size: dw $-$$ 以在引导加载程序中存储一个大小,您可以在 asm 列表或 hexdump 中查看该大小。但这会占用 2 个字节。

nasm -fbin foo.asm -l /dev/stdout | less 将显示地址的列表 |十六进制转储 |源代码行,可以很容易地查看time ... db 0 的开始位置以及您放入dw 的整数。例如,您可以在 a code-golf answer of mine 中看到该格式的示例。


或者您可以简单地注释掉times 510 - ($-$$) db 0 / dw 0xaa55 填充并查看文件大小!

如果您已接近限制,请在优化代码大小时将其注释掉,直到您认为应该适合并且可以工作。

【讨论】:

  • 真的没有什么比得上MASM的ECHO $吗?类似于在开头定义lblBEGIN EQU $,在结尾定义ECHO $-lblBEGIN
  • @zx485: 就像 CPP #warn 等价于让汇编器本身在汇编时执行 I/O?从来没听说过; nasm 保持简单。如果您将.o.obj-felf32(或something16?)组装成nm,您可以使用nm 获得符号元数据。
  • 好吧,好吧。但我不明白“NASM 保持简单”,因为我不认为 assemble-time output 函数很复杂 ;-) 但是,感谢您的回答。
  • @ecm:啊,对不起。我确实尝试过(但尝试“错误”,没有 %[ ] 让它扩展)。
  • @zx485: 原来我错了,NASM 的%warning 可以 参考符号偏移之类的东西;请参阅@ecm 的答案。 (简单来说,我并不是说很难实现,我的意思是语言设计 POV 很奇怪,就像它变成了一种脚本语言,可以对运行汇编程序的终端进行 I/O。)
猜你喜欢
  • 2021-09-03
  • 2021-12-27
  • 2016-08-02
  • 2021-12-16
  • 1970-01-01
  • 2013-07-16
  • 2013-07-15
  • 2012-03-16
  • 1970-01-01
相关资源
最近更新 更多