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

zer*_*o77 2 x86 assembly real-mode bootloader x86-16

在制作了一个小型引导程序来教我自己的汇编语言后,我注意到该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
Run Code Online (Sandbox Code Playgroud)

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

Ĵ

运行时似乎没有打印任何东西.有什么问题,我该如何解决?

use*_*557 6

解决方案由Michael Petch,Weather Vane,Jim Mischel和GJ在评论中提供.详细说明:

STOSB指令隐含地存储数据[ES:DI],而LODSB指令隐式地从装载数据[DS:SI].你STOSB用来写bufferLODSBbuffer.但是,您设置了DS段寄存器,但没有ES.因此,您不会将'j'角色存储到您正在阅读的相同位置.

解决方案只是ESDS:

mov ax, 07C0h       
mov ds, ax
mov es, ax
Run Code Online (Sandbox Code Playgroud)

注意:您可能还希望在代码中使用字符串指令(例如,)之前显式清除方向标志.您可以按照说明执行此操作.在交付给bootsector之前,BIOS很可能会清除方向标志(这就是为什么它在没有它的情况下为你工作的原因),但是为了绝对确定,你应该自己清除标志.LODSBSTOSBCLDCLD

  • IIRC,对方向标志采取任何措施是不安全的.通常,代码在引导加载程序中尽可能防御,因为现实世界的PC BIOS几乎存在于每个可以想象的错误中.我自己没有写过bootloader代码,但这就是我读过的内容. (2认同)