用汇编语言做个图形界面程序框架(DOS蓝色风格)

软件开发大郭
0 评论
/
40 阅读
/
24917 字
13 2023-02

最近在做工控项目,用到的技术都是上个世纪的DOS系统,程序编译用汇编和C,

现在会用这个写程序的很少了,网上的教程不是少这里,就是缺那里,文章都是一通乱复制,

也不管对不对,导致网上很多汇编代码写DOS的程序,没有一个正常运行的,下面给个简单的案例,

从代码到编译整个完整的过程做一个记录和分享:

准备工具:

DOS运行环境:DOSBOX

用于模拟DOS环境的软件,你也可以用虚拟机来安装DOS
下载地址:https://www.dosbox.com

编辑器:Sublime Text4

你可以用其他任何你熟悉的文本编辑器
下载地址: http://www.sublimetext.com/

编译器:MASM

微软出的汇编器软件,网上搜下dos版本的masm下载。

界面设计

我的这个图形界面包括3个部分,分别是:欢迎界面、主界面以及结束界面。

程序主要分为2个,一个是主程序,一个是宏程序。

新建2个文件, 将对应的代码保存到相应的文件。

1. 主程序(main.asm)

;----------------------------------------------------------------------------
;	              S E G M E N T  STARTS
;----------------------------------------------------------------------------
include mnmacro.asm
data segment
scrmm	db 100 dup(?)
;----------------------------------------------------------------------------
;	              mainmenu name
;----------------------------------------------------------------------------
mainmenu1	db 'File'
mainmenu2	db 'Tool'
mainmenu3	db 'R8042'
mainmenu4	db 'Other'
mainmenu5	db 'Extra'
mainmenu6       db 'Help'
;----------------------------------------------------------------------------
;	             file's submenu name
;----------------------------------------------------------------------------
submenu11	db 'Save'
submenu12	db 'Open'
submenu13	db 'Exit'
;----------------------------------------------------------------------------
;	             Tool's submenu name
;----------------------------------------------------------------------------
submenu21	db 'I O'
submenu22	db 'ISA '
submenu23	db 'Memory'
;----------------------------------------------------------------------------
;	             R8042's submenu name
;----------------------------------------------------------------------------
submenu31	db 'A20'
submenu32	db 'reboot'
submenu33	db 'LED '
;----------------------------------------------------------------------------
;	             other's submenu name
;----------------------------------------------------------------------------
submenu41	db 'PCI '
submenu42	db 'Beep'
submenu43	db 'e820  '
;----------------------------------------------------------------------------
;	             extra's submenu name
;----------------------------------------------------------------------------
submenu51	db 'CMOS '
submenu52	db 'int'
submenu53	db '=== '
;----------------------------------------------------------------------------
;                    help's submenu name
;----------------------------------------------------------------------------
submenu61       db 'about'
submenu62       db '     '
submenu63       db '     '
;----------------------------------------------------------------------------
;		Welcome window information
;----------------------------------------------------------------------------
msgtitle	db 'System Controller'
msg1    db 'Please press Alt+F,Alt+T,Alt+R,Alt+O,Alt+E,Alt+H or ',19h,' to open the submenu.'
msg2	db 'Please press Enter (',11h,0c4h,0d9h,') to close the submenu.'
msg3	db 'Please press ',1bh,' or ',1ah,' to select the mainmenu.'
msg4	db 'Please press ',18h,' or ',19h,' to select the submenu.'
msg5	db 'Copyright 2023 Guoxin from Grabbyte.com.'
msg6	db 'Press any key to continue...'
msg7	db '                   '
;----------------------------------------------------------------------------
;		exit window information
;----------------------------------------------------------------------------
over	db 'Thank you for using...Good bye!!!!'
;----------------------------------------------------------------------------
;		other information
;----------------------------------------------------------------------------
escape	db 'Press ESC to exit                        E-mail:grabbyte@163.com'
text1	db 'This is a simple tool ru, there are io, memory, pci, isa, e820, '
text2	db 'a20, keyboard led, reboot and beep, etc. You can use this gadget'
text3	db 'to view their status, or to achieve a particular effect.'
text4   db '================================================================'
text5	db 'Thank you!'
text6	db '                                         ---powered by GuoXin'
sub11	db 'Select Save'
sub12	db 'Select Open'
sub13	db 'Select Exit'
sub21	db 'Select I O'
sub22	db 'Select ISA '
sub23	db 'Select Memory'
sub31	db 'Select a20'
sub32	db 'Select reboot'
sub33	db 'Select LED'
sub41	db 'Select PCI'
sub42	db 'Select Beep'
sub43	db 'Select e820'
sub51	db 'Select CMOS'
sub52	db 'Select int'
sub53	db 'Select === '
sub61   db 'Select about'
sub62   db 'Select      '
sub63   db 'Select      '
;----------------------------------------------------------------------------
mainnum db 1			;Main menu sequence number(主菜单序列号)
subnum	db ?			;Sub menu sequence number(子菜单序列号)
subshow db 0			;0 sub menu is not displayed(为0时子菜单不显示)
mainindex db ?			;Main menu character length(主菜单字符长度)
data ends
;----------------------------------------------------------------------------
code segment
assume cs:code,ds:data,es:data

	;extern memory1:far
	;extern io1:far
	;extern pci1:far
	;extern isa1:far
	;extern beep1:far
	;extern a201:far
	;extern e8201:far
	;extern key1:far
	;extern reboot1:far
	;extern cmos1:far
	;extern int1:far
	;extern about1:far
