尝试在实模式下写一个micro kernel program 时,随着函数的增加而出现了N种意料之外的结果。

初步检查问题可能为:

  • 内存访问超过了1MB
  • 未完整的读入硬盘数据
  • 数据段、栈段未合理分配

调试结果

WDNMD!
结果三天的调试…
已放弃!

部分代码

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include "stdint.h"
#define COLOR_WHITE 0x07
#define KEYBOARD 0x00
#define E_KEYBOARD 0x10

/*
* 显示模式 低分辨率
* */
#define H_40_2516_T 0x00
#define H_80_2516_T 0x02
/*
* 显示模式 VGA
*
* */
#define VBE_640_400256 0x103
/*#################################调用汇编代码#########################################################################*/
void display_char(uint8_t ch, uint16_t row,uint16_t col); // 在第 row 行 第 col 列的位置显示一个字符 ch
void set_cursor(uint16_t row,uint16_t col);
void set_vmof_lowp(uint8_t mode); // 设置普通显示模式
uint8_t set_vmof_VBE(uint16_t mode); // 设置高分辨率模式
void write_pixel(uint16_t row,uint16_t col,uint16_t pixel); // 往指定位置写入一个指定颜色像素
uint16_t read_lba28hd_512B(uint16_t vofds,uint16_t offset,uint8_t f3,uint8_t f4,uint8_t f5,uint8_t f6); // 从指定硬盘读入512字节,并将数据放到指定物理内存
uint8_t read_byte(uint16_t vofds,uint16_t offset); // 从指定内存位置读取一字节
void flush(void); // 从程序加载器进入后,这个方法设置了程序的栈段、数据段、
uint16_t input_char(); // 读入键盘一个字符 低字节为字母ascll码,若低字节为 0 ,则高字节存放扫描码
void hlt(void ); // cpu进入低功耗状态
uint8_t get_bcd_year(void); // 获取bcd格式年

/*
* 获取与设置常用寄存器的值
* */
uint16_t get_DS();
uint16_t get_ES();
/////////////////////////////////////调用时出错了
void set_DS(uint16_t v); // ss
void set_ES(uint16_t v);
/*############################################################################################################*/
/*
* #################################################################
*
* */
char caseup(char c);
void input_c();
void init(uint8_t cx,uint8_t cy,uint8_t shade);
void spl_INT_display(uint16_t v,uint16_t row,uint16_t col);
/*
* ##################################################################
* */
// 程序入口
void ino() {
set_vmof_lowp(0x03);
init(9,9,'O');
input_c();
hlt();
}


void input_c(){
char col=0;
char row=0;
while (1){
short ax = input_char();
char al = ax & 0b11111111; // 获取ax 低8位
char ah = ax >> 8; //获取 ax的高8位
if (al==0x1b)break; // Esc按
switch (al) {
case 13: // 回车
set_cursor(++row,0);
col^=col;
break;
case 0x08: // 退格
display_char(0,row,--col);
break;
case 0: // 键盘扫描码
if (ah==72){ // 上
set_cursor(row==0?0:--row,col);
} else if (ah==80)//下
set_cursor(row==24?24:++row,col);
else if (ah==75) //左
set_cursor(row,col==0?0:--col);
else if (ah==77) //右
set_cursor(row,col==79?79:++col);
break;
default:
display_char(al,row,col);
init(9,9,al);
set_cursor(row,col==79?79:++col);
break;
}

}
}

char caseup(char c){
if (c>=97&&c<=122){
return c-32;
}
return c;
}
void init(uint8_t cx,uint8_t cy,uint8_t shade){
uint8_t v_start_x = 40-cx;
uint8_t v_start_y = 12 - cy/2;
for (uint8_t y = 0; y<cy; ++y) {
for (uint8_t x= 0; x < cx*2; ++x) {
display_char(shade,y+v_start_y,x+v_start_x);
++x;
display_char(' ',y+v_start_y,x+v_start_x);
}
}
}

void spl_INT_display(uint16_t v,uint16_t row,uint16_t col){

char svy;
char i=0;
char index = 0;
char cm [10];
while (1){
svy = v %10;
v /=10;
if (v==0&&svy==0)
break;
cm[index++] = svy;
i++;
// display_char(svy+0x30,4,i++);
}
i = 0;
for(--index;index>=0;index--){
display_char(cm[index]+0x30,row,col+i);
i++;
}
}
MBR
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
jmp main
msg db ''
stsave db 'save to disk...'
done db 'done'
wrm db 10 ; 读取扇区数量
diskaddr db 0xc8 ;扇区初始位置
gbl dw 0x1000;数据加载到这里 逻辑地址
proc dw 0x0000,0x1000


main:
;----------初始化-----
mov ax,0x7c0
mov ds,ax
mov ax,0xb800


mov es,ax
mov ax,0x00
mov ss,ax
xor sp,sp

;---------end-----
;call save_as_disk

;call exit
xor si,si
xor ch,ch
mov cl,[wrm]


