kernel.asm
[BITS 32]
[GLOBAL start] ;我们必须导出start这个入口,以便让链接器识别 ,
[EXTERN _ya_main] ;用到本文件外定义的函数 在kernel.c
jmp start
start:
call _ya_main ;调用C
jmp $
kernel.c
#include "..\include\graph.h"
#include "..\include\pciprobe.h"
unsigned short color ;
void ya_main()
{
//写字的颜色
color = rgb_mix( 0 , 255 , 255 ) ;
unsigned int x = 250 ;
unsigned int y = 50 ;
if(PciBusProbe()){
ya_draw_chars( 250, 5, "北桥存在" , color) ;
}
//ya_draw_chars( 250, 50, "北桥存在" , color) ;
PciProbe() ;
//ya_draw_4bit_bmp(500 , 20 , 0x68400) ;
netcardprobe() ;
// 显示内存中0x400120开始的数值,以16进制0x显示,每行八个,共三行
char *b = (char *) 0x400120;
show_data( b , 8 , 0 , 40 , color );
b = b+0x20; //下一行八个双字 8X4 = 32 = 0x20
show_data( b , 8 , 0 , 60 , color );
netinitial();
}
graph.c
#include "..\include\graph.h"
unsigned int * addr = (int *)0x10050 ;
// 颜色合成函数
unsigned short rgb_mix( unsigned char r , unsigned char g , unsigned char b )
{
union{
unsigned int color ;
struct{
unsigned char b : 5 ;
unsigned char g : 6 ;
unsigned char r : 5 ;
}sa;
}ua;
ua.sa.r = r >> 3 ;
ua.sa.g = g >> 2 ;
ua.sa.b = b >> 3 ;
return ua.color ;
}
// 画点函数
void draw_dot( unsigned int x , unsigned int y , unsigned short color )
{
// 取得显卡地址
//unsigned short *video_addr ;
unsigned int mid = *addr ;
unsigned short * video_addr = (unsigned int *)mid ;
// 计算点的偏移量
unsigned int offset = y * 800 + x ;
// *( video + offset ) = color ;
*( video_addr + offset ) = color ;
}
// 显示英文
void ya_draw_english( unsigned int x , unsigned int y , unsigned int addr_in_font , unsigned short color )
{
unsigned char *english_font = ( unsigned char * )(0x10400 + addr_in_font * 16) ;
int ta = y ;
int tb = x ;
unsigned char font_char ;
for (int tc = 0; tc < 16; tc++) { // 一个英文 16 行
for (int td = 7; td >= 0; td--) { // 一行一个字节 八位
tb++ ;
if ((font_char = english_font[ tc ] & (1 << td))) {
draw_dot(tb, ta, color);
}
}
ta++; // 显示下一行
tb = x;
}
}
// 显示汉字
void ya_draw_chinese( unsigned int x , unsigned int y , unsigned int addr_in_font , unsigned short color )
{
unsigned char *chinese_font = ( unsigned char * )(0x11400 + addr_in_font * 32) ;
int ta = y ;
int tb = x ;
unsigned char font_char ;
for (int tc = 0; tc < 16; tc++) { // 一个汉字16行
for (int te =0 ; te < 2; te++){ // 一行两个字节 十六位
for (int td = 7; td >= 0; td--) {
tb++ ;
if ((font_char = chinese_font[ tc*2 + te ] & (1 << td))) {
draw_dot(tb, ta, color);
}
}
}
ta++; // 显示下一行
tb = x;
}
}
// 显示字符串
void ya_draw_chars( int x, int y, char *chars , unsigned short color)
{
while (*chars){
char ch = *chars++ ;
if (ch & 0x80){ //是中文
char cl = *chars++ ;
cl -= 0xa1;
ch -= 0xa1;
int addr = 94*ch + cl ;
ya_draw_chinese( x , y , addr , color);
x += 16 ;
}
else{ //是英文
int addr = ch ;
ya_draw_english(x , y , addr , color);
x += 8 ;
}
}
}
void ya_draw_4bit_bmp(unsigned int x ,unsigned int y ,unsigned int addr)
{
int color [16] = {0x0,0x8000,0x400,0x8400,0x10,0x8010,0x410,0x8410,0xc618,0xf800,0x7e0,0xffe0,0x1f,0xf81f,0x7ff,0xffff} ;//调色板值
int lx = x ; //每行要从这里开始,保留这个值
int * ta = (int *)(addr+0xa) ; //位图数据开始偏移量 在第0xa字节共四字节
int * tb = (int *)(addr+0x22) ; //位图数据长 在第0x22字节共四字节
int * width = (int *)(addr+0x12) ; //位图宽 在第0x12字节共四字节
int * height = (int *)(addr+0x16) ; //位图高 在第0x16字节共四字节
int td ; //一行要读的字节数
int te ; //补几个字节
int tf ; //图宽
tf = * width ;
switch(tf%8){ //计算一行要读的字节数td 要补的字节数te
case 0:
td = tf/2 ;
te = 0 ;
break ;
case 1:
td = (tf+1)/2 ;
te = 3 ;
break ;
case 2:
td = tf/2 ;
te = 3 ;
break ;
case 3:
td = (tf+1)/2 ;
te = 2 ;
break ;
case 4:
td = tf/2 ;
te = 2 ;
break ;
case 5:
td = (tf+1)/2 ;
te = 1 ;
break ;
case 6:
td = tf/2 ;
te = 1 ;
break ;
case 7:
td = (tf+1)/2 ;
te = 0 ;
break ;
}
int tc = td + te ;
char * string = (char *)(addr+*ta+*tb-tc) ; //数据从最末端-32字节处开始
for(int i=0 ; i< *height ;i++){
for(int j=0 ; j<td ;j++){
unsigned char ch = *string ; //一个字符有八位,要分别取得其高四位和低四位
unsigned char c1 = ch>>4; //取得高四位
unsigned int pa = color[c1] ; //取得调色板的对应颜色值
if(pa!=0xffff){ //如果是白色,跳过不显示
draw_dot(x , y , pa ) ;
}
unsigned char c2 = ch & 0xf; //取得低四位
pa = color[c2] ; //取得调色板的对应颜色值
if(pa!=0xffff){
draw_dot(x , y , pa ) ;
}
string++ ;
x++ ;
}
string = string + te -tc*2; //必须是四个字节宽,补X个字节,然后后退XX字节
x = lx ;
y++;
}
}
//读内存值,n是要显示的个数
void show_data( char *string ,int n , int x , int y , unsigned short color )
{
unsigned int pos ;
for( int j = 0 ; j < n ; ++j){
ya_draw_chars( x , y ,"0x", color ) ; //以0x开关表示16进制值
x += 16;
for( int i = 0 ; i < 4 ; ++i ){
unsigned char ch = *(string +3) ; //32位存放顺序是颠倒的
unsigned char lo4,hi4;
hi4 = (ch & 0xf0) >> 4;
lo4 = ch & 0x0f;
if ( hi4 <0xa )
{pos = hi4 +0x30 ; } //0的ASCII值为0x30
else
{ pos = hi4 +0x57 ; } //a+0x57 = 0x61,正是小a的值
ya_draw_english( x , y , pos , color ) ;
x += 8 ;
if ( lo4 <0xa )
{pos = lo4 +0x30 ; } //0的ASCII值为0x30
else
{ pos = lo4 +0x57 ; } //a+0x57 = 0x61,正是小a的值
ya_draw_english( x , y , pos , color ) ;
x += 8 ;
*string--;
}
x += 16 ; //多加一个8,中间有空格好看
string = string + 8; //前面减了4再加8相当于加4,指向下一个双字,*string = *string + 8 是向其指向的值加8
}
}