start:
	mov ax,data
	mov ds,ax
	mov es,ax
;----------------------------------------------------------------------------
;		Initializing screen start(初始化屏幕开始)
;----------------------------------------------------------------------------
	mov ah,0
	mov al,03h
	int 10h
;----------------------------------------------------------------------------
;               Initializing screen end(初始化屏幕结束)
;----------------------------------------------------------------------------
	showcur 1	;Hide cursor(隐藏光标)
;----------------------------------------------------------------------------
;		Start the main window drawing
;----------------------------------------------------------------------------
	drawwindow 1eh,0,0,24,79
	outputstr msgtitle,17,10,30,1fh
	outputstr msg1,73,15,5,17h
	changemenu 15,18,5,1eh
	changemenu 15,24,5,1eh
	changemenu 15,30,5,1eh
	changemenu 15,36,5,1eh
	changemenu 15,42,5,1eh
	changemenu 15,48,5,1eh
	changemenu 15,57,1,1eh
	outputstr msg2,46,16,5,17h
	changemenu 16,18,11,1eh
	outputstr msg3,43,17,5,17h
	changemenu 17,18,1,1eh
	changemenu 17,23,1,1eh
	outputstr msg4,42,18,5,17h
	changemenu 18,18,1,1eh
	changemenu 18,23,1,1eh
	outputstr msg5,33,13,5,1fh
	outputstr msg6,28,20,40,9eh
	outputstr msg7,19,9,28,93h
	outputstr msg7,19,11,28,93h
	setpos 10,28
	outputchar ' ',93h,1
	setpos 10,46
	outputchar ' ',93h,1
	mov ah,07h
	int 21h
	drawwindow 1eh,0,0,24,79
	drawwindow 70h,0,0,0,79
	drawwindow 70h,24,0,24,79
	setpos 1,0
	windowtandb 0d5h,0cdh,0b8h,1,0,80,1eh			;Top and bottom border
	mov al,2
draw:
	windowlandr 0b3h,al,0,80,1eh
	inc al
	cmp al,17h
	jne draw
	windowtandb 0c0h,0c4h,0d9h,23,0,80,1eh
	outputstr escape,64,24,3,70h             ;宽度64,24行,颜色70h,