lr:
call read_disk
mov al,[diskaddr]
inc al
mov [diskaddr],al
loop lr
call far [proc]
mov ax,0x1e00
mov ds,ax
;call show_by
call exit

save_as_disk: ; 参数bx[ds:bx],cx 压栈 dx ax bx
; 写扇区数量
mov al,0x01
mov dx,0x1f2
out dx,al

inc dx
mov al,0xc8 ; 第一百个扇区
out dx,al
inc dx
;--0x1f4----
mov al,0x00
out dx,al
inc dx
;-----0x1f5----
mov al,0x00
out dx,al
inc dx
; -------0x1f6----
mov al,0xe0 ; 1110 0000
out dx,al
;----------
inc dx
mov al,0x30
out dx,al
; 接下来判断硬盘是否可读
.waits:
in al,dx ;观察 0x1f7端口bit位状态
and al,0x88 ; 0x88=10001000
cmp al,0x08 ; 0000 1000
jnz .waits
mov dx,0x1f0
mov cx,256
.save: ;要写入的字数量在cx中
mov ax,'wh'
out dx,ax ; ds:bx
add bx,0x02
loop .save
call exit


show: ; 参数: [ds:bx]bx(地址) 和 cx(字节数) PS:将bx,ax和cx压栈
mov al,[ds:bx]
mov ah,0x07
mov [es:si],ax
add si,0x02
inc bx
loop show
ret


read_disk: ; 压栈: dx, bx ax cx-----------------------------------------------
push ds
push cx

xor bx,bx

; 读取扇区数
mov al,0x01
mov dx,0x1f2
out dx,al

inc dx
mov al,[diskaddr]
out dx,al
inc dx
;-----0x1f4
mov al,0x00
out dx,al
inc dx
;------0x1f5
mov al,0x00
out dx,al
inc dx
;-------0x1f6
mov al,0xe0
out dx,al
inc dx

mov al,0x20
out dx,al
.waits:
in al,dx ;观察 0x1f7端口bit位状态
and al,0x88 ; 0x88=10001000
cmp al,0x08 ; 0000 1000
jnz .waits
mov cx,256
mov dx,0x1f0

mov ax,[gbl]
mov ds,ax

.read:
in ax,dx
mov [ds:si],ax
add si,2
;mov byte [es:si],0x07
loop .read

pop cx
pop ds
;mov ds,ax

ret
;---------------------------------------------------------------------




show_by:
push ds
mov ax,[ds:gbl]
mov ds,ax
xor bx,bx
mov cx,512
call show
pop ds
call exit

exit:
hlt
jmp near exit

times 510-($-$$) db 0
dw 0xaa55
API
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126

[section .text]
extern _set_vmof_lowp
extern _display_char
extern _hlt
extern _get_bcd_year
extern _input_char
extern _set_cursor
extern _flush
extern _ino
extern _write_pixel
extern _read_byte

_flush:
mov ax,0x1e00
mov es,ax
mov ds,ax
xor di,di
xor si,si
xor bp,bp
xor sp,sp
mov ax,0x000
mov ss,ax
call _ino


_set_vmof_lowp:
push bp
mov bp,sp
sub sp,24
mov ah,0
mov al,[di+8]
int 0x10
mov sp,bp
pop bp
ret
_write_pixel:
push bp
mov bp,sp
sub sp,24
mov bh,0
mov dx,[di+8]
mov cx,[di+12]
mov al,[di+16]
mov ah,0x0c
int 0x10
mov sp,bp
pop bp
ret
_display_char: ; display_char(char ch,int x,int y)
push bp
mov bp,sp
sub sp,32
xor bh,bh
;----设置光标位置
mov ah,0x02
mov dh,[di+12]
mov dl,[di+16]
;mov al,[di+20]
int 0x10
;-------显示--------
mov ah,0x0a
mov cx,1
mov bl,0x04
mov al,[di+8]
int 0x10
; ------更新光标
;--------
mov sp,bp
pop bp
ret
_get_bcd_year:
push bp
mov bp,sp
sub sp,16
mov ah,0x04
int 0x1a
xor ah,ah
mov al,cl
mov sp,bp
pop bp
ret
_input_char:
push bp
mov bp,sp
sub sp,24
mov ah,0x00
int 0x16
mov sp,bp
pop bp
ret
_set_cursor:
push bp
mov bp,sp
sub sp,24
mov ah,0x02
mov dh,[di+8]
mov dl,[di+12]
;mov al,[di+20]
int 0x10
mov sp,bp
pop bp
ret


_read_byte:
push bp
push si
push ds
mov bp,sp
sub sp,48
mov ax,[di+12] ;偏移地址的值
mov si,ax
mov ax,[di+8] ; ppppp 不要用 si 来接参数
mov ds,ax
xor ah,ah
mov al,[ds:si]
mov sp,bp
pop ds
pop si
pop bp
ret

_hlt:
hlt
jmp _hlt

评论