Chinaunix首页 | 论坛 | 博客
  • 博客访问: 18681997
  • 博文数量: 7460
  • 博客积分: 10434
  • 博客等级: 上将
  • 技术积分: 78178
  • 用 户 组: 普通用户
  • 注册时间: 2008-03-02 22:54
文章分类

全部博文(7460)

文章存档

2011年(1)

2009年(669)

2008年(6790)

分类: C/C++

2008-03-20 17:06:11

1 开发语言分析

1. 1 汇编语言与C语言比较

传统BIOS程序的开发一般以汇编语言作为开发工具.它的优点是:代码精简,时间效率与空间效率高,比较适合于BIOS程序开发.缺点是:源程序代码冗长,使用大量标号,定义与区分工作量大,容易混淆,寄存器使用容易冲突,模块化设计功能差,软件的开发周期长.

C语言具备如下优点:模块化的设计语言易于实现算法,缩短软件的开发周期,提高软件的开发质量,便于维护、升级,易于实现图形化用户界面,实现仿真Windows界面操作,比较适合于系统软件的开发.其缺点是:对于Intel架构的C编译器,Borland C + +,代码的运行必须有操作系统的支持,因此,很难应用于BIOS程序开发.

目前,专门用于单片机及嵌入式系统开发的C语言已经成熟,然而还没有专门用于微机系统BIOS程序开发的C语言,使得BIOS程序的开发仍停留在使用汇编语言阶段.

然而, C语言产生的代码十分精炼,非常接近于汇编语言,如能脱离对操作系统的依赖,并与嵌入式汇编结合,更适合快速的BIOS开发.我们通过对Borland C + +产生代码进行分析找出了解决方案.

1.2 C语言编译代码分析

Borland C + +大部分函数使用了操作系统的功能调用,BIOS程序往往运行于操作系统装入之前,此时是无法调用操作系统功能的.因此,一般情况下,C语言编写的程序代码是不能脱离开操作系统支持而运行的.

BIOS程序一般都固化在ROM器件中.由于器件容量小的限制,要求BIOS程序的代码要尽可能地短,而用C语言设计的程序最短也要几KB.: Borland C + +空语句main ( ) { }在微模式下编译链接后产生的代码长度为4KB.

程序中一条有用的语句都没有,为什么会产生出4KB的代码呢?我们经过分析发现,在编译系统的lib目录下有多个扩展名为. obj的文件.其中c0 t. obj的机器码与空C程序产生的目标代码几乎一致,只是空C程序产生的可执行程序代码比c0 t. obj多了几条语句:

push bp

mov bp, sp

pop bp

ret

由此看来,任何C程序中都将包含lib目录下对应编译模式启动代码文件的代码.其中c0 t.obj为微模式的启动代码.只要将启动代码替换成适合BIOS程序设计的自编启动代码,我们称之为“BIOS启动代码”,即可实现用C语言进行BIOS程序的开发.

2 用C语言实现BIOS编程

2. 1 创建BIOS启动代码汇编源文件

扩展BIOS程序量一般在几十KB左右,可选用微模式来进行设计.其好处在于,微模式无堆栈段,可直接使用EXE2B IN. EXE. EXE类型的文件转换为. COM类型.. COM类型的文件无文件头PSP (程序段前缀) ,因此,便于作为固件进行固化.本题目的BIOS相关程序设计过程均采用了微模式.

为了降低代码长度,本文用自己设计的简短BIOS启动代码模块替换了Borland C + +的原有启动代码模块.方法为:c: \borlandc \ lib \ startup目录下原启动代码汇编原文件c0. asm更名为c0. bak,重新建立扩展BIOS启动代码汇编源文件c0. asm.

为了使BIOS启动代码适合于ISAPC I兼容的扩展BIOS设计,必须按PC I标准给出相应的PCI配置数据.例如,PCI为载体的扩展BIOS需在BIOS代码中包含网卡的类别号(020000H)、扩展BIOS大小及PC I.以下为扩展BIOS启动代码汇编源程序:

; c0. asm

; startup code for ISA & PCI Extended BIOS.

  Locals

;定义调用的C程序主函数为外部类型