;----------------------------------------------------------------------------
;		Start menu drawing
;----------------------------------------------------------------------------
	setpos 0,3
	outputstr mainmenu1,4,0,3,0fh
	outputstr mainmenu2,4,0,13,70h
	changemenu 0,13,1,74h
	outputstr mainmenu3,5,0,23,70h
	changemenu 0,23,1,74h
	outputstr mainmenu4,5,0,33,70h
	changemenu 0,33,1,74h
	outputstr mainmenu5,5,0,43,70h
	changemenu 0,43,1,74h
        outputstr mainmenu6,4,0,53,70h
	changemenu 0,53,1,74h
	setpos 0,3
;----------------------------------------------------------------------------
;		End of the main window and menu drawing
;----------------------------------------------------------------------------
	outputstr msg1,73,15,5,17h
	changemenu 15,18,5,1eh
	changemenu 15,24,5,1eh
	changemenu 15,30,5,1eh
	changemenu 15,36,5,1eh
	changemenu 15,42,5,1eh
	changemenu 15,48,5,1eh
	changemenu 15,57,1,1eh
	outputstr msg2,46,16,5,17h
	changemenu 16,18,11,1eh
	outputstr msg3,43,17,5,17h
	changemenu 17,18,1,1eh
	changemenu 17,23,1,1eh
	outputstr msg4,42,18,5,17h
	changemenu 18,18,1,1eh
	changemenu 18,23,1,1eh
	outputstr text1,63,3,5,1ah
	outputstr text2,64,4,5,1ah
	outputstr text3,56,5,5,1ah
	outputstr text4,64,6,5,1ah
	outputstr text5,29,7,5,1ah
	outputstr text6,64,8,5,1ah ;字符个数64,行8,开始列5,颜色属性1ah
;----------------------------------------------------------------------------
;		;Message receiving cycle(接受消息循环)
;----------------------------------------------------------------------------
input:
	mov	ah, 0
	int	16h             ;ah=字符的扫描码
	cmp	ah, 01h		;esc的扫描码是01h  
	jne	continue1
	call	exit
	jmp	input
continue1:
	cmp	ah, 4bh		;left的扫描码是4bh
	jne	continue2
	call	prsleft
	jmp	input
continue2:
	cmp	ah, 4dh		;right的扫描码是4dh
	jne	continue3
	call	prsright
	jmp	input
continue3:
	cmp	ah, 50h		;down的扫描码是50h  
	jne	continue4
	call	prsdown
	jmp	input
continue4:
	cmp	ah, 21h         ;key f
	jne	continue5   
	mov	ah, 02h
	int	16h
	and	al, 0fh
	cmp	al, 08h
	jne	continue5
	call	FAlt
	jmp	input
continue5:
	cmp	ah, 14h         ;key t
	jne	continue6
	mov	ah, 02h
	int	16h             ;取变换键当前状态,al=变换键当前状态
;-----------------------------------------------------------------------
	;前面我们已经提到Shift、Ctrl 、Alt、Num Lock、Scroll、Ins 和
	;Caps Lock这些键不具有ASCII码,但按动了它们能改变其它键所产生
	;的代码,那么如何能判断这些键按动与否呢?在键盘状态字节中高4位
	;指出各种键盘方式(Ins、Caps Lock、Num Lock、Scroll)是ON(1)
	;还是OFF(0);低4位表示Alt、Ctrl、leftShift、rightshift键是否按动。
	;这8个键有
	;时又被称为变换键。使用INT 16H的AH=2的功能即可得到这些键状态
	;的信息。
;-----------------------------------------------------------------------
	and	al, 0fh         ;高4位清零
	cmp	al, 08h         ;检查alt键
	jne	continue6
	call	talt
	jmp	input
continue6:
	cmp	ah, 13h         ;key r
	jne	continue7
	mov	ah, 02h
	int	16h
	and	al, 0fh
	cmp	al, 08h
	jne	continue7
	call	RAlt
	jmp	input
continue7:
	cmp	ah, 18h         ;key o
	jne	continue8
	mov	ah, 02h
	int	16h
	and	al, 0fh
	cmp	al, 08h
	jne	continue8
	call	OAlt
	jmp	input
