.MODEL SMALL
.STACK 100h
.DATA
; === 菜单与提示信息 ===
szMenuTitle DB 13,10,'========== FUNCTION SELECTION MENU ==========',13,10,'$'
szOption1 DB 13,10,' 1. Show Current Time ',13,10,'$'
szOption2 DB 13,10,' 2. Draw Rectangle ',13,10,'$'
szOption3 DB 13,10,' 3. Perform Math Calculation ',13,10,'$'
szOption4 DB 13,10,' 4. Reverse Input String ',13,10,'$'
szOption5 DB 13,10,' 5. Exit Program ',13,10,'$'
szMenuEnd DB 13,10,'===========================================',13,10,'$'
szPrompt DB 13,10,'Please choose an option (1-5): $'
szInvalid DB 13,10,'Invalid input! Press any key to retry...$'
; === 时间显示相关 ===
szTimeLabel DB 13,10,'Current Time is: $'
szTimeBuffer DB '00:00:00$',0
; === 图形绘制参数 ===
szTopBottom DB '----------------------------------------$' ; 宽度约40字符
szSideChar DB '|$'
szSpace DB ' $'
; === 数学运算提示 ===
szMathTitle DB 13,10,'===== MATHEMATICAL OPERATION =====',13,10,'$'
szOpSelect DB 13,10,'Choose operation: 1=Add 2=Sub 3=Mult 4=Div : $'
szInputFirst DB 13,10,'Enter first number: $'
szInputSecond DB 13,10,'Enter second number: $'
szResultOut DB 13,10,'Result = $'
szRemainOut DB 13,10,'Remainder = $'
szZeroDivErr DB 13,10,'Error: Division by zero not allowed!$'
; === 字符串处理相关 ===
szStrTitle DB 13,10,'===== STRING REVERSAL =====',13,10,'$'
szStrPrompt DB 13,10,'Input string (max 50 chars): $'
szOrigShow DB 13,10,'Original: $'
szRevShow DB 13,10,'Reversed: $'
; === 缓冲区与变量 ===
InputBuf DB 51, ?, 51 DUP('$')
RevBuf DB 51 DUP('$')
numA DW ?
numB DW ?
resultVal DW ?
tempDigit DW ?
; === 返回提示 ===
szReturnKey DB 13,10,13,10,'Press any key to continue...$'
.CODE
; 主入口
START:
MOV AX, @DATA
MOV DS, AX
BEGIN_LOOP:
CALL ClearScreen
CALL ShowMainMenu
MOV AH, 01h ; 读取按键
INT 21h
CMP AL, '1'
JE TIME_MODULE
CMP AL, '2'
JE GRAPH_MODULE
CMP AL, '3'
JE MATH_MODULE
CMP AL, '4'
JE STRING_MODULE
CMP AL, '5'
JE QUIT_PROGRAM
; 错误输入处理
MOV AH, 09h
LEA DX, szInvalid
INT 21h
CALL WaitAnyKey
JMP BEGIN_LOOP
; ===================================
; 功能1:显示系统时间
; 使用 INT 21H AH=2Ch 获取时间
; ===================================
TIME_MODULE:
CALL ClearScreen
LEA DX, szTimeLabel
MOV AH, 09h
INT 21h
MOV AH, 2Ch ; 获取系统时间
INT 21h ; CH=小时, CL=分钟, DH=秒
; 处理小时
MOV AL, CH
CALL BinToTwoAscii
MOV szTimeBuffer[0], AL
MOV szTimeBuffer[1], AH
; 处理分钟
MOV AL, CL
CALL BinToTwoAscii
MOV szTimeBuffer[3], AL
MOV szTimeBuffer[4], AH
; 处理秒
MOV AL, DH
CALL BinToTwoAscii
MOV szTimeBuffer[6], AL
MOV szTimeBuffer[7], AH
LEA DX, szTimeBuffer
MOV AH, 09h
INT 21h
CALL WaitAnyKey
JMP BEGIN_LOOP
; ===================================
; 功能2:绘制矩形框
; 在指定位置画边框
; ===================================
GRAPH_MODULE:
CALL ClearScreen
MOV AH, 02h ; 设置光标位置 (Row=6, Col=15)
MOV BH, 0
MOV DH, 6
MOV DL, 15
INT 10h
LEA DX, szTopBottom ; 上边框
MOV AH, 09h
INT 21h
MOV CX, 8 ; 侧边高度
DRAW_SIDES_LOOP:
PUSH CX
MOV AH, 02h ; 左竖线
MOV DL, 15
INT 10h
LEA DX, szSideChar
MOV AH, 09h
INT 21h
MOV AH, 02h ; 右竖线
MOV DL, 15 + 40 - 1
INT 10h
LEA DX, szSideChar
MOV AH, 09h
INT 21h
MOV AH, 0Ah ; 换行
MOV DL, 13
MOV AH, 02h
INT 21h
POP CX
LOOP DRAW_SIDES_LOOP
MOV AH, 02h ; 下边框定位
MOV DH, 6 + 9
MOV DL, 15
INT 10h
LEA DX, szTopBottom
MOV AH, 09h
INT 21h
CALL WaitAnyKey
JMP BEGIN_LOOP
; ===================================
; 功能3:数学运算模块
; 支持四则运算
; ===================================
MATH_MODULE:
CALL ClearScreen
LEA DX, szMathTitle
MOV AH, 09h
INT 21h
LEA DX, szOpSelect
MOV AH, 09h
INT 21h
MOV AH, 01h
INT 21h
CMP AL, '1'
JE DO_ADD
CMP AL, '2'
JE DO_SUB
CMP AL, '3'
JE DO_MUL
CMP AL, '4'
JE DO_DIV
JMP MATH_MODULE
DO_ADD:
CALL GetTwoNumbers
MOV AX, numA
ADD AX, numB
MOV resultVal, AX
CALL ShowResultOnly
JMP MATH_END
DO_SUB:
CALL GetTwoNumbers
MOV AX, numA
SUB AX, numB
MOV resultVal, AX
CALL ShowResultOnly
JMP MATH_END
DO_MUL:
CALL GetTwoNumbers
MOV AX, numA
MUL numB
MOV resultVal, AX
CALL ShowResultOnly
JMP MATH_END
DO_DIV:
CALL GetTwoNumbers
CMP numB, 0
JE DIV_ERROR
MOV AX, numA
XOR DX, DX
DIV numB
MOV resultVal, AX
MOV tempDigit, DX
CALL ShowQuotientAndRemainder
JMP MATH_END
DIV_ERROR:
LEA DX, szZeroDivErr
MOV AH, 09h
INT 21h
CALL WaitAnyKey
JMP MATH_MODULE
MATH_END:
CALL WaitAnyKey
JMP BEGIN_LOOP
; ===================================
; 功能4:字符串反转
; 输入后反向输出
; ===================================
STRING_MODULE:
CALL ClearScreen
LEA DX, szStrTitle
MOV AH, 09h
INT 21h
LEA DX, szStrPrompt
MOV AH, 09h
INT 21h
LEA DX, InputBuf
MOV AH, 0Ah
INT 21h
; 显示原文
LEA DX, szOrigShow
MOV AH, 09h
INT 21h
MOV SI, OFFSET InputBuf + 2
MOV CL, InputBuf[1]
MOV CH, 0
CALL PrintStringAtSI
; 反转
LEA SI, InputBuf + 2
LEA DI, RevBuf
ADD DI, CX
DEC DI
MOV BX, CX
SHR BX, 1 ; 循环次数 = 长度 / 2
REVERSE_CHAR_LOOP:
MOV AL, [SI]
MOV AH, [DI]
MOV [SI], AH
MOV [DI], AL
INC SI
DEC DI
DEC BX
JNZ REVERSE_CHAR_LOOP
; 添加结束符
MOV BYTE PTR [DI+1], '$'
; 显示反转结果
LEA DX, szRevShow
MOV AH, 09h
INT 21h
LEA DX, RevBuf
MOV AH, 09h
INT 21h
CALL WaitAnyKey
JMP BEGIN_LOOP
; ===================================
; 子程序定义区
; ===================================
; 清屏
ClearScreen PROC
MOV AH, 06h
MOV AL, 0
MOV BH, 07h
MOV CX, 0
MOV DX, 184Fh
INT 10h
RET
ClearScreen ENDP
; 显示主菜单
ShowMainMenu PROC
LEA DX, szMenuTitle
MOV AH, 09h
INT 21h
LEA DX, szOption1
INT 21h
LEA DX, szOption2
INT 21h
LEA DX, szOption3
INT 21h
LEA DX, szOption4
INT 21h
LEA DX, szOption5
INT 21h
LEA DX, szMenuEnd
INT 21h
LEA DX, szPrompt
INT 21h
RET
ShowMainMenu ENDP
; 等待任意键
WaitAnyKey PROC
LEA DX, szReturnKey
MOV AH, 09h
INT 21h
MOV AH, 07h
INT 21h
RET
WaitAnyKey ENDP
; 二进制转ASCII(0~99)
BinToTwoAscii PROC
XOR AH, AH
MOV BL, 10
DIV BL
ADD AL, '0'
ADD AH, '0'
RET
BinToTwoAscii ENDP
; 获取两个数字
GetTwoNumbers PROC
CALL ReadNumberFromUser
MOV numA, BX
CALL ReadNumberFromUser
MOV numB, BX
RET
GetTwoNumbers ENDP
; 读取一个数
ReadNumberFromUser PROC
PUSH AX
PUSH CX
PUSH DX
MOV BX, 0
READ_LOOP:
MOV AH, 01h
INT 21h
CMP AL, 13
JE DONE_READ
CMP AL, '0'
JB READ_LOOP
CMP AL, '9'
JA READ_LOOP
SUB AL, '0'
MOV AH, 0
PUSH AX
MOV AX, BX
MOV CX, 10
MUL CX
MOV BX, AX
POP AX
ADD BX, AX
JMP READ_LOOP
DONE_READ:
POP DX
POP CX
POP AX
RET
ReadNumberFromUser ENDP
; 仅显示结果
ShowResultOnly PROC
LEA DX, szResultOut
MOV AH, 09h
INT 21h
MOV AX, resultVal
CALL PrintAXAsDecimal
RET
ShowResultOnly ENDP
; 显示商和余数
ShowQuotientAndRemainder PROC
LEA DX, szResultOut
MOV AH, 09h
INT 21h
MOV AX, resultVal
CALL PrintAXAsDecimal
LEA DX, szRemainOut
MOV AH, 09h
INT 21h
MOV AX, tempDigit
CALL PrintAXAsDecimal
RET
ShowQuotientAndRemainder ENDP
; 打印AX中的十进制数
PrintAXAsDecimal PROC
PUSH AX
PUSH BX
PUSH CX
PUSH DX
MOV CX, 0
MOV BX, 10
PRT_LOOP:
XOR DX, DX
DIV BX
PUSH DX
INC CX
OR AX, AX
JNZ PRT_LOOP
OUT_LOOP:
POP DX
ADD DL, '0'
MOV AH, 02h
INT 21h
LOOP OUT_LOOP
POP DX
POP CX
POP BX
POP AX
RET
PrintAXAsDecimal ENDP
; 打印SI指向的CL长度字符串(手动添加换行)
PrintStringAtSI PROC
PUSH AX
PUSH CX
PUSH SI
PRINT_SILoop:
MOV AL, [SI]
MOV DL, AL
MOV AH, 02h
INT 21h
INC SI
LOOP PRINT_SILoop
POP SI
POP CX
POP AX
RET
PrintStringAtSI ENDP
; 程序退出
QUIT_PROGRAM:
MOV AH, 4Ch
INT 21h
END START
最新发布