macro

mWrite macro text
ifb <text> ;;如果参数为空则进入里面;ifb宏编译条件语句的参数要放在<>里面
echo 错误,您的参数为空
exitm ;;结束展开下面的宏
endif
push edx
mov edx,offset text
call writestring
pop edx
endm
mGoto macro x:req,y:req
local error ;;在这里定义一个标号常量.注意它的用法,这样做就可以重复调用宏,每次名字都不一样
error=0 ;;注意error的用法
if (x lt 0) or (x gt 25 );;这里注意if语句不需要使用<>来括住.注意它的用法 x不在在0~25之间,则
echo 错误,x不在0~25之间;;在这里显示的x会自动被替换成调用x的值.
error=1 ;;注意error的用法
endif
if (y lt 0) or (y gt 25)
echo 错误,y不在0~25之间;;在这里显示的y会自动被替换成调用y的值.
error=error+1 ;;注意error的用法
endif
if (error gt 0) ;;注意error的用法
exitm
endif
push edx
mov dh,y
mov dl,x
call Gotoxy
pop edx
endm
mReadString macro buff:req,maxCount:req
ifidni <maxCount>,<edx> ;;ifidni不区分大小写参数相同则编译.参数用<>括住
echo 错误,maxCount这个参数不能是edx
exitm
endif
push edx
push ecx
mov edx,buff
mov ecx,maxCount
call ReadString
pop ecx
pop edx
endm
mWriteReg macro regs
local string
.data
string byte "&regs=",0 ;;这里就是使用& 符号&将宏的内部对宏参数的引用替换为调用时的实际值.编译器就不会把它当作字符来处理掉
.code
push edx
push eax
mov edx,offset string
call writestring
mov eax,regs ;;这里注意用法,因为regs传进来的是一个寄存器
call writeHex
pop eax
pop edx
endm
mWriteText macro text
ifnb<text>
Leng textequ %(sizeof text) ;;%对表达式求值.首先计算出text的值
Line textequ %(@Line) ;;@Line汇编操作符,用于返回当前源码的行号
%echo 字符长度是Leng 行号是Line;;%在行首,表示展开该行所有文本宏或宏函数
endif
endm
mReadLar macro text
local string
.data
string byte text ;;这里在定义的时候没有插入空字符
.code
push edx
mov edx,offset string
call writestring
pop edx
endm
mAllF macro message
mReadLar "&message" ;;注意这里的用法.接收进来的参数再&替换给mReadLar调用
endm
mFunc macro system ;;宏函数和普通的宏一样,区别是宏函数要返回一个值
ifdef system
exitm<-1> ;;返回-1
else
exitm<0>
endif
endm
mFunction macro system
if mFunc(system) ;;非0则进入.在这里调用宏函数的方法是:宏名字 (参数) 宏函数再返回值给if比较
echo 0 system已经定义了
else
echo -1 system未定义
endif
endm
.data
var1 byte "abcdeee",13,10,0
var2 byte 10 dup(0)
.code
main PROC
mWrite ;;这里在编译时会提示错误参数为空,而宏相应的也不会展开下面的操作
mGoto 11,11 ;;这里则是正常的把光标定位于11.11
mGoto 33,55 ;;提示错误,这里调用时会使上面的echo相应的x和y变成其值
mReadString offset var1,lengthof var2
mWriteReg eax
mWriteText var1 ;;在编译的时候注意看值是多少
mReadLar <"显示字符" , 0dh , 0ah>;;这里的<>符号是将多个字符当作一组字符传送,不然编译器会把期当作3个参数
Shar Textequ <warning: y-coord if !> 24> ;;注意前面的!用法.在汇编里面>是转义字符!强制它作为字符符号
mAllF %Shar ;;这里也要使用%展开操作.
mAllF Shar ;;这里没有用%展开也就直接在屏幕上打印2个Shar
system=1
mFunction system ;调用宏函数,如果上面的system=1去掉,则在编译时宏函数会返回为system未定义
;还有一点可以去掉system=1在编译的时候用ml -c -d system=1 1.asm 这样也会提示这个参数据被定义了

main ENDP
;到这里已经完了。宏用的到基本都在上面使用过了。请认真看注解


例一:多余的参数会被忽略
mSum macro v1, v2, v3
  mov eax, v1
  add eax, v2
  add eax, v3
endm

mSum 11, 22, 33, 44, 55 ;多余的参数会被忽略

例二:宏参数的默认值
  REQ用来标宏参数是必备的
mSum macro v1:req, v2:req, v3:=<33>, v4:=<44>
  mov eax, v1
  add eax, v2
  add eax, v3
  add eax, v4
endm
参数 v1、v2 通过 REQ 标识说明是必备参数
参数 v3、v4 给出了默认值
例三: EXITM: 退出宏
       EXITM退出来,跳到宏结束

例四:PURGE: 取消宏
main proc
  mPrint
  mPrint
  purge mPrint ;可用逗号隔开取消多个宏
  mPrint  ;这个宏不会展开了
  ret
main endp


例五:宏中 local 的使用:
从三个数中求最大数的宏

mMax macro v1, v2, v3
 LOCAL L1, L2 ;;如没有这句, 宏在多次展开时会让 L1、L2 重名, 这样宏会把标号名称协调好
  mov eax, v1
  cmp eax, v2
  jge L1
  mov eax, v2
L1: cmp eax, v3
  jge L2
  mov eax, v3
L2:
endm
例六:灵活的参数

;能把 JGE 或 JLE 做参数:
  mCom1 macro XX, v1, v2
    LOCAL L1
    mov eax, v1
    cmp eax, v2
    XX L1
    mov eax, v2
   L1:
  endm

例七:& 操作符

能通过参数让 J*E 变为 JGE 或 JLE:
  mCom2 macro X, v1, v2
    LOCAL L1
    mov eax, v1
    cmp eax, v2
    J&X&E L1 ;;这里用到特殊操作符 &
    mov eax, v2
   L1:
  endm

例八 :特殊操作符: &、<>、%、! & ;替换操作符
<> ;字符串传递操作符
% ;表达式操作符, 也用于得到一个变量或常量的值
! ;转义操作符


; Test34_8.asm
.386
.model flat, stdcall

include windows.inc
include kernel32.inc
include masm32.inc
include debug.inc
includelib kernel32.lib
includelib masm32.lib
includelib debug.lib

;自定义的宏
mPrint macro Text
  PrintText '* &Text& *'
endm

.code
main proc
;该宏会把参数直接替换过去
  mPrint 1234 ;* 1234 *
 
;要保证参数的完整应该使用 <>
  mPrint 12,34 ;* 12 *
  mPrint <12,34> ;* 12,34 *
 
;需要计算结果应该使用 %()
  mPrint 34+12 ;* 34+12 *
  mPrint %(34+12) ;* 46 *
 
;用到 &、<、>、%、! 应该使用 ! 转义
  mPrint 10 !% 2 = %(10/2)!! ;* 10 % 2 = 5! *
  ret
main endp
end main

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值