板凳
chenzep [专家分:3640] 发布于 2006-04-21 23:27:00
我来发一个我自己写的一些宏给你,本来想整理一下再发的.
因为有些指令是80386+指令,所以,你的程序开头要加.386P伪指令,这个伪指令的用法如下:
.MODEL SMALL
.386P ;这个地方不能少了这个指令.
宏如下:
PUSH_REGS MACRO REG1,REG2,REG3,REG4,REG5,REG6,REG7,REG8
IFNB <REG1>
PUSH REG1
ENDIF
IFNB <REG2>
PUSH REG2
ENDIF
IFNB <REG3>
PUSH REG3
ENDIF
IFNB <REG4>
PUSH REG4
ENDIF
IFNB <REG5>
PUSH REG5
ENDIF
IFNB <REG6>
PUSH REG6
ENDIF
IFNB <REG7>
PUSH REG7
ENDIF
IFNB <REG8>
PUSH REG8
ENDIF
ENDM
POP_REGS MACRO REG1,REG2,REG3,REG4,REG5,REG6,REG7,REG8
IFNB <REG8>
POP REG8
ENDIF
IFNB <REG7>
POP REG7
ENDIF
IFNB <REG6>
POP REG6
ENDIF
IFNB <REG5>
POP REG5
ENDIF
IFNB <REG4>
POP REG4
ENDIF
IFNB <REG3>
POP REG3
ENDIF
IFNB <REG2>
POP REG2
ENDIF
IFNB <REG1>
POP REG1
ENDIF
ENDM
;1.1:将8位REG的低4位的二进制数值转化为相应的16进制的ASCII值
;1.2:这里假设REG的高4位为0,如果不是,则高4位清零
;2:任何一个8位的寄存器
;3:REG
BINTOHEX MACRO REG :=<AL>
AND REG,0FH
.IF REG>9
ADD REG,37H
.ELSE
ADD REG,30H
.ENDIF
ENDM
;1:显示一个ASCII字符
;2:随便一个ASCII数值
;4:改变的寄存器: AX,BX
DISP_ASCII MACRO ASC
IFNB <ASC>
MOV AL,ASC
ENDIF
MOV AH,0EH
MOV BL,07H ;前景色
MOV BH,00H ;页号
INT 10H
ENDM
;在原来的位置显示若干个字符
DISP_ASC_LOCATE MACRO ASC
PUSH_REGS AX,BX,CX
IFNB <ASC>
MOV AL,ASC
ENDIF
MOV AH,09H
MOV BL,07H
MOV BH,0
MOV CX,1 ;重复次数
INT 10H
POP_REGS AX,BX,CX
ENDM
;将BITS位的REG的数值以16进制的形式输出
;这个是一个共用的宏
;必须要.386指令,不然会出错
;改变的寄存器:AX,BX,CX
DISPREG MACRO REGBITS:REQ,REG:REQ
LOCAL DISPREG1
MOV CX,REGBITS
SHR CX,2 ;CX=CX/4,386指令
DISPREG1:
ROL REG,4 ;取REG的高4位输出,这个是386的指令,不然会出错
PUSH REG
BINTOHEX
DISP_ASCII
POP REG
LOOP DISPREG1
ENDM
;以16进制的形式显示一个8位数
;入口参数:任何一个8立即数、8位寄存器
;返回数值:无
;使用的寄存器: 无
DISP_8 MACRO NUM
PUSH_REGS AX,BX,CX
MOV AL,NUM
MOV AH,AL
DISPREG 8,AX
POP_REGS AX,BX,CX
ENDM
;1:以16进制的形式显示一个16位数
;2:任何一个16位立即数、16位寄存器
;3:无
;4:无
DISP_16 MACRO NUM
PUSH_REGS AX,BX,CX
MOV AX,NUM
DISPREG 16,AX
POP_REGS AX,BX,CX
ENDM
;1:以16进制的形式显示一个32位数
;2:任何一个32位立即数、32位寄存器
DISP_32 MACRO NUM
PUSH_REGS AX,BX,CX
MOV EAX,NUM
DISPREG 32,EAX
POP_REGS AX,BX,CX
ENDM
;1:获得光标的位置
;3:CH=光标的起始行,CL=光标的结束行
; DH=行,CL=列
;4: CX,DX
GET_CURSOR MACRO
PUSH_REGS AX,BX
MOV BH,0 ;页号
MOV AH,3
INT 10H
POP_REGS AX,BX
ENDM
;1:设置光标位置
;2:行号,列号
SET_CURSOR MACRO LINES,ARR
PUSH_REGS AX,BX,DX
MOV DH,LINES
MOV DL,ARR
MOV AH,2
MOV BH,0
INT 10H
POP_REGS AX,BX,DX
ENDM
;1:屏幕上卷
;2:上卷行数和子窗口的坐标
SCREEN_UP MACRO NUM,TOP,LEFT,BOTTOM,RIGHT
PUSH_REGS AX,BX,CX,DX
MOV AL,NUM ;上卷的行数
MOV AH,6
MOV BH,7 ;卷入行的属性
MOV CH,TOP;窗口的
MOV CL,LEFT
MOV DH,BOTTOM
MOV DL,RIGHT
INT 10H
POP_REGS AX,BX,CX,DX
ENDM
;1:清屏
SCRCLR MACRO
SCREEN_UP 25,0,0,24,79
ENDM
;1:实现换行功能
CRLF MACRO
PUSH_REGS AX,BX
DISP_ASCII 0DH
DISP_ASCII 0AH
POP_REGS AX,BX
ENDM
;1:获得字符串的长度
;2:DS(*)、字符串的首地址
;3:LEN
;4:CX,SI,AL
STR_LEN MACRO STR_ADDR,LEN
MOV SI,STR_ADDR
LODSB
MOV CX,0
.WHILE AL!=0
INC CX
LODSB
.ENDW
MOV LEN,CX
ENDM
;1:显示一个字符串
;2:DS(*)、字符串的首地址+字符串的长度,如果没有指定长度,那么以0为结束符号
DISP_STR MACRO STR_ADDR,LEN
PUSH_REGS AX,CX,SI
MOV SI,STR_ADDR
IFNB <LEN>
MOV CX,LEN
.WHILE CX>0
MOV AL,[SI]
DISP_ASCII
INC SI
DEC CX
.ENDW
ENDIF
IFB <LEN>
MOV AL,[SI]
.WHILE AL!=0
DISP_ASCII
INC SI
MOV AL,[SI]
.ENDW
ENDIF
POP_REGS AX,CX,SI
ENDM
;1:以16进制的形式显示一个字符串的二进制内容
;2:DS(*)、字符串的首地址+字符串的长度,如果没有指定长度,那么以0为结束符号
DISP_STR_16 MACRO STR_ADDR,LEN
PUSH_REGS DX,SI
MOV DX,LEN
MOV SI,STR_ADDR
.WHILE DX>0
LODSB
DISP_8 AL
DEC DX
.ENDW
POP_REGS DX,SI
ENDM
;1:获得一个字符但是不显示
;3:AL
;4:AX
GET_HIDE_CH MACRO
MOV AH,0
INT 16H
ENDM
;1:获得并显示一个字符
;3:AL
;4:AX
GET_CH MACRO
GET_HIDE_CH
DISP_8 AL
ENDM
;1:输入一个字符串
;2:字符串的首地址
GET_STR MACRO STR_ADDR
PUSH_REGS AX,CX,SI
MOV SI,STR_ADDR
MOV CX,0 ;CX是用来保存输入的有效字符的个数的,在这里只有回车和退格不是有效字符
GET_HIDE_CH
.WHILE AL!=0DH
.IF AL==08H ;处理退格键
.IF CX!=0
DISP_ASCII ;这个只是光标前移,字符还在
DISP_ASC_LOCATE ' ' ;清除字符
DEC CX ;有效字符减少一个
DEC SI
.ENDIF
.ELSE
MOV [SI],AL
DISP_ASCII
INC SI
INC CX
.ENDIF
GET_HIDE_CH
.ENDW
MOV [SI],0
POP_REGS AX,CX,SI
ENDM
;1:把十进制的STR字符串转化为数值保存在EAX中
;2: DS(*)、数字字符串的首地址,首地址不可以是EBX
;3:EAX
;5:在处理前要对STR进行扫描,保证STR的正确
STRD_TO_EAX MACRO STR_ADDR
PUSH_REGS SI,EBX
XOR EBX,EBX
XOR EAX,EAX
MOV SI,STR_ADDR
LODSB
.WHILE AL != 0
SUB AL,'0'
ADD EBX,EBX ;EBX=2*EBX
LEA EBX,[EBX*4+EBX] ;EBX=5*EBX
ADD EBX,EAX
LODSB
.ENDW
MOV EAX,EBX
POP_REGS SI,EBX
ENDM
;1:把16进制的STR字符串转化为数值保存在EAX中
;2: DS(*)、数字字符串的首地址
;3:EAX
;5:在处理前要对STR进行扫描,保证STR的正确
STRH_TO_EAX MACRO STR_ADDR
PUSH_REGS SI,BX
XOR EAX,EAX
MOV SI,STR_ADDR
.WHILE BYTE PTR [SI] != 0
MOV BL,BYTE PTR [SI]
INC SI
.IF BL>'9'
SUB BL,'a'-'9'+1
.ELSE
SUB BL,'0'
.ENDIF
SHL EAX,4
ADD AL,BL
.ENDW
POP_REGS SI,BX
ENDM
;判断一个字符串是否是合法的十进制字符串
;SI为入口地址
;返回AH=0是,=1不是
ISDEC MACRO
LOCAL NOTDEC,ISDEC_EXIT
PUSH SI,BX
MOV BL,AL
LODSB
.WHILE AL!=0
.IF AL>'9'
JMP NOTDEC
.ELSEIF AL<'0'
JMP NOTDEC
.ENDIF
LODSB
.ENDW
XOR AH,AH
JMP ISDEC_EXIT
NOTDEC:
MOV AH,1
ISDEC_EXIT:
MOV AL,BL
POP_REGS BX,SI
ENDM
;判断一个字符串是否是合法的16进制数
ISHEX MACRO
LOCAL ISHEX_EXIT,ISHEX_LOP
PUSH_REGS BX,SI
MOV BL,AL ;保存AL
XOR AH,AH
ISHEX_LOP:
LODSB
OR AL,AL
JZ ISHEX_EXIT
.IF AL>='0'
.IF AL<='9'
JMP ISHEX_LOP
.ENDIF
.ENDIF
.IF AL>='A'
.IF AL<='F'
JMP ISHEX_LOP
.ENDIF
.ENDIF
.IF AL>='a'
.IF AL<='f'
JMP ISHEX_LOP
.ENDIF
.ENDIF
MOV AH,1
JMP ISHEX_EXIT
ISHEX_EXIT:
MOV AL,BL
POP_REGS BX,SI
ENDM