分享
 
 
 

MASM宏使用总结

王朝other·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

MASM宏使用总结

td.general1 {

background-color : #ffcc00;

}

td.general2 {

background-color : #CCCC99;

}

td.general3 {

background-color : #cccc99;

}

td

{

font-size: 11px;

}

body { margin-left : 10%;

margin-top : 10;

margin-right : 10%;

margin-bottom : 2;

font-family: verdana, arial, helvetica, sans-serif;

font-size: 11px}

p { font-family: verdana, arial, helvetica, sans-serif; font-size: 11px}

H1 {

font-size : 16pt;

font-weight : bold;

border-width : 0 0 3px;

border-style : double;

}

h2

{

font-weight: bold;

font-size: 18px;

color: #cc3300;

font-family: verdana, arial, helvetica, sans-serif;

padding-left : 4px;

padding-top : 4px;

padding-right : 4px;

padding-bottom : 4px;

border-style : solid;

border-width : 1px;

border-color : #9f9f9f;

background-color: #cccc99;

}

H3 {

font-size : 11pt;

font-weight : bold;

}

a:link {color: #CC3300; font-family: verdana, arial, helvetica, sans-serif;

font-weight: normal; font-size: 11px; text-decoration: none}

a:visited {color: #CC3300; font-family: verdana, arial, helvetica, sans-serif;

font-weight: normal; font-size: 11px; text-decoration: none}

a:active {color: #ffffff; font-family: verdana, arial, helvetica, sans-serif;

font-weight: normal; font-size: 11px; text-decoration: none}

