作为学习操作系统开发的一部分,我正在 x86 引导扇区中开发代码。我希望我的代码将其打印到控制台:
你好
我得到了这个:
H
为什么它只打印一个字符而不是整个字符串?我怎样才能解决这个问题?
这是我的代码片段:
mov ah, 0x0e
mov bx, string_p
add bx, 0x7c00
mov al, [bx]
int 0x10
jmp $
string_p:
db 'Hello',0
"then padding and magic number"
作为学习操作系统开发的一部分,我正在 x86 引导扇区中开发代码。我希望我的代码将其打印到控制台:
你好
我得到了这个:
H
为什么它只打印一个字符而不是整个字符串?我怎样才能解决这个问题?
这是我的代码片段:
mov ah, 0x0e
mov bx, string_p
add bx, 0x7c00
mov al, [bx]
int 0x10
jmp $
string_p:
db 'Hello',0
"then padding and magic number"
中断10H
,寄存器AH
设置为0EH
(INT 10h/AH=0eh),将打印寄存器中的当前字符AL
。Ralf Brown 的中断列表被认为是 DOS 和 BIOS 中断的圣经。它是关于哪些中断可用、它们如何工作以及它们的副作用的宝贵信息来源。
如果您使用INT 10h/AH=0eh您需要手动推进每个字符的字符串指针并一次打印出一个。像这样的代码应该可以工作:
org 0x7c00 ; starting address
bits 16 ; 16-Bit mode
main:
cli ; disable interrupts
cld ; clear direction flags
xor ax, ax ; set AX to 0
mov ds, ax ; set DS to 0
mov ah, 0x0e ; call 0EH bios call
mov si, string ; move starting address of `string` into SI
loop:
lodsb ; load byte at DS into AL, update (increment) SI
or al, al ; check if AL is 0 (ORing will do nothing, but set the right flags
jz hltloop ; if zero jump to end
int 0x10 ; do the print call
jmp loop ; jump back to loop start
hltloop:
hlt ; halt and catch fire
jmp hltloop ; jump back to halt, if an interrupt occurred anyway
string:
db 'Hello',0
times 510-($-$$) db 0
dw 0xAA55
此示例使用LODSB指令读取字符串的每个字符。LODS指令记录为:
将源操作数中的字节、字或双字分别加载到AL、AX 或 EAX 寄存器中。源操作数是一个内存位置,其地址从 DS:ESI 或DS:SI寄存器中读取(取决于指令的地址大小属性,分别为 32 或16)。DS 段可以被段覆盖前缀覆盖。
这已经很晚了,但可能会对某人有所帮助。我在 ubuntu 上开发操作系统时遇到了同样的问题。这对我有用。我创建了一个打印函数并在将我的字符串地址移动到 bx 后调用它:
print_function:
pusha
mov ah, 0x0e
mov al, [bx]
int 0x10
cmp al, 0
jne increment
jmp the_end
increment:
add bx , 1
mov al, [bx]
int 0x10
cmp al, 0
jne increment
jmp the_end
the_end:
popa
ret