extrn main: near

code seg segment byte public ’code’

  assume cs: code_seg, ds: code_seg

  org 0

start p roc p roc far

;扩展BIOS有效标志

  db 055h, 0aah

;累加和范围: ? =ROM器件容量/512

sum range db ?

jmp begin

  org 8

;扩展卡标识

  db ’PCI EXTANDED BIOS’

  org 18h

; PC I数据配置指针

  dw offset pcir

pcir  db ’PCIR’; PC I数据配置

venderid  dw 0000h; PCI厂商ID

deviceid  dw ?;用户自定设备ID

data pointer dw 0000h;产品数据指针

pci data len dw 0018h; PC I数据长度

pci version db 00h ; PCI版本号

;扩展卡类别为网卡

class  db 00h, 00h, 02h

map len  dw 0040h; BIOS代码长度

code ver  dw 0000h;代码数据版本

code type  db 00h;代码类型

indicator  db 80h;指示器

reserved  dw 0000h;保留字

;调用C程序主函数main ( )

begin:  call main

;返回BIOS调用程序

  retf

;累加和凑0单元,应根据计算给出该值:

; ? = 0 -所有字节之对256求余

check sum  db ?

start p roc  endp

code seg  ends

  end start p roc

2. 2 生成BIOS启动代码目标文件

c: \ borlandc \ lib \ startup目录中有一个文件build2c0. bat,它是用来生成启动代码obj文件的,使用方法:

build2c0 libtype [ srcdir [ objdir ] ]

其中: libtype可取clib ()winlib (Windows) , srcdir为原文件目录(默认“.) , objdir为产生的obj文件目录(默认“.).

首先将c: \borlandc \ lib目录下原有3 . obj文件更名为3 . bak,再运行如下可产生DOSstartup模块的命令:

build - c0clib c: \borlandc \ lib \ startup c: \borlandc \lib

这样便产生了适合BIOS编程的启动模块,我们称之为BIOS启动模块.此后,即可在Borland

C + +IDE环境下用C语言编写BIOS程序了.

2. 3 编程注意事项

a.编程时还要注意不能使用产生操作系统功能调用的函数,p rintf ( ).为此,需自己建立一些常用的标准设备输入输出函数,这些函数应尽量使用功能调用.

b.原有C语言的一些未调用操作系统功能的函数都可以使用.如头文件为bios. hstring. hmem. hctype. hsetjmp. hstdarg. h中定义的所有函数, . hstdlib. h中定义的部分函数.

c.变量类型除float类型不可用外,其余都可使用.这样在C程序中可以随意使用表达式进行数值运算,而不必考虑寄存器使用冲突问题.

d.对使用C语句实现有困难的操作,可在C语言中嵌入汇编代码,不过使用时要考虑寄存器冲突等问题,所以应尽量避免使用.

e.程序可按面向对象编程模式编写,但必须注意不要使用IO.

3 扩展BIOS编程典型示例

下面给出使用Borland C + +编写的扩展BIOS程序示例,程序全部都使用C语句.该程序可固化到一片BOOT ROM.启动时显示“HelloWorld!”后暂停,按任意键后继续引导系统.读者可根据实际需要编写诸如无盘工作站引导卡、系统还原卡和分区引导卡等各种扩展BIOS程序.

disp lay a character

Void dispchar ( char ch)

{AL= ch; AH = 0x0e; BX = 0;

geninterrup t (0x10) ;

}

Wai for keyboard hit

void pause ( void)

{ AH = 0; geninterrup t (0x16) ;

}

Disp layHello World! " void main ( void) { char

3 p =HelloWorld! " ; while (p ) { dispchar ( 3 p +

+ ) ; } pause ( ) ;

}

4 结论

通过构建适合BIOS数据结构的启动代码并回避操作系统的功能调用,采用现有C编译器Borland C + +实现BIOS程序开发是完全可行的.本方法已成功应用于系统还原卡、终端卡的开发,源程序代码几乎全部采用C语言完成,只有少量嵌入式汇编代码.与采用汇编语言开发相比,可在极短的时间内开发出高质量的BIOS代码.

阅读(3089) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~