我正在使用10h中断,AH为0Eh,输出“Hello World!”文字已被删除但未着色 . 我在qemu-system-x86_64上运行它,与NASM一起组装,我的代码如下:
BITS 16
start:
mov ax, 07C0h ; Set up 4K stack space after this bootloader
add ax, 288 ; (4096 + 512) / 16 bytes per paragraph
mov ss, ax
mov sp, 4096
mov ax, 07C0h ; Set data segment to where we're loaded
mov ds, ax
mov si, text_string ; Put string position into SI
call print_string ; Call our string-printing routine
jmp $ ; Jump here - infinite loop!
text_string db 'Hello World!', 0
print_string: ; Routine: output string in SI to screen
mov ah, 0Eh ; int 10h 'print char' function
mov bh, 0x00
mov bl, 0x03
.repeat:
lodsb ; Get character from string
cmp al, 0
je .done ; If char is zero, end of string
int 10h ; Otherwise, print it
jmp .repeat
.done:
ret
times 510-($-$$) db 0 ; Pad remainder of boot sector with 0s
dw 0xAA55 ; The standard PC boot signature
4 回答
我可以使用09进行10h中断而不是0E打印颜色 . 但是,您必须在每个字符后更改光标位置才能使用此方法 . 这是工作代码 .
我认为比标记为接受的更好的想法是使用中断10h的功能13h . 该函数应该将整个字符串与属性(颜色)一起发送到屏幕 . 这个函数有四个 modes of operation ,在
AL
寄存器中指定 .因此,您可以通过在
BL
中为模式00h
或01h
指定属性来为整个字符串使用相同的属性(颜色),或者将字符串本身中的属性混合以使用不同的属性打印每个字符 .我用这种方法看到的唯一缺点就是你必须事先知道字符串的长度(把它放入
CX
),因为这个函数不能用于以空字符结尾的字符串 .但是,另一方面,在字符之前存储字符串的一个字节长度而不是字符之后的空字符可以有一些好处:你不要占用比空终止符更多的地方 . 即使是两个字节的长度也不是浪费 . 您可以将两个字节的长度直接加载到
CX
中 . 您也可以使用一个字节长度执行相同的操作,但请务必在之后清除CH
.拥有该属性的每个字符的能力属性也有时是有用的 .
其他寄存器照常:
BH
是页码 .DX
是在屏幕上启动字符串的位置:DH:DL = Y:X
ES:BP
指向内存中字符串的第一个字符 .如果使用电传打字模式(
01h
或03h
),则可正确解释ASCII控制字符,而不是作为符号打印 . 它们还将光标位置更新为字符串的末尾 .要使其连续工作,可以使用函数
AH=03h
来获取光标位置 . 它被设置为将光标位置加载到DH:DL
,因此可以在随后的AH=13h
调用中直接使用它来从该位置打印字符串 . 我是这样做的:调用(假设
ES
已正确设置):数据部分:
哦,服务仅适用于1986年1月19日及之后的AT,EGA和PC敞篷车的XT . 但我想它不会造成任何问题,除非你正在处理一件严重的旧垃圾; -J
要更改光标位置:
RBIL-> inter61a.zip-> INTERRUP.A
我更喜欢直接写入0B800h的segmentaddress .
没有经过测试,但我希望没有错误 .