assembly - 从引导加载程序运行时 STOSB 指令不存储字节

标签 assembly x86 x86-16 bootloader real-mode

在制作了一个小型引导加载程序来自学汇编语言之后,我注意到 stosb 指令似乎不起作用。我将问题压缩为一个最小的示例:

BITS 16

start:
mov ax, 07C0h       
add ax, 288     
mov ss, ax
mov sp, 4096

mov ax, 07C0h       
mov ds, ax ;setting up stack

mov al, 'j'
mov di, buffer
stosb

mov si, buffer
jmp loops

loops:
mov ah, 0Eh
lodsb
cmp al, 0
je done
int 10h
jmp loops

done:
hlt

buffer times 64 db 0

times 510-($-$$) db 0   ; Pad remainder of boot sector with 0s
dw 0xAA55

当这个引导加载程序运行时,它应该将字母j存储到缓冲区中,然后将该缓冲区打印到显示器上。输出应该是:

j

运行时它似乎没有打印任何内容。有什么问题,如何解决?

最佳答案

Michael Petch、Weather Vane、Jim Mischel 和 GJ 在评论中给出了解决方案。详细说明:

STOSB 指令隐式将数据存储到 [ES:DI],而 LODSB 指令隐式从 [DS 加载数据:SI]。您可以使用STOSB写入buffer并使用LODSBbuffer读取。但是,您设置了 DS 段寄存器,但未设置 ES。因此,您不会将 'j' 字符存储到您正在读取的同一位置。

解决方案只需将ESDS一起设置即可:

mov ax, 07C0h       
mov ds, ax
mov es, ax

注意:您可能还想明确清除 direction flag在代码中使用字符串指令(例如 LODSBSTOSB)之前。您可以使用 CLD 指令来执行此操作。 BIOS 很可能会在移交给引导扇区之前清除方向标志(这就是为什么它在没有 CLD 的情况下为您工作),但为了绝对确定,您应该自己清除该标志。

关于assembly - 从引导加载程序运行时 STOSB 指令不存储字节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38250752/

相关文章:

c++ - 为什么要在函数调用时填充堆栈?

将 MIPS 系统调用转换为 getchar();或 scanf();在C中

assembly - 无效的基/索引表达式

x86 - Intel 8086汇编中CS和IP寄存器的用途是什么?

assembly - 8086 中的中断、指令指针和指令队列

assembly - 字符串打印机不打印换行符

macos - Mac OS X 上的 64 位程序集运行时错误 : "dyld: no writable segment" and "Trace/BPT trap"

multithreading - 是否因为 “lock”而没有使用 “cache coherency mechanism”操作码前缀?

assembly - 试图获取当前运行的 .COM 程序的名称。它存储在哪里?

assembly - 在 16 位实模式下改变中断