【我所認知的BIOS】->汇编语言之宏汇编2
By LightSeed
2010-2-3
在上一节详细讲了宏汇编的理论,那这节来聊聊我在仿写ADU的时候用的一些宏汇编的例子吧。有了下面这个串宏汇编,那么程序的可维护性就高了很多,在添加或者删除这个工具的功能的时候,就显得格外简单和高级语言写出来的工具的健壮性可媲美。这也是我对这个工具感觉做的最好的地方之一,和大家share一下。(不过这个算法是仿照award bios中setup下面的菜单来做的。)
代码如下:
1、主要宏
;-------------------------------------------------------------------------
;******* By LightSeed
;******* lightseed@163.com
;******* 2010-2-3
;
;Macro name: CreateMainItem
;input :
; Name :Name of this item
; MorS :mainmenu or submenu
; IBT :item belong to (which item 1,2..8 etc)
; ORD :item order in its menus 0~8 for main item,9~255 for subitem
; MaxSubNum :the highest value of submenu
; MaxSubMenuStrNum:the number of submenu's string.
; MaxStrNum :the maximal number of strings to display
; IsHighLit :set if it is choosed
; SubitemNum :the number of subitem
; Attrib :attribute of this main item
; X_axis :row number in window under DOS
; Y_axis :line number in window under DOS
; _item_str :offset address of strings to display
;
;ex :
; Name =xxxx will be created ' xxxx_item lable near'
; MorS =00h means mainmenu,
; 01h submenu
; others reserved
; IBT when it is mainmenu,IBT no use
; when it is submenu,IBT belong to 1--F1,2--F2...etc
; ORD =00h default to order
; =01h means the first order
; ...
; MaxSubNum =04h means it can be defined 4 subitems at most
; MaxStrNum =05h means it can be defined 5 strings to be displayed
; IsHighLit =01H have been highlight
; SubitemNum =0h have no subitem
; Attrib =00011110b blackgroud:blue front:yellow
; X_axis
; Y_axis
; _item_str xxxxxh offset address
;
;remark: there will be define a set of structure ,4 data will be filled soon
; this macro must be defined with Create_String and EndCreateItem_Str.
; because,there are some parameters should be put
; ex:
; CreateMainItem xx,xx,xx,xx,...
; Create_String xx_label
; db x,x,x,x,x,x
; EndCreateItem_Str
;-------------------------------------------------------------------------
CreateMainItem macro Name,MorS,IBT,ORD,MaxSubNum,MaxSubMenuStrNum, MaxStrNum,IsHighLit,SubitemNum,Attrib,X_axis,Y_axis,_item_str
Check_Input_Error Name,%IBT,%MaxSubNum,%MaxStrNum,%MorS
Create_Item_Content Name, %MorS, %IBT, %ORD, %MaxSubNum,/
%MaxStrNum,%IsHighLit,%Attrib,%Item_Num,%SubitemNum
db Name&_MorS
db Name&_IBT
db Name&_ORD
db Name&_MaxSubNum
db MaxSubMenuStrNum
db Name&_MaxStrNum
db Name&_IsHighLit
db Name&_SubitemNum
db Name&_Attrib
db Name&_Str_Itm_Num ;Display_String_Num,will be place here
db Y_axis ;Yaxis
db X_axis ;Xaxis
dw offset Name&_Str ;offset address Display string
endm;CreateMainItem
上面的这个宏的功能主要是创建一个结构体,这个结构体是对每个出现在工具中的item做各个属性的定义的。可以说,这个结构体是画工具界面的主要参数。对于这个创建结构体的宏,内部结构又分三个部分。
①对输入的各个参数进行校验,如果出错则输出错误提示信息,编译停止。
②经过第一个宏的check后,说明输入数据均是有效的,进而调用另外一个宏来创建一些数据(因为实际输入的数据有些需要进行计算后才填入到结构体中去。这里计算出来的数据均是全局常量,方便在第三部分直接用数据。如果这个定义的数据不放在第二部分的话,那么第三部分在引用这些常量的时候就出错。)。
③经过前面两个宏的处理后,对应的数据定义好了(在第二部分中处理好的),直接定义结构体内容。
在这个宏里,我们充分看到了在上一节中说的那些宏嵌套和参数引用等问题。
2、检验(数据)宏
代码如下:
;******* By LightSeed
;******* lightseed@163.com
;******* 2010-2-3
Check_Input_Error macro item_Name,Item_Bel_To,Max_Sub_Num, Max_Str_Num,main_or_sub
;----- if item_Name not declared, then force error -----
ifb <item_Name>
%out
%out item_Name do not declared!
.ERR
ENDIF
;----- if IBPT not declared, then force error -----
ifb <Item_Bel_To>
%out
%out where the item belong and point do not declared!
.ERR
ENDIF
;----- if MaxSubNum not declared, then force error -----
ifb <Max_Sub_Num>
%out
%out MaxSubNum not declared!
.ERR
ENDIF
;----- if MaxStrNum not declared, then force error -----
ifb <Max_Str_Num>
%out
%out MaxStrNum not declared!
.ERR
ENDIF
;----- if main_or_sub not declared, then force error -----;
ifb <main_or_sub>
%out
%out main_or_sub not declared!
.ERR
ENDIF
endm;Check_Input_Error
对于这个宏,其实我只想说明一点,应该说把上一节的条件汇编用在了这里。
3、处理(数据)宏
代码如下:
;-------------------------------------------------------------------------
;******* By LightSeed
;******* lightseed@163.com
;******* 2010-2-3
;
;
;
;Macro name: Create_Item_Content
;input :
;
; Name =xxxx will be created ' xxxx_item label near'
; MorS =00h mainmenu
; =01h submenu
; IBT =00h means mainmenu,
; 01h submenu
; others reserved
; ORD =00h default to order
; =01h means the first order
;
; MaxSubNum =04h means it can be defined 4 subitems at most
; MaxStrNum =05h means it can be defined 5 strings to be displayed
; IsHighLit =01H have been highlight
; Attrib =00011110b blackgroud:blue front:yellow
;-------------------------------------------------------------------------
Create_Item_Content macro Name,MorS,IBT,ORD,MaxSubNum,MaxStrNum,IsHighLit,Attrib,CurrentItemNum,SubitemNum
_MorS = MorS
_IBT = IBT
_ORD = ORD
_MaxSubNum = MaxSubNum
_MaxStrNum = MaxStrNum
;qe'=' gt'>' lt'<' ge'>=' le'<='
;when you create a main menu,counter ++
if _MorS eq 0
_TotalMainMenuNum = _TotalMainMenuNum+1 ;
endif
;if _TotalMainMenuNum > the highest value then force error
if _TotalMainMenuNum gt MaxMainMenuNum
%out
%OUT The number of mainmenu too large
.ERR
endif
;if _MaxSubNum > the highest value then force error
if _MaxSubNum gt MaxSubMenuNum
%out
%OUT The number of submenu too large
.ERR
endif;_MaxSubNum gt MaxSubMenuNum
;if order > the highest value then force error
if _MorS eq 0 ;if mainmenu?
if _ORD gt MaxMainMenuNum
%out
%OUT The order of mainmenu too large
.ERR
endif; _ORD gt MaxMainMenuNum
else ;_MorS eq 0 ;it is submenu
if _ORD gt MaxSubMenuNum
%out
%OUT The order of submenu too large
.ERR
endif; _ORD gt MaxSubMenuNum
endif;_MorS eq 0
public Name&_item
Name&_item Label Near ;create the item
ifndef Name&_MorS
Name&_MorS equ MorS
endif
ifndef Name&_IBT
Name&_IBT equ IBT
endif
ifndef Name&_ORD
Name&_ORD equ ORD
endif
ifndef Name&_MaxSubNum
Name&_MaxSubNum equ MaxSubNum
endif
ifndef Name&_MaxStrNum
Name&_MaxStrNum equ MaxStrNum
endif
ifndef Name&_IsHighLit
Name&_IsHighLit equ IsHighLit
endif
ifndef Name&_SubitemNum
ifb <SubitemNum>
Name&_SubitemNum equ 0
else
Name&_SubitemNum equ SubitemNum
endif;<SubitemNum>
endif
ifndef Name&_Attrib
Name&_Attrib equ Attrib
endif
ifndef Name&_Str_Itm_Num
Name&_Str_Itm_Num equ Name&_str_&CurrentItemNum
endif
;define offset item
OffsetAddress&CurrentItemNum equ offset Name&_item
endm;Create_Item_Content
这个宏,看上去很代码很多,其实看清庐山真面目了以后就感觉很简单。那么我就简单说说看这个宏的时候,应该注意的几个问题:
①用“=”定义的是一个变量,它可以在宏计算的时候当一个变量来使用,可以被重新赋值。而用“EQU”定义的是一个常量,是不能够加减重新赋值的。
②“&”是个连接符,它的作用其实就是为了让变量或者常量看起来,或者说操作起来更直观易懂。
③条件汇编在这个宏里用的最多。总的来说,其实这个宏都只是定义了一些常量来供主宏来定义结构体罢了。从这个角度上看,这些定义的常量就类似于函数的输出了。只是中间的逻辑稍微不那么直观而已。
关于宏汇编的东西,我就和大家讲这么两个小节,而且主要是围绕我写的那个工具中用到的宏汇编来写的。(不过我想能够融会贯通这些宏的使用的话,也应该够用了吧。呵呵。。。毕竟人家BIOS也就用了这些嘛。)如果您对此还有什么疑问的话,我们可以再深入交流。