continue8:
	cmp	ah, 12h         ;key e
	jne	continue9
	mov	ah, 02h
	int	16h
	and	al, 0fh
	cmp	al, 08h
	jne	continue9
	call	ealt
	jmp	input
continue9:
	cmp	ah, 23h         ;key h
	jne	continue10
	mov	ah, 02h
	int	16h
	and	al, 0fh
	cmp	al, 08h
	jne	continue10
	call	halt
	jmp	input
continue10:
	cmp	ah, 48h		;up
	jne	continue11
	call	prsup
	jmp	input
continue11:
	cmp	ah, 1ch		;enter
	jne	continue12
	call	prsenter
	jmp	input
continue12:
	jmp	input
; ===========================================================================
prsenter proc near			;Press the ENTER key
	cmp	subshow, 0
	jne	enter1
	call	prsdown
	ret
enter1:
	mov	al,mainnum
	push	ax
	mov	cl, 0ah
	mul	cl
	sub	ax, 07h
	mov	mainnum,al
	dec	mainnum
	writescr mainnum,scrmm
	inc	mainnum
	setpos 0,mainnum
	pop	ax
	mov	mainnum,al
	drawwindow 13h,22,4,22,50
	cmp	mainnum, 1
	jne	prsenter1
	cmp	subnum, 2
	jne	entersub12
	outputstr sub11,11,22,5,13h
entersub12:
	cmp	subnum, 3
	jne	entersub13
	outputstr sub12,11,22,5,13h
entersub13:
	cmp	subnum, 4
	jne	prsenter1
	outputstr sub13,11,22,5,13h
	call	exit
prsenter1:
	cmp	mainnum, 2
	jne	prsenter2

	cmp	subnum, 2
	jne	entersub22
	;call	io1
	jmp	start

entersub22:
	cmp	subnum, 3
	jne	entersub23
	;call	isa1
	jmp	start

entersub23:
	cmp	subnum, 4
	jne	prsenter2
	;call	memory1
	jmp	start

prsenter2:
	cmp	mainnum, 3
	jne	prsenter3
	cmp	subnum, 2
	jne	entersub32
	;call	a201
	jmp	start

entersub32:
	cmp	subnum, 3
	jne	entersub33
	;call	reboot1
	jmp	start

entersub33:
	cmp	subnum, 4
	jne	prsenter3
	;call	key1
	jmp	start

prsenter3:
	cmp	mainnum, 4
	jne	prsenter4
	cmp	subnum, 2
	jne	entersub42
	;call	pci1
	jmp	start

entersub42:
	cmp	subnum, 3
	jne	entersub43
	;call	beep1
	jmp	start

entersub43:
	cmp	subnum, 4
	jne	prsenter4
	;call	e8201
	jmp	start

prsenter4:
	cmp	mainnum, 5
	jne	prsenter5
	cmp	subnum, 2
	jne	entersub52
	;call	cmos1
	jmp	start

entersub52:
	cmp	subnum, 3
	jne	entersub53
	;call	int1
	jmp	start
entersub53:
	cmp	subnum, 4
	jne	prsenter5
	outputstr sub53,10,22,5,13h
prsenter5:
        cmp	mainnum, 6
	jne	prsenter6
	cmp	subnum, 2
	jne	entersub62
	;call	cmos1
	jmp	start

entersub62:
	cmp	subnum, 3
	jne	entersub63
	;call	int1
	jmp	start
entersub63:
	cmp	subnum, 4
	jne	prsenter6
	;outputstr sub53,10,22,5,13h
prsenter6:
	mov	subshow, 0
	ret
prsenter endp
; ===========================================================================
halt proc near					;H+Alt
	mov	al,mainnum
	mov	cl,0ah
	mul	cl
	sub	ax,07h
	mov	mainnum,al
	cmp	subshow, 1
	jne	hshow
	dec	mainnum
	writescr mainnum,scrmm
	inc	mainnum