a:hover {text-decoration: none; font-family: verdana, arial, helvetica,

sans-serif; font-weight: normal; font-size: 11px;color: #ffcc99}

pre

{

border-right: #9f9f9f 1pt solid;

border-top: #9f9f9f 1pt solid;

padding-left: 5pt;

padding-bottom: 10pt;

border-left: #9f9f9f 1pt solid;

padding-top: 10pt;

border-bottom: #9f9f9f 1pt solid;

font-family: 'Courier New' , Georgia;

background-color: #cccc99;

}

很久没有在CSDN发帖了,gigix也离开CSDN了...(沉默)

最近用MASM的宏作了一个另类的东西,汇编环境下的OOP对象模型。作出了C++对象模型的

大部分功能。基于网上现有的那几个已经有的东西,而且已经远远超出了。等我把它彻底写

完善了在发出来给大家看。不过大家可以从这里:

参与这个另类东西的讨论

要感谢allaboutprogram.com给我提供这么好的一个版面。

我的个人主页是:新版个人主页

这篇文章是我花了一个晚上作的总结,从一个比较本质的角度解释了一些宏的行为,不是

教科书设置是Programmer Guide达到的程度。看起来比较没有味道,但是如果你要用起宏来

你会发现我几乎没有说废话。不是教你怎么去用宏,但是你看过之后也不用学了,自己试验

一下就可以写了。虽然没有几个家伙还在用MASM,更少人用MACRO了,可能这个就是我另类的

风格吧。

MASM宏使用总结

导语

MASM(Macro Assembler)是由微软公司提供的汇编工具,虽然有些年头了,但是仍然存在于

vc.net这样比较新的工具中。有很多汇编教科书以这个为对象,讲述了如何用汇编去设计一

个程序,作为计算机科学系学生的基础课。但是,讲述的内容大体上还是停留在5.1版,而且

停留在DOS的时代。虽然提到了win32下的汇编,但是并没有放在首要的位置。另一个被忽视

的是作为MASM最大特色的宏,怎么去看待汇编工具中提供的强大的宏,以及怎么和在什么场

合下使用宏,语焉不详。本文是作者在大量使用MASM宏,搭建了一个汇编环境下的OOP系统后

,作的一个总结。

善用宏,能够减少重复编码,以及构建强大的功能,是重用代码,美化代码的一个有力的工

具。宏在高级语言中是一个应该被极力避免的东西,在低级语言中确未必如此。

宏就是预处理

宏就是在代码被汇编成为obj文件之前进行的预处理。由于发生在汇编期(Assembly-Time,

和高级语言中的编译期是一个意思),所以不会给执行期带来负担,可以用作代码生成工具

,设置和C++中的模板一样,用作meta-programming的工具。在MASM中宏可以分为两种:1、

Text Macro 2、Procedure (Function) Macro。第一种宏就是和#define pi 31415926这样的

简单的文本替换的宏,第二种就是那种带参数,可以有局部变量,可以返回值这样的可以看

作函数或者过程的宏。下面就先从Text Macro入手,看看如何使用简单的宏。

简单的文本宏

你可以给一个字符序列指定一个符号名,然后在源代码的其余部分用这个名字来代替这个

字符序列。这个指定了名字的文本就是文本宏。说白了就是文本替换。用TEXTEQU来定义一个

这样的宏。

name TEXTEQU <text>

name TEXTEQU textvar

name TEXTEQU %numvar

我这里给出的使用说明和MASM Programmer Guide中给出的不大一样,但是这个更能说明问题

。我在这儿只解释第一个用法,后面的用法将在讲了“汇编期变量”之后再讲。举一些使用

的例子。

pi TEXTEQU <3.1416>

DWPTR TEXTEQU <WORD PTR>

arg1 TEXTEQU <[bp+4]>

然后在代码中就可以用pi这些名字来代替3.1416这些。表示他们是字符串,如果把不加

则会把你给出的字符串当作一个汇编期的文本变量来进行求值,而这样的话会出错的。

汇编期的变量与常量

这个几个东西其实都有自己的名字,其实按照用法来说就是汇编期的常量与变量的意思。

比如Text Macro(对,就是前面的文本宏)用作汇编期的文本常量,Name Assignment用作汇

编期的数值变量。

定义汇编期常量

什么是汇编期常量呢?其实也就是常量的意思,因为无论在编译期还是执行期它都是静态

的,一旦定义之后其值不能改变。回忆在C中,你用#define来定义常量。但是#define可以改

变一个宏所等于的值,也就是说常量与否需要你的维护(编译器会给出一个警告)。在MASM

中有一个关键字专门用来定义常量,尝试改变常量的值会得到一个错误提示。

name EQU expression

name EQU <text>

第一个是用作定义个“数值”常量,第二个是用作定义“文本”常量。以后要特别区分开

文本和数值。

定义汇编期文本变量

汇编期文本变量是对“text macro”的另外一个看法。其实它们是同一个事情。当你定义

了一个文本宏之后,你可以把那个宏名看作汇编期文本变量的名字,被宏名替换的文本内容

作为变量的文本值。

那么前面说过的第二种用法:name TEXTEQU textvar就很好理解了。就是让把一个文本变

量赋给另一个文本变量。比如:

talent TEXTEQU <genius>

taowen TEXTEQU talent

第一行定义了一个名字为talent的汇编期文本变量,第二行把talent的值赋给了名为

taowen的变量。从结果上看这个和:

talent TEXTEQU <genius>

taowen TEXTEQU <talent>

是一样的,但是第二种做法是先因为文本宏替换的作用把talent变成了genius。实际的效

果是这样的:

taowen TEXTEQU <genius>

显示文本变量的内容

在C中经常用printf,在运行期显示一些变量的内容来进行调试。而在MASM中则用echo来

在汇编期显示文本变量的内容。

china TEXTEQU <great country>

%echo china

这样会在汇编时的命令行中出现great country。如果你把%号去掉,则显示的是china。

你应该可以推测出%是干什么的了,就是对一个变量进行求值。

定义汇编期数值变量

常量有两种那么变量也应该有两种。这里就介绍汇编期数值变量的用法。

name = expression

expression是一个数值表达式,比如:

val = 3+4

此时val就是一个数值变量,其值为7。你也可以这么写:

valexp TEXTEQU

val = valexp

看上去好像式把一个文本变量赋给了数值变量,进行了类型转换(呵呵,效果是一样的)

。其实实际上是把3+4写到了valexp处,因为文本宏进行了文本替换。

把数值变量赋给文本变量

前面我们看到了如何“把文本变量赋给数值变量”,那么反过来呢?

val = 3+4

valexp TEXTEQU val

结果是提示错误:STest.asm(15) : error A2051: text item required。汇编器说需要

文本项,那么我们加上就好了。

val = 3+4

valexp TEXTEQU

用%echo valexp检查一下你就会发现,并不是如你所愿的显示的是7,而是val。这个是因

为使得汇编器认为val是一个字符串,由于数值变量不是文本替换的宏,并不会把val替换

为7,所以当然显示的是val。正确的做法是:

val = 3+4

valexp TEXTEQU %val

%号和前面的用法一样,是用作求值。回忆一开始介绍的文本宏的用法中的第三条就是:

name TEXTEQU %numvar。这个用法就是让一个数值变量的值赋给文本变量,经常用作显示一

个数值变量的值。调试的时候这么写。

pi = 3.1415926

temp TEXTEQU %pi

%echo temp

这个是一个很重要的调试技巧。

宏过程和宏函数

前面从简单的文本宏引出汇编期的常量与变量。如果仅仅是用在宏外的代码中,一个文本

宏作一些简单的替换就足够了。它们更多的是用在复杂的宏中,这些宏可以看作过程和函数

。同汇编期的变量一样,它们是用在汇编期的。

下面将不再把text macro视为宏,而把它视为文本变量。宏直接指宏过程或者宏函数。宏

过程是不带返回值的宏,而宏函数是带返回值的宏。它们都可以带参数,也都可以有局部变

量。其实可以统一的成为宏函数,或者汇编期函数

用如下的格式创建一个简单的宏

name MACRO

statements

ENDM

statements中可以进行判断或者循环,可以说是非常的全功能。但是汇编期的函数和执行

期的函数是很不一样的,一个是发生在汇编期的预处理,另一个是把执行期的执行位置改变

,执行一段代码之后返回。

clear_eax_m MACRO

xor eax, eax

ENDM

clear_eax_p Proc

xor eax, eax

ret

clear_eax_p Endp

关于这个两者的区别,我假定你已经理解了,如果不理解可以参考任何一本汇编教科书,

上面有完整的汇编代码说明为什么不同。

给宏传递参数

参数对于函数的重要性不言而喻,对于宏的参数如下定义。

name MACRO parameterlist

statements

ENDM

简单情况下,对于parameterlist就是参数名字用,号格开,比如:

clear_reg MACRO reg

xor reg, reg

ENDM

调用的时候,用这种格式:

clear_reg eax

对于宏过程,这个是唯一的调用格式。

参数的传递和执行期的函数的参数传递也是很不一样的。参数是被直接替换的。你可以作

这么一个试验:

TestMacro MACRO param

echo param

%echo param

ENDM

TextVar TEXTEQU <Hello>

TestMacro TextVar

输出的结果是TextVar和Hello。到底是怎么回事就不用我多说了。你甚至可以进一步测试

TestMacro MACRO param

param TEXTEQU <How are you>

ENDM

TextVar TEXTEQU <Hello>

TestMacro TextVar

%echo TextVar

输出的结果是How are you。可见所谓的参数不过就是替换。参数名会被引数名给替换(

引数就是调用时候传递过去的那些参数)。由于MASM中宏这个系统中,所有的这些变量名的

符号都是在一个共同的空间之中(呵呵,怎么听起来像数学术语?),都是全局的东西。

对于参数可以进行一些限定修饰,比如让你调用的时候一定要传递这个参数:

Clear_reg MACRO reg:REQ

xor reg, reg

ENDM

或者指定一个缺省值:

Clear_reg MACRO reg:=<eax>

xor reg, reg

ENDM

或者让参数个数成为一个变数。

Clear_reg MACRO regs:VARARG

FOR reg, <regs>

xor reg, reg

ENDM

ENDM

不过要注意的是VARARG修饰的参数必须是参数中的最后一个。

让宏返回一个值

宏过程和宏函数的区别在于是否有返回值。当然这里的返回值和执行期的函数的返回值也

是很不一样的。执行期的函数是通过eax来传递返回值的。而这里,也不过是直接替换而已。

返回值的语法是这样的:

EXITM textitem

一个宏函数可以有多个EXITM,就像C中的函数可以有多个return一样。不过必须返回值一

致。看一个简单的例子

Who MACRO

EXITM <taowen>

ENDM

%echo Who()

结果是显示taowen。如果把()去掉,则显示的是who。可见对于宏函数的调用一定要加上

()。而调用宏过程则不能加()。看一个有趣的例子:

Who MACRO temp

%echo temp

ENDM

Who()

显示的结果是()。说明()被当作传递给宏过程的参数了。

可以比较随意的使用返回值,可以把返回值这么用。

Who MACRO

EXITM <taowen>

ENDM

Who() TEXTEQU <genius>

这样就定义了汇编期文本变量,值为genius。可见宏函数可以用在任何文本变量可以出现

的地方,很多地方可以把高级语言中函数中那些类推过来。

局部变量

宏中可以有局部变量,它看起来像局部的,实际上不过是一些名称上的小技巧。

对于局部变量有两点事实:1、在函数外无法访问,2、在对函数的不同次的调用中其值应

该不受前次调用的影响。

TestMacro MACRO

LOCAL LocalVar

%echo LocalVar

LocalVar TEXTEQU <Hello>

ENDM

如果对于函数的调用每次之间会互相影响,那么这么调用:

TestMacro

TestMacro

第一次会产生一个未定义变量的错误,而第二次就会输出Hello。事实上,由于LocalVar

是LOCAL的。所以两次都是未定义错误。这个就体现了局部变量的多次调用的独立性。

下面我们来揭穿局部变量的底牌。不用我多叙述,直接看看这个你就明白了:

TestMacro MACRO

LOCAL LocalVar

echo LocalVar

ENDM

TestMacro

TestMacro

输出的结果是:??0000与??0001。这个就是局部变量的实际名字。局部变量就是通过怪怪

的名字让外部无法访问(你不知道它是什么名字),然后在每次展开同一个宏的时候用不同

的名字替换局部变量的名字,使得多次调用之间不会互相影响。

其实你可以试验一下这个:

??0000 TEXTEQU <Hello>

TestMacro MACRO

LOCAL LocalVar

%echo LocalVar

ENDM

TestMacro

显示的结果是Hello,这样就在一个宏过程(函数)的外部访问了局部变量。

文本操作

MASM内置了两套文本操作功能,一个是宏函数,另一个是Directive。功能是一样的,但

是提供了表达上的灵活性。

name CATSTR [[textitem1 [[, textitem2]] ...]]

name INSTR [[position,]] textitem1, textitem2

name SIZESTR textitem

name SUBSTR textitem, position [[, length]]

这一套是Directive,作用分别是:连接文本,查找子文本,获得文本长度,取子文本。

@CatStr( string1 [[, string2...]] )

@InStr( [[position]], string1, string2 )

@SizeStr( string )

@SubStr( string, position [[, length]] )

这一套是宏函数。用一个例子显示两套其实是一样的:

taowen TEXTEQU @CatStr(<He is >, <genius>)

%echo taowen

taowen CATSTR <He is >, <genius>

%echo taowen

可以看到两个例子输出的都是He is genius。有两点需要注意:1、@CatStr这样的宏函数

可以作为左值,被用来赋值。2、@CatStr这样的宏函数对于参数并不自动求值,当行为和你

想的不一样的时候,加上%。

对于具体的使用不是很难,试验一下就可以知道了。一点就是第一个字符的索引是1,而

不是C中的0。

%与求值

%可能是最难使用的语法了。一般就是行为和你想的不一样的时候,加上%试验一下。%与

与!等,构成了一团糟。

一般情况下,你不用%号。用%可以把数值变量转变为文本变量。可以用%号强制取出文本

的值。比如:

Index = 0

NameT CATSTR <Person>, %Index

%NameT TEXTEQU <taowen>

%echo Person0

先对Index用%就是把数值变成文本,第二个%就是把NameT变成Person0。这里也演示了一

个产生变量名的很重要的技巧,只要把Index进行一些递增,就能够构建一个变量的数组了。

可以一定程度上放置被求值,不过大部分情况下由于文本宏的替换不受影响,所以仍然

取到的是替换后的值。!用来取消符号原有的意思。比如:

Symbol CATSTR <Go >, <!,>, <Go>

%echo Symbol

输出的结果是Go, Go。如果不加!则,号会导致错误。有趣的是如果你在第二个Go后面加上

!本来应该是Go, Go!。结果确实一个缺少右尖括号的错误,原来是!把的原有意思变化了,

不再表示结束了。如果你这样:

Symbol CATSTR <Go >, <!,>, <Go!>>

%echo Symbol

得出的就是Go, Go。看出来是怎么回事了吧。要产生!,就这么写:

Symbol CATSTR <Go >, <!,>, <Go!!>

%echo Symbol

关于什么时候用什么时候不用,我的看法是最好能用就用。具体为什么,是因为能

够加大适用范围。

在宏中进行循环

循环有四种:WHILE,REPEAT,FOR,FORC。语法如下:

WHILE expression

statements

ENDM

REPEAT expression

statements

ENDM

FOR parameter [[:REQ | :=default]] , <argument [[, argument]]...>

statements

ENDM

FORC parameter, <string>

statements

ENDM

WHILE与REPEAT从用法到效果是一样的,至少我认为是一样的。expression要求值为一个

数值,可以用EQ(等于),LT(小于)这些判断Operator来比较数值。

I = 0

WHILE I LT 10

Temp TEXTEQU %I

%echo Temp

I = I + 1

ENDM

输出的结果就是0一直到9。

FOR与FORC是专门用途的循环,一个是用于取得一个参数列表中的各个参数,另一个是逐

个取出一个字符串中的每个字符。各举两个例子就可以明白:

TestMacro MACRO params:VARARG

FOR param, <params>

%echo param

ENDM

ENDM

TestMacro arg1, arg2, arg3

显示的结果是arg1然后是arg2然后是arg3。

FORC char, <Hello>

%echo char

ENDM

分别显示的是H和e和l和l和o。

在宏中进行判断

判断很简单了,不过有很多种IF,IFDEF,IFIDN,IFE,IFNDEF,IFDIF。使用上没有什么值得

注意的都比较简单。分别是判断数值,判断符号是否定义,判断两个文本是否一致。

关于宏还有定义在宏中的宏,OPATTR, SIZEOF, LENGTHOF, 等等许多比较高级的东西。

不过我相信有前面讲述的基础,这些东西的使用不过是查查手册的事情。

Good luck, that is all.

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有