INT 10h / AH = 13h - write string.
input:
AL = write mode:
bit 0: update cursor after writing;
bit 1: string contains attributes.
BH = page number.
BL = attribute if string contains only characters (bit 1 of AL is zero).
CX = number of characters in string (attributes are not counted).
DL,DH = column, row at which to start writing.
ES:BP points to string to be printed.
;--------------------------------------------------------------------------------
Bit color table:
Character attribute is 8 bit value, low 4 bits set foreground color, high 4 bits set background color. Background blinking not supported.
HEX BIN COLOR
0 0000 black
1 0001 blue
2 0010 green
3 0011 cyan
4 0100 red
5 0101 magenta
6 0110 brown
7 0111 light gray
8 1000 dark gray
9 1001 light blue
A 1010 light green
B 1011 light cyan
C 1100 light red
D 1101 light magenta
E 1110 yellow
F 1111 white
我改进了一下这个程序,使用equ伪操作符来计算字符串长度
;%define _DEBUG_
%ifdef _DEBUG_
org 0100h ;编译成com文件进行调试
%else
org 07c00h ; 程序将被加载到07c00h处
%endif
;这里有几个个疑问:
;1、为什么要把cs(代码段地址)传送到es(附加段地址)
; 因为这里只有一个段? 即cs和es的地址都相同,代码段和数据段都是一个段,因此将es的值赋为cs的值,以用于后面显示字符串的寻址。
;2、为什么不能直接这样使用: mov es, cs?
; 对段寄存器的操作限制,
; (1)段寄存器间不能传送
; (2)立即数不能直接传送给段寄存器,要使用通用寄存器作中间步骤,原因是段寄存器需要移位操作
; (3)不能使用mov 修改cs的值
mov ax, cs
mov es, ax
call DispStr ;显示字符串
jmp $ ;无限循环
DispStr:
mov ax, BootMessage
mov bp, ax ;ex:bp = 串地址
mov cx, messageLength;cx = 串长度
mov ax, 01301h ;ah = 13, al =01h
mov bx, 0009h ;页号为0(bh=0),黑底蓝字(bl = 09h,高亮)
mov dx, 0 ;0行0列
int 10h ;10h 号中断
ret
BootMessage: db "Hello, OS world, It's my first Boot loader!"
messageLength equ $-BootMessage
times 510-($-$$) db 0 ;
dw 0aa55h ;
对于学习本书非常有用的Intel 芯片开发用户手册,详细介绍了书中涉及到但作者没有详细介绍的16位32位混合编码,各种内存模式,保护模式编码等
IA-32 Intel® Architecture Software Developer's Manuals