hshow:
	readscr 52,scrmm
	submenu 52,submenu61,5,submenu62,5,submenu63,5,9
	changemenu 0,mainnum,5,70h
	changemenu 0,mainnum,1,74h
	mov	mainnum, 06h
	changemenu 0,53,4,0fh
	changemenu 2,54,6,0fh
	mov	subnum, 2
	mov	subshow, 1
	setpos 0,53
	ret
halt endp
; ===========================================================================
ealt proc near					;E+Alt
	mov	al,mainnum
	mov	cl,0ah
	mul	cl
	sub	ax,07h
	mov	mainnum,al
	cmp	subshow, 1
	jne	eshow
	dec	mainnum
	writescr mainnum,scrmm
	inc	mainnum
eshow:
	readscr 42,scrmm
	submenu 42,submenu51,5,submenu52,3,submenu53,3,9
	changemenu 0,mainnum,5,70h
	changemenu 0,mainnum,1,74h
	mov	mainnum, 05h
	changemenu 0,43,5,0fh
	changemenu 2,44,6,0fh
	mov	subnum, 2
	mov	subshow, 1
	setpos 0,43
	ret
ealt endp
; ===========================================================================
oalt proc near					;O+Alt
	mov	al,mainnum
	mov	cl,0ah
	mul	cl
	sub	ax,07h
	mov	mainnum,al
	cmp	subshow, 1
	jne	oshow
	dec	mainnum
	writescr mainnum,scrmm
	inc	mainnum
oshow:
	readscr 32,scrmm
	submenu 32,submenu41,4,submenu42,4,submenu43,6,9
	changemenu 0,mainnum,5,70h
	changemenu 0,mainnum,1,74h
	mov	mainnum, 04h
	changemenu 0,33,5,0fh
	changemenu 2,34,6,0fh
	mov	subnum, 2
	mov	subshow, 1
	setpos 0,33
	ret
oalt endp
; ===========================================================================
ralt proc near					;R+Alt
	mov	al,mainnum
	mov	cl,0ah
	mul	cl
	sub	ax,07h
	mov	mainnum,al
	cmp	subshow, 1
	jne	rshow
	dec	mainnum
	writescr mainnum,scrmm
	inc	mainnum
rshow:
	readscr 22,scrmm
	submenu 22,submenu31,3,submenu32,6,submenu33,4,9
	changemenu 0,mainnum,5,70h
	changemenu 0,mainnum,1,74h
	mov	mainnum, 03h
	changemenu 0,23,5,0fh
	changemenu 2,24,6,0fh
	mov	subnum, 2
	mov	subshow, 1
	setpos 0,23
	ret
ralt endp
; ===========================================================================
talt proc near					;T+Alt
	mov	al,mainnum
	mov	cl,0ah
	mul	cl
	sub	ax,07h
	mov	mainnum,al
	cmp	subshow, 1
	jne	tshow
	dec	mainnum
	writescr mainnum,scrmm
	inc	mainnum
tshow:
	readscr 12,scrmm
	submenu 12,submenu21,3,submenu22,4,submenu23,6,9
	changemenu 0,mainnum,5,70h
	changemenu 0,mainnum,1,74h
	mov	mainnum, 02h
	changemenu 0,13,4,0fh
	changemenu 2,14,6,0fh
	mov	subnum, 2
	mov	subshow, 1
	setpos 0,13
	ret
talt endp
; ===========================================================================
falt proc near					;F+Alt
	mov	al,mainnum
	mov	cl, 0ah
	mul	cl
	sub	ax, 07h
	mov	mainnum,al
	cmp	subshow, 1
	jne	fshow
	dec	mainnum
	writescr mainnum,scrmm
	inc	mainnum
fshow:
	readscr 2,scrmm
	submenu 2,submenu11,4,submenu12,4,submenu13,4,9
	changemenu 0,mainnum,5,70h
	changemenu 0,mainnum,1,74h
	mov	mainnum,01h
	changemenu 0,3,4,0fh
	changemenu 2,4,6,0fh
	mov	subnum, 2
	mov	subshow, 1
	setpos 0,3
	ret
