汇编语言菜单系统.docx
- 文档编号:26847023
- 上传时间:2023-06-23
- 格式:DOCX
- 页数:29
- 大小:428.46KB
汇编语言菜单系统.docx
《汇编语言菜单系统.docx》由会员分享,可在线阅读,更多相关《汇编语言菜单系统.docx(29页珍藏版)》请在冰豆网上搜索。
汇编语言菜单系统
实训一光标漫游
⒈问题
在25行80列的显示屏内,通过按键“→、←、↑、↓”来改变光标的位置,如按“→”键则光标往右侧走一列,按“↑”键则光标往上走一行的位置,最终通过“Esc”结束程序。
⒉边界问题
要处理好特殊情况:
①光标在第一行,再按“↑”键时;②光标在第一列,再按“←”键时;③光标在第25行,再按“↓”键时;④光标在第80列,再按“→”键时。
⒊边界问题处理
采用折返的方式:
①光标在第1行,再按“↑”键时进到第25行;②光标在第1列,再按“←”键时进到第80行;③光标在第25行,再按“↓”键时进到第1行;④光标在第80列,再按“→”键时时进到第1列。
⒋实验基础
1读键:
用int16h的0号功能调用
掌握扫描码和字符码的区别
Movah,0
Int16h
;返回AH=扫描码,AL=字符码
2定位光标:
用int10h的2号
3清屏:
用int10h的6号(或7号)功能调用
MOVAH,6
MOVBH,04h
MOVAL,0
MOVCX,0
MOVDX,184fh
INT10h
④相关键的扫描码和字符码
EnterKeyEQU1c0dh
EscKeyEQU010bh
UpCursorEQU4800h
LeftCursorEQU4b00h
RightCursorEQU4d00h
DownCursorEQU5000h
5.算法
do
{
定位光标
读键
if(al==特殊键)
{
if(ah==左光标键)
修正列值}
elseif(ah==右光标键)
{修正列值}
elseif(ah==上光标键)
{修正行值}
elseif(ah==下光标键)
{修正行值}
}
}
while(al!
=Esc)
6.实验步骤
运行“光标漫游示例.EXE”了解需求。
①编一小程序获得特殊键“→、←、↑、↓”“Esc、回车”等的扫描码和Asc码值,并记录以备后用;
②写出光标漫游的算法(保存,用类自然语言描述,用word,与同学、老师讨论算法的可行性与正确性);
③在②初步正确的基础上,编写汇编语言源程序;
④如发现算法问题,用调试器调试;
7.要点
光标如何根据所按的键跟随?
折返如何处理?
x=(x+1)%25;
8.该实验与大实验的关联性
请大家体会主菜单“实验蓝本.exe”的处理过程。
附件:
实验报告内容
①问题
②设计要点及算法
③源程序
④运行结果
⑤使用调试器状况和经验总结
⑥使用体会和总结
实训一光标漫游改进
根据跳跃表法(另称跳转表,教材p180)来改进光标漫游程序。
键:
“→、←、↑、↓”、“Esc”、“Enter”、“ALT_X”(退出循环)。
其中对“Esc”、“Enter”键暂不做任何处理。
1.掌握跳转表的原理
MenuJmpTbldwEnterkey,IsEnterKey
dwEscKey,IsESCKey
dwUpCursor,IsUpCursor
dwLeftCursor,IsLeftCursor
dwRightCursor,IsRightCursor
dwDownCursor,IsDownCursor
上述跳转表共6项,每项为:
键值(扫描码+字符码)、处理的入口地址
2.掌握跳转表的总控程序(入口地址为标号)
……
ContinueReadKey:
……
MOVBX,offsetMenuJmpTbl
MOVCX,6
YesNoKeyEqual:
cmpax,[bx]
jeIsKeyEqual
addbx,4
loopYesNoKeyEqual
jmpContinueReadKey
IsKeyEqual:
movbx,[bx+2]
jmpbx
……
IsEnterKey:
…..
IsESCKey:
…..
3.掌握跳转表的总控程序(入口地址为子程序)
……
ContinueReadKey:
……
MOVBX,offsetMenuJmpTbl
MOVCX,6
YesNoKeyEqual:
cmpax,[bx]
jeIsKeyEqual
addbx,4
loopYesNoKeyEqual
jmpContinueReadKey
IsKeyEqual:
movbx,[bx+2]
call bx
jmpContinueReadKey
……
IsEnterKeyproc
……;不能用无条件转移指令等跳出子程序
ret
IsEnterKeyendp
…..
IsESCKeyproc
…..
实训二色彩处理及方框显示
⒈问题
在显示屏显示各种形状的方框(大小不一)。
┬──┬ ┌───┐
│ │ │ │
└──┘ └───┘等
实验中可用1,2,3,4,…,9,0等来代替,如:
3
6
6
6
9
⒉实验基础
1注意颜色查看conio.c中的函数:
颜色名称
值
颜色名称
值
BLACK
0
DARKGRAY
8
BLUE
1
LIGHTBLUE
9
GREEN
2
LIGHTGREEN
10
CYAN
3
LIGHTCYAN
11
RED
4
LIGHTRED
12
MAGENTA
5
LIGHTMAGENTA
13
BROWN
6
YELLOW
14
LIGHTGRAY
7
WHITE
15
⒊实验步骤
①编写小程序,用int10h的0eh功能来显示字符串;
②写出显示方框的算法(注意模块化);
③在②初步正确的基础上,编写汇编语言源程序;
④如发现算法问题,用调试器调试;
4完成本实验的实验报告。
4.算法
ShowBox(左上角坐标,右下角坐标,方框串,颜色)
{//显示第一行
//for显示中间行
//显示最后一行
}
ShowALineOfBox(左上角坐标,宽度,方框子串,颜色)
{//定位光标
//设置颜色并显示第一字符
//for显示中间字符
//显示最后一字符
}
5.实验关键
先实现ShowALineOfBox子程序,编程时考虑模块化的概念,处理参数的传递方法(先采用变量或寄存器的方式来传送)。
参考下列案例:
boxstrdb'123'
….
movah,0eh
movbl,0fh
movbh,0
moval,boxstr
int10h
movcx,10
moval,boxstr+1
showrepchar:
int10h
loopshowrepchar
moval,boxstr+2
int10h
注意上述代码和算法的关系。
6.直接写屏来显示的原理和方法
①对显示缓冲区的简单介绍
②对字符属性字节的简单介绍
③一个简单的例子
④直接写屏的案例
movdi,0b800h
moves,di
xordi,di;di=0,表示是0行0列的位置,如要显示在(5,8)的位置,di该何值?
movsi,offsetboxstr
movah,0fh
lodsb
stosw
movcx,10
lodsb
repstosw
lodsb
stosw
7.直接写屏的方框显示算法
ShowBox(左上角坐标,右下角坐标,方框串,颜色)
{//根据左上角坐标计算显示缓冲区地址,用子程序定义
//显示第一行
//for显示中间行
//显示最后一行
}
※可用+160的方法来处理下一行的起始位置,编程时用进栈和退栈指令来保存和还原
ShowALineOfBox(左上角坐标的起始地址,宽度,方框子串,颜色)
{
//设置颜色并显示第一字符
//for显示中间字符
//显示最后一字符
}
8.参数表的标准传递方式
ShowBox(左上角坐标,右下角坐标,方框串,颜色)
C语言参数传递模型:
把参数自右向左压入栈;在函数执行时用相应的参数数据。
子程序的参数入栈:
示例
Movax,颜色
Pushax
Movax,方框串地址
Pushax
Movax,右下角坐标
Pushax
Movax,左下角坐标
Pushax
…
showBoxproc
;子程序里代码
Movbp,sp
;[bp+2]左下角坐标
;[bp+4]右下角坐标
;[bp+6]串地址
;[bp+8]颜色
……
ret8
showBoxEndp
实训三主菜单的显示与选择
⒈问题
在屏幕上显示下列菜单,并能通过“→、←、↑、↓”来切换菜单项。
如初始显示为:
当按“→”键时,变成:
再按“→”键时,变成:
系统的先期实现按下列约定实施:
“Enter”确认菜单项或弹出子菜单;
“ESC”返回子菜单;
“→、←”主菜单项间切换;
“↑、↓”子菜单项间切换;
完成上述功能后,再对相应的按键进行功能的扩展。
⒉实验基础
本实验是实验一加颜色处理的方法来实现,所以本次实验的基础大家都具备。
运行“主菜单演示.exe”体会编程。
⒊实验原理
如何来实现菜单项的切换是本实验的技巧。
假定我们用一变量mi来指向当前选中的菜单,当按“→”键时,我们用“未选中的颜色”来定位重写“File”的串,使菜单变成:
然后是按键处理后,mi修正为1,然后用“选中的颜色”定位重写“Edit”,
变成上图的效果,实现了菜单项的动态切换。
⒋实验步骤
①在word上写出算法(其中主菜单的字符串数据放在数组中)。
②思考……
③提问
④算法正确后再编写程序。
⒌主菜单的显示算法
实训四菜单数据的组织
⒈问题
看实例“实验蓝本.exe”,思考菜单数据如何组织?
数据的组织与菜单显示之间怎么关联?
⒉菜单的逻辑结构图
⒊数据的组织结构
//菜单结构体定义
MenuStrustruc
SubMenuCountdb?
;子菜单的数目
SubMenuWidthdb?
;子菜单的宽度
SubMenuAddrdw?
;子菜单数据结构地址
MenuStrWidthdb?
;菜单项字符串长度
MenuStrAddrw?
;菜单项的字符串地址
MenuStruends
⒋菜单数据的组织
看“Menu2014.asm”
⒌理解菜单数据组织与程序的关系
⒍改进实训练三
①掌握结构体变量和指针的使用;
②在一循环中用结构体变量或指针来访问相关参数;
③在循环中加入打印字符串语句,显示出主菜单;
④加入颜色等,实现主界面。
实训五菜单系统的设计
整个菜单系统的设计需要进一步抽象。
设计时要考虑扩展性和通用性的问题:
菜单数据的改变,如我们的实例中只有3层菜单,如果把菜单数据增加到4、5等层次菜单时,你所编写的程序代码在只允许修改菜单数据,而不允许修改所有的函数的情况下,你的设计是否能达到此目标?
要实现上述目标,必须对处理过程进行抽象。
菜单系统总体上应该如此实施:
①显示主菜单;②读键(暂定有效键为“→、←、↑、↓、Esc、Enter”);③处理有效键。
④反复执行②③。
特别要注意整个程序中只有一处读键的地方。
由于菜单系统选择的层次性,我们必须对菜单选择的(中间)过程进行有效保存,以便回溯。
如当我们进入主菜单项的“Options”→“Compiler”→“Compiler”的子菜单,当我们用“Esc”键时可以回退到“Compiler”状态,从“Compiler”还可以回退到“Options”状态。
为有效管理这种选择状态,我们必须对选择状态加以保存。
我们采取以下结构体来保存选择的历史信息(C语言):
typedefstructMenuSelectStru{
ShortIntMenuIndex,MenuTotal;//选择菜单中的哪项
MenuItemStru*MenuAddr;//对应主菜单/子菜单的数据结构地址
PCHAR_INFOAddrOfSaveText;//备份下拉菜单区域的空间
boolPullDownMenu;//下拉菜单有否显示
ShortIntleft,top,right,bottom;
};
也可考虑用下列历史结构:
(把left,top,right,bottom内容放入AddrOfSaveText指向的空间中)
HistoryStrustruc
MenuIndexdb0;选择菜单中的哪项
MenuTotaldb0;菜单的项数
MenuAddrdw0;对应主菜单/子菜单的数据结构地址
AddrOfSaveTextdw0;备份下拉菜单区域的空间
PullDownMenudb0;下拉菜单有否显示
HistoryStruends
考虑到本实验的最大菜单级数为三级,我们可定义含3个元素的数组来保存历史的选择信息(如果考虑3级以上,则应该把数组的元素个数适当加大)。
//选择的历史缓冲区
CHAR_INFOSecondSave[300],FirstSave[300];
MenuSelectStruHis[3]={{0,8,MainMenu,false,0,0,0,0},
{0,0,0,FirstSave,false,0,0,0,0},
{0,0,0,SecondSave,false,0,0,0,0}};
有了选择的历史缓冲区,可以提高我们的抽象级别:
该层菜单的选中项 该层菜单的总数 该层菜单的首地址
MenuIndex
MenuTotal
MenuAddr
…
0
8
MainMenu
0
1
2
3
4
MenuLayer指向当前菜单选择的层次
当我们操作菜单时,可以围绕“选择的历史缓冲区”来管理即可,如:
当我们在主菜单的选择时定位到“Options”时,历史数据为:
MenuIndex
MenuTotal
MenuAddr
…
5
8
MainMenu
当拉下“Options”的子菜单进入到“子菜单的选择”时,历史数据为:
MenuIndex
MenuTotal
MenuAddr
…
5
8
MainMenu
0
5
OptSubM
当在“Options”的子菜单下操作时,我们改变MenuIndex的值即可,如选中“Options”子菜单下的“Linker”项,MenuIndex应该为1:
MenuIndex
MenuTotal
MenuAddr
…
5
8
MainMenu
1
5
OptSubM
His[Layer].MenuAddr:
表示主(或子)菜单数组的首地址
对应MainMenu[x].SubMenuItemAddr变成
His[Layer].MenuAddr[His[Layer].MenuIndex].SubMenuAddr
此时Layer=0;
如何得到子菜单的起始显示列值?
答:
MainMenuCol[His[0].MenuIndex]
显示区备份与还原编程有关函数(在conio.c中):
获得显示区的属性信息:
voidgettextinfo(structtext_info*_r)
把_source指向的数组的内容还原到区域(_left,_top)、(_right,_bottom):
voidputtext(int_left,int_top,int_right,int_bottom,PCHAR_INFO_source)
把显示区域(_left,_top)、(_right,_bottom)中的内容备份到_target指向的数组:
voidgettext(int_left,int_top,int_right,int_bottom,PCHAR_INFO_target)
实训六浏览DbaseⅢ表数据
⒈问题
了解DbaseⅢ的表结构,掌握一种通用的数据组织原理,并把数据在工作区中显示。
⒉实验基础
①了解DbaseⅢ的表结构及定义;
②对照DbaseⅢ结构用二进制编辑器FlexHex.exe软件来查看其物理组织原理;
③掌握高级语言中的“int”等类型的数据组织方式(注意高字节放在高地址);
④用小程序分步读出文件头、字段信息等;
⑤最后实施表数据的浏览。
附件:
DBF文件格式分析
DBF数据表文件的结构分析:
DBF文件由两部分组成,
第一部分是结构描述,即文件头信息;共32个字节(0~31)
第二部分是表本身的内容,该部分又分为两个部分:
前一部分是表的结构说明,共32个字节具体的内容见下表1
后一部分是字段描述区,从第32个字节开始到十六进制结束字符0x0D。
具体包括内容见表2
解读:
低字节在前,所以要取字段总数时,应该用如下方法:
记录总数 = 第4个字节+2561次方*第5字节+2562*第6字节+2563*第7字节
注意:
字段名 以ASCII码方式存放,最大长度是10个字符,若字段名长度少于10个字符则以空字符(0x00)填充
字段类型 以ASCII码方式存放,1个字符,其值为
Fieldtype:
C – Character
Y – Currency
N – Numeric
F – Float
D – Date
T – DateTime
B – Double
I – Integer
L – Logical
M –Memo
G –General
C – Character(binary)
M – Memo(binary)
P – Picture
+ – Autoincrement(dBaseLevel7)
O – Double(dBaseLevel7)
@ – Timestamp(dBaseLevel7)
DBF数据表文件的结构结束标志为"0x0D",占1个字节。
对于VFP表文件从"0x0D"所在的字节开始的263B用于描述自由表或数据库表的相关信息(若为自由表则取值全为零)。
其VFP表文件长度=32(文件头)+32*字段个数+1(结束标志)+263。
然后是数据部分记录1、记录2……记录n
各记录均为定长格式,以ASCII码方式顺序存放。
每个记录的第一个字节是删除标志,若记录被删除,则该字节为0x2A即"*";否则为0x20即空格。
各记录间无分隔符
整个文件的结束标志为0x1A,位于最后一个记录之后的一个字节中。
struct dbf_head { /* DBF文件头结构 */
char vers; /* 版本标志*/
unsigned char yy,mm,dd; /* 最后更新年、月、日 */
unsigned long no_recs; /* 文件包含的总记录数 */
unsigned short head_len,rec_len; /* 文件头长度,记录长度 */
char reserved[20]; /* 保留 */
};
struct field_element{ /* 字段描述结构 */
char field_name[11]; /* 字段名称 */
char field_type; /* 字段类型 */
unsigned long offset; /* 偏移量 */
unsigned char field_length; /* 字段长度 */
unsigned char field_decimal; /* 浮点数整数部分长度 */
char reserved1[2]; /* 保留 */
char dbaseiv_id; /* dBASE IV work area id */
char reserved2[10]; /*
char production_index;
};
/************************************************************************************
COMMENTS:
DBF文件的总体格式
a.数据记录部分,紧随结构描述部分,以ASCII码方式顺序存放,结束标志为1AH(即
文件结束标志),每条记录的首字节为删除标志,20H表示有效,2AH表示已被删除,
字段值间无分隔符,记录亦无结束标记.
b.结构描述部分,位于文件首部,以二进制方式存放,结束标志为0DH.长度
为32*(数据库的字段个数+1(即库整体描述))+1(0DH结束标志)
************************************************************************************/
#include
#include
#include
//DBF 文件头结构//即库整体描述表,共32个字节
typedef struct tagDBFFILEHEADER
{
unsigned chardfMark;//0x03h 或 0x80h(有MEMORY字段)0
unsigned chardfYear,dfMmonth,dfDay;//依次为年月日,二进制1-3
unsigned longdfRecordCount;//总记录个数,低位字节在前4-7
unsigned shortdfHeaderLength;//文件头长度=第9字节值*256+第8字节值8-9
unsigned shortdfRecordLength;//记录长度=第11字节值*256+第10字节值10-11
unsigned chardfReserved[20];//保留12-31
}DBFFILEHEADER;
//DBF 字段结构//即字段描述表,32个字节/字段
typedef struct tagDBFINFOHEADER
{
uns
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 汇编语言 菜单 系统