为什么我的机器代码没有按预期运行?

Why does my machine code not behave as expected?

我正在使用 DOSBox 调试器作为环境来探索基于 x86/64 的处理器如何遍历机器代码。

作为参考,我使用的 "DOS2 length-delimited output" 示例位于: https://montcs.bloomu.edu/~bobmon/Information/LowLevel/Assembly/hello-asm.html

我尝试了几种不同的方法,但这是产生最接近我正在寻找的结果的方法。

我正在使用十六进制编辑器手动输入字节,这是我目前保存在名为 "executable.com":

的文件中的十六进制代码
68 DD 01 1F B2 00 B6 00 B1 06 B3 01 B4 40 B0 00
CD 21 B4 4C B0 00 CD 21 48 65 6C 6C 6F 21 0A D0
0A 24 20

通过调试器执行此文件可得到以下代码概览:

01DD:0100  68DD01              push 01DD
01DD:0103  1F                  pop  ds
01DD:0104  B200                mov  dl,00
01DD:0106  B600                mov  dh,00
01DD:0108  B106                mov  cl,06
01DD:010A  B301                mov  bl,01
01DD:010C  B440                mov  ah,40
01DD:010E  B000                mov  al,00
01DD:0110  CD21                int  21
01DD:0112  B44C                mov  ah,4C
01DD:0114  B000                mov  al,00
01DD:0116  CD21                int  21

这有点类似于 link 中的代码(当然我也尝试过),它确实按预期打印了一个长度为 6 的字符串。
但是,字符串不是从我想要的位置获取的,因此输出只是一堆字符,而不是十六进制代码中存在的 "Hello!"。

对正在发生的事情有什么想法吗?

我按照 Peter Cordes 的建议使用 NASM 重新创建了这个示例,它最初产生的结果与我之前的一次尝试完全相同,但是当我将 "org 0x100" 添加到我的汇编源代码的开头时我得到了我想要的结果。

这实际上为所有地址添加了一个偏移量,因为代码加载到地址 0x100 而非 0x00 的内存中时需要。 在此示例中,"org 0x100" 仅导致生成结果中的一位发生变化,但这一位是从内存中正确位置读取与提前读取 256 字节之间的区别。

机器代码最终是这样的:

BA 13 01 B9 06 00 BB 01 00 B8 00 40 CD 21 B8 00
4C CD 21 48 65 6C 6C 6F 21

以及用于生成它的汇编代码:

org 0x100

mov dx, msg
mov cx, 0x06
mov bx, 1
mov ax, 0x4000
int 0x21
mov ax, 0x4C00
int 0x21

msg db "Hello!"