falt endp
; ===========================================================================
prsup proc near					; Press the up arrow
	cmp	subshow,0
	jne	prsup2
	ret
prsup2:
	mov	al,mainnum
	push ax
	mov	cl,0ah
	mul	cl
	sub	ax,07h
	mov mainnum,al
	changemenu subnum,mainnum,8,70h
	inc	mainnum
	changemenu subnum,mainnum,1,74h
	pop ax
	mov	mainnum,al
	cmp	subnum,02h
	jne	prsuptop
	mov	subnum,04h
	jmp	prsup1
prsuptop:
	dec	subnum
prsup1:
	mov	al,mainnum
	push ax
	mov	cl, 0ah
	mul	cl
	sub	ax, 07h
	mov	mainnum, al
	changemenu subnum,mainnum,8,0fh
	pop ax
	mov	mainnum, al
	ret
prsup endp
; ===========================================================================
prsdown proc near				; Press the down arrow
	cmp	subshow,0
	jne	prsdown2
	cmp	mainnum,1
	jne	prsdown3
	call	falt
	jmp	prsdown8
prsdown3:
	cmp	mainnum,2
	jne	prsdown4
	call	talt
	jmp	prsdown8
prsdown4:
	cmp	mainnum,3
	jne	prsdown5
	call	ralt
	jmp	prsdown8
prsdown5:
	cmp	mainnum,4
	jne	prsdown6
	call	oalt
	jmp	prsdown8
prsdown6:
        cmp	mainnum,5   ;最坑爹的bug,这行代码自己手敲的和拷贝的效果竟然不一样!!!
	jne     prsdown7
	call    ealt
	jmp     prsdown8
prsdown7:
	call	halt
prsdown8:
	ret
prsdown2:
	mov	al,mainnum
	push	ax
	mov	cl, 0ah
	mul	cl
	sub	ax, 07h
	mov	mainnum, al
	changemenu subnum,mainnum,8,70h
	inc	mainnum
	changemenu subnum,mainnum,1,74h
	pop	ax
	mov	mainnum, al
	cmp	subnum, 04h
	jne	prsdownbot
	mov	subnum, 02h
	jmp	prsdown1
prsdownbot:
	inc	subnum
prsdown1:
	mov	al,mainnum
	push	ax
	mov	cl, 0ah
	mul	cl
	sub	ax, 07h
	mov	mainnum, al
	changemenu subnum,mainnum,8,0fh
	pop	ax
	mov	mainnum, al
	ret
prsdown endp
; ===========================================================================
prsright proc near				; Press the right arrow
	cmp	subshow,0
	je	prsright1
	call	prsrgtsub
	ret
prsright1:
	mov	al,mainnum
	push	ax
	mov	cl, 0ah ;00001010b
	mul	cl
	sub	ax, 07h ;00000111b
	mov	mainnum, al
	changemenu 0,mainnum,5,70h
	changemenu 0,mainnum,1,74h ;这里的1,代表一个字节的宽度,是主菜单的第一个红色的大写字母
	pop ax
	mov	mainnum, al
	cmp	mainnum, 06h  ;最后一个主菜单编号
	jne	prsright2
	mov	mainnum, 01h  ;第一个主菜单的编号
	jmp	prsright3
prsright2:
	inc	mainnum
prsright3:                    ;第二个主菜单
	cmp	mainnum, 1
	je	prsright4
	cmp	mainnum, 2
	je	prsright4
	cmp	mainnum, 5
	je	prsright5
	cmp	mainnum, 3
	je	prsright5
	cmp	mainnum, 4
	je	prsright5
	cmp     mainnum, 6
	je      prsright6
prsright4:
	mov	mainindex, 5
	jmp	prsright7
prsright5:
        mov     mainindex, 5
        jmp     prsright7
prsright6:
	mov	mainindex, 5
