显示器I/O知识:
显存地址是 0xb8000,屏幕是80*25,每个位置由两个字节决定。第一个字节决定所显示的字符,如0xb8000。第二个字节决定怎么显示字符(背景颜色,前景颜色),如0xb8001。
汇编命令知识:
cld: 方向标志置0,si和di 增1或增2;
std: 方向标志置1,si和di 减1或减2
串传送指令(数据从A内存到B内存)
cld
movsb # ds:[si] -> es:[di], ++si, ++di
movsw # ds:[si] -> es:[di], si+=2, di+=2
串存储指令(数据从寄存器到内存)
cld
stosb # al -> es:[di], ++si
stosw # ax ->es:[di], si+=2
串读取指令(数据从内存到寄存器)
cld
lodsb # ds:[si] –> al, ++si
lodsw # ds:[si] –> ax, si+=2
重复前缀指令
rep: 用在movs、stos、lods指令前,每执行一次指令,cx减1;直到cx = 0,重复执行结束。
下面这段代码的作用是把内存中的字符串复制到0xb8000地址上
.text
.global start
.code16
start:
jmp $0x0, $code
msg:
.string "1kos booting......\x0"
code:
movw $0xb800,%ax #显存地址在0xb8000
movw %ax, %es
xorw %di, %di #es:di = 0xb8000
xorw %ax, %ax
movw %ax, %ds #ds:si = msg
movw $msg, %si
cld #si和di自增
movb $0x07, %ah #字符属性:黑底白字
loop:
cmp $0x0, (%si)
je end
lodsb #ds:[si] -> al, ++si
stosw #ax -> es:[di], di += 2 #al=字符 ah=属性
jmp loop
end:
jmp end