目的:
掌握宏的编写与调用,以及其展开的过程,注意区分宏和过程的不同之处。
要求:
(1)编写宏指令
(2)在主程序中调用宏指令
(3)实现主程序与宏指令的参数传递
(4)练习编写宏并通过.LST文件查看宏的展开情况。
题目1:
用宏实现摄氏温度到华氏温度的转换
实验要求:定义一个宏,实现输入摄氏温度转换为华氏温度转换公式为F=(9/5)*C+32,并存在EAX中。
提示:在进行公式计算时,先用摄氏温度C*9,再加上取整因子2,再进行除5的运算,即整个公式演变为F=(C*9+2)/5+32
;用宏实现摄氏温度到华氏温度的转换
;作者:KUN.A.A
;date:2022/05/20
.386
.MODEL FLAT
ExitProcess PROTO NEAR32 stdcall, dwExitCode:DWORD
INCLUDE io.h
cr EQU 0dh ; carriage return character
LF EQU 0ah ; linefeed character
.STACK 4096 ; reserve 4096-byte stack
.DATA ; reserve storage for data
Prompt1 BYTE CR,LF,"This program will convert a Celsius "
BYTE "temperature to the Fahrenheit scale",cr,Lf,Lf
BYTE "Enter Celsius temperature: ",
Value BYTE 10 DUP (?)
Answer BYTE CR,LF,"The temperature is"
Temperature BYTE 6 DUP (?)
BYTE " Fahrenheit",cr,Lf,0
.CODE ; start of main program code
calFahrenheit MACRO Tem
atoi Tem ; 转为整数
imul ax,9 ; C*9
add ax,2 ; 加取整因子2到被除数
mov bx,5 ; 除数5
cwd ; 字扩展
idiv bx ; C*9/5
add ax,32 ; C*9/5 + 32
ENDM
_start:
output Prompt1 ; 提示输入摄氏度
input Value,10 ; 输入ASCII字符
calFahrenheit Value
itoa Temperature,ax ; 结果转为ASCII
output Answer ; 输出提示与最后结果
INVOKE ExitProcess, 0 ; exit with return code 0
PUBLIC _start ; make entry point public
END ; end of source code
题目2:
写一个Max1宏定义,该宏有两个参数,第一个参数为存储器中一个串的地址,该串元素为字长度,第二个参数为串的元素个数。该宏代码将求解这个串中元素最大值,最大值放在AX。
;用宏实现求串中元素最大值
;作者:KUN.A.A
;date:2022/05/20
.386
.MODEL FLAT
ExitProcess PROTO NEAR32 stdcall, dwExitCode:DWORD
INCLUDE io.h
cr EQU 0dh ; carriage return character
LF EQU 0ah ; linefeed character
.STACK 4096 ; reserve 4096-byte stack
.DATA ; reserve storage for data
Prompt1 BYTE "This program will find max value in string",cr,lf,"input string:",0
string WORD 80 DUP (?),0
stringLen DWORD ?,0
result BYTE cr,Lf,"maxnumber of string is:",0
resultNum WORD 20 dup (?),0
.CODE ; start of main program code
findMAX MACRO strfirst,len
LOCAL loop1
LOCAL less
mov ecx,len
mov bx,0 ;bx置零
cld
loop1: lodsb ;复制串元素到AX
cmp ax,bx ;比较
jl less ;小于则跳转,重复循环
mov bx,ax ;否则赋值给BX AX>BX
less:
loop loop1
mov ax,bx ;最大值赋给AX
ENDM
_start:
output Prompt1
input string,80 ;输入串
lea eax,string ;得到串首地址
push eax ;长度参数
call strlen ;过程求串长度
mov stringLen,eax ;保存串长度
lea esi,string ;串首地址
findMAX esi,stringLen ;宏调用
mov resultNum,ax
output result
output resultNum
INVOKE ExitProcess, 0 ; exit with return code 0
strlen PROC NEAR32
; 得到栈内传过来字符串长度
; 由EAX返回
push ebp ; establish stack frame
mov ebp, esp
pushf ; save flags
push ebx ; and EBX
sub eax, eax ; length := 0
mov ebx, [ebp+8] ; address of string
whileChar: cmp BYTE PTR [ebx], 0 ; null byte?
je endWhileChar ; exit if so
inc eax ; increment length
inc ebx ; point at next character
jmp whileChar ; repeat
endWhileChar:
pop ebx ; restore registers and flags
popf
pop ebp
ret 4 ; return, discarding parameter
strlen ENDP
PUBLIC _start ; make entry point public
END ; end of source code
LOCAL定义宏中标志位并活用跳转,比较cmp与跳转jmp相关语句使用进行串操作与比较,使用lea去取串首,cld决定串操作方向。
区分PROC NEAR32过程与MACRO 参数的使用与区别,ENDP与ENDM相应作用。使用cwd字扩展进行除法,使用CLD STD和REP操作去操作串。