prsright7:
	mov	al,mainnum
	push	ax
	mov	cl, 0ah
	mul	cl
	sub	ax, 07h
	mov	mainnum, al
	changemenu 0,mainnum,mainindex,0fh ;当主菜单或者是子菜单被选中时,显示的黑底亮白的字体
	pop	ax
	mov	mainnum, al
	ret
prsright endp
; ===========================================================================
prsrgtsub proc near	;When the menu is opened to press the right arrow
	cmp	mainnum, 1
	jne	prsrgt1
	call	talt
	jmp	prsrgt6
prsrgt1:
	cmp	mainnum, 2
	jne	prsrgt2
	call	ralt
	jmp	prsrgt6
prsrgt2:
	cmp	mainnum, 3
	jne	prsrgt3
	call	oalt
	jmp	prsrgt6
prsrgt3:
	cmp	mainnum, 4
	jne	prsrgt4
	call	ealt
	jmp	prsrgt6
prsrgt4:
        cmp	mainnum, 5
	jne	prsrgt5
	call	halt
	jmp	prsrgt6
prsrgt5:
	call	falt
prsrgt6:
	ret
prsrgtsub endp
; ===========================================================================
prsleft proc near				;Press the left arrow
	cmp	subshow, 0
	je	prsleft1
	call	prslftsub
	ret
prsleft1:
	mov	al,mainnum
	push	ax
	mov	cl, 0ah
	mul	cl
	sub	ax, 07h
	mov	mainnum,al
	changemenu 0,mainnum,5,70h
	changemenu 0,mainnum,1,74h
	pop	ax
	mov	mainnum, al
	cmp	mainnum, 01h;第一个主菜单编号
	jne	prsleft2
	mov	mainnum, 06h;最后一个主菜单的编号,或者说是一共有6个主菜单
	jmp	prsleft3
prsleft2:
	dec	mainnum
prsleft3:
	cmp	mainnum, 1
	je	prsleft4
	cmp	mainnum, 2
	je	prsleft4
	cmp	mainnum, 5
	je	prsleft5
	cmp	mainnum, 3
	je	prsleft5
	cmp	mainnum, 4
	je	prsleft5
	cmp     mainnum, 6
	je      prsleft6
prsleft4:
	mov	mainindex, 5     ;E
	jmp	prsleft7
prsleft5:
	mov	mainindex, 5
	jmp	prsleft7
prsleft6:
	mov	mainindex, 5
prsleft7:
	mov	al,mainnum
	push	ax
	mov	cl, 0ah
	mul	cl
	sub	ax, 07h
	mov	mainnum, al
	changemenu 0,mainnum,mainindex,0fh
	pop	ax
	mov	mainnum, al
	ret
prsleft endp
; ===========================================================================
prslftsub proc near	;When the menu is opened by pressing the left arrow
;当菜单打开是按左箭头
      	cmp	mainnum, 1
	jne	prslft1
	call	halt
	jmp	prslft6
prslft1:
	cmp	mainnum, 2
	jne	prslft2
	call	falt
	jmp	prslft6
prslft2:
	cmp	mainnum, 3
	jne	prslft3
	call	talt
	jmp	prslft6
prslft3:
	cmp	mainnum, 4
	jne	prslft4
	call	ralt
	jmp	prslft6
prslft4:
        cmp     mainnum, 5
	jne     prslft5
	call    oalt
	jmp     prslft6
prslft5:
	call	ealt
prslft6:
	ret
prslftsub endp
; ===========================================================================
exit proc near				;Exit subpoc退出子程序
	drawwindow 1eh,0,0,24,79
	outputstr msgtitle,17,10,30,1fh
	outputstr over,34,15,21,1ch
	outputstr msg7,19,9,28,93h
	outputstr msg7,19,11,28,93h  ;总字数19,行11,颜色93h
	setpos 10,28
	outputchar ' ',93h,1
	setpos 10,46
	outputchar ' ',93h,1
	mov	ah, 07h
	int	21h
	mov	ah, 0
	mov	al, 03h
	int	10h
	mov	ah, 4ch
	int	21h
	ret
