加入一些实用的打印功能,这对我们的调试是大有帮助的,我们单独放到kliba.S文件中
.data
.global disp_str
disp_pos: .4byte ((80 * 6 + 0) * 2)
.text
.globl disp_str,disp_int
.code32
/***************************************************************************
* void disp_str(char * info);
***************************************************************************/
disp_str:
push %ebp
mov %esp, %ebp
mov 8(%ebp), %esi //字符串地址
mov disp_pos, %edi //读出显示位置
mov $0x0F, %ah //字符属性
cld
disp_start:
lodsb //将DS:ESI寻址的一个内存字节装入al
test %al, %al //两个操作数逻辑与运算,测试al是否为0
jz disp_end //结果为0则设置ZF零标志为1,跳转到2,结束显示
cmpb $0x0A, %al //是不是回车换行 al - 0xa = 0,则zf置1
jz disp_enter //是回车,zf=1,跳转
disp_char://显示一个字符
movw %ax, %gs:(%edi)
add $2, %edi
//cmp $((80 * 25 - 2) * 2), %edi//是否显示完一屏幕
jmp disp_start//显示下一字符
disp_enter://如果是enter,跳到下一行显示 ,每行显示80个字符,一个字符2字节
push %eax //eax入栈
movl %edi, %eax //edi ---> eax
movb $160, %bl //160---> bl 80-char * 2byte=160
divb %bl //160---> bl
andl $0xFF, %eax //eax = eax & 0xff 当前所在行数
incl %eax //eax = eax + 1 Goto next line
movb $160, %bl
mulb %bl //eax = eax * 160
movl %eax, %edi //eax---> edi
popl %eax
jmp disp_start
disp_end:
movl %edi, disp_pos//保存显示位置
popl %ebp
ret
/**-----------------------------------------------------------------
* Print num in AL
*------------------*/
DispAL:
push %ecx
push %edx
push %edi
mov (disp_pos), %edi
mov $0x0F, %ah
mov %al, %dl
shrb $4, %al
mov $2, %ecx
DispAL.begin:
and $0x0F, %al
cmp $9, %al
ja DispAL.1
add $'0', %al
jmp DispAL.2
DispAL.1:
sub $0x0A, %al
add $'A', %al
DispAL.2:
mov %ax, %gs:(%edi)
add $2, %edi
mov %dl, %al
loop DispAL.begin
mov %edi, (disp_pos)
pop %edi
pop %edx
pop %ecx
ret
/***************************************************************************
* void disp_int(unsigned long num);
***************************************************************************/
disp_int:
movl 4(%esp), %eax
shr $24, %eax
call DispAL
movl 4(%esp), %eax
shr $16, %eax
call DispAL
movl 4(%esp), %eax
shr $8, %eax
call DispAL
movl 4(%esp), %eax
call DispAL
movb $0x07, %ah
movb $'h', %al
pushl %edi
movl (disp_pos), %edi
movw %ax, %gs:(%edi)
addl $4, %edi
movl %edi, (disp_pos)
popl %edi
ret
相应的Makefile需要修改如下:
kliba.o:kliba.s
$(AS) -o kliba.o -a kliba.s
system: head.o kliba.o main.o
$(LD) $(LDFLAGS) -o system head.o kliba.o main.o
C中使用方法
void disp_str(char *info);
void disp_int(int num);
disp_str("How old are you?\n");
disp_int(0x12345678);