exit endp
; ===========================================================================
code ends

     end start

2. 功能宏调用程序(mnmacro.asm)

;设置光标位置
setpos macro top,left
mov ah,02h
mov bx,0
mov dh,top
mov dl,left
int 10h
endm
;修改菜单属性
changemenu macro top,left,width,attr
local chg
mov dl,left
chg:
setpos top,dl
mov bh,0
mov ah,08h
int 10h
mov bl,attr
mov cx,1
mov ah,09h
int 10h
inc dl
mov al,left
add al,width
cmp dl,al
jne chg
setpos top,left
endm
;绘制窗口
drawwindow macro attr,top,left,bottom,right
push ax
push bx
push cx
push dx
mov ah,06h
mov al,0
mov bh,attr
mov ch,top
mov cl,left
mov dh,bottom
mov dl,right
int 10h
pop dx
pop cx
pop bx
pop ax
endm
;绘制窗口上下边框
windowtandb macro l,m,r,top,left,width,attr
setpos top,left
outputchar l,attr,1
setpos top,left+1
outputchar m,attr,width-2
setpos top,left+width-1
outputchar r,attr,1
endm
;绘制窗口左右边框
windowlandr macro char,top,left,width,attr
setpos top,left
outputchar char,attr,1
setpos top,left+width-1
outputchar char,attr,1
endm
;输出字符
outputchar macro char,attr,num
push ax
mov bh,0
mov ah,09h
mov al,char
mov bl,attr
mov cx,num
int 10h
pop ax
endm
;输出字符串
outputstr macro str,num,top,left,attr
push ax
push bx
push bp
push cx
push dx
mov ah,13h
lea bp,str
mov cx,num
mov dh,top
mov dl,left
mov bh,0
mov al,1
mov bl,attr
int 10h
pop dx
pop cx
pop bp
pop bx
pop ax
endm
;绘制子菜单
submenu macro left,menu1,num1,menu2,num2,menu3,num3,width
local menu
drawwindow 70h,1,left,5,left+width
windowtandb 0dah,0c4h,0bfh,1,left,width+1,70h
mov al,2
menu:
windowlandr 0b3h,al,left,width+1,70h
inc al
cmp al,5;==================
jne menu
windowtandb 0c0h,0c4h,0d9h,5,left,width+1,70h
outputstr menu1,num1,2,left+2,0fh
changemenu 2,left+1,8,0fh
outputstr menu2,num2,3,left+2,70h
changemenu 3,left+2,1,74h
outputstr menu3,num3,4,left+2,70h
changemenu 4,left+2,1,74h
setpos 2,left+2
endm
;读取屏幕内容
readscr macro left,memory
local read
sub ax,ax
mov si,ax
read:
add ah,left
inc al
inc si
mov ch,ah
setpos al,ch
mov ah,08h
mov bh,0
int 10h
mov memory[si],al
mov memory[si+50],ah
mov ax,si
mov bl,10
div bl
cmp si,50
jne read
endm
;写入屏幕
writescr macro left,memory
local read
sub ax,ax
mov si,ax
read:
add ah,left
inc al
inc si
mov ch,ah
setpos al,ch
mov al,memory[si]
mov ah,memory[si+50]
mov dl,al
mov dh,ah
outputchar dl,dh,1
mov ax,si
mov bl,10
div bl
cmp si,50
jne read
endm
;设置光标属性
showcur macro show
push ax
push cx
mov ah,1
mov cl,0
mov ch,show
int 10h
pop cx
pop ax
endm

3. 编译程序

编译成OBJ文件

masm main.asm


一路按回车,用默认的

链接OBJ生成Exe

link main.obj

一路按回车,用默认的


生成的exe文件只有12KB,汇编就是不一样,程序很简洁

运行效果

运行命令

欢迎界面

主界面

子菜单

结束界面

    暂无数据