asm编程情况的构建和masm32宏macro的应用精彩Word文件下载.docx
《asm编程情况的构建和masm32宏macro的应用精彩Word文件下载.docx》由会员分享,可在线阅读,更多相关《asm编程情况的构建和masm32宏macro的应用精彩Word文件下载.docx(9页珍藏版)》请在冰豆网上搜索。
由于功能完善的asm集成编程环境还没有出现,所以我们只能根据各种编辑器的优缺点和自己的偏好
加以选择.不要抱怨!
谁叫你选择的是ASM?
?
我用的是editplus.感觉不错,推荐使用.
(二)编译器的选择(compiler)
现在网上的编译器种类很多,比较著名的有MASM,TASM,NASM,FASM,SPASM,A86,GAS,GoASM等,究
竟选择什么作为我们的编译器似乎是每个初学者几乎必问的问题.其实各个编译器互有优缺点,究竟选
择什么,取决于你的实际需要.下面介绍一下主要的几种:
和TASM
Masm是微软的ASM编译器,TASM是编译器巨人Borland公司的产品,版本现在已经可以在其主页
免费下载,我最初选择masm的原因很简单,是因为大部分教科书都使用他作为蓝本,在dos时代的机房里
面配备的也基本都是MASM.就dos而言,但低版本的masm并不是最佳的,因为borland公司推出了TASM,
Tasm完全兼容masm,并且由于编译速度快等优点获得了编程者的厚爱.但在国内使用较多的还是MASM.
WIn32下有点力不从心了,这是由于tasm的头文件和库不完整,而Borland也放弃了Tasm的继
续开发.相反MASM则不断更新,更由于hutch为Masm作了一个masm32V?
.zip的开发包,里面有完整的头
文件和库文件,所以win32下使用masm的人数日渐增多,成为主流.
NASM(netwideassembler),是一个正在开发中的项目,其目的是支持多种平台的文件格式,比如elf,等unix
和linux所使用的文件格式,如果你要在上述平台下写asm,那么最好的选择是nasm,不过nasm当然也可
以用于写win32ASM,麻烦的问题和tasm是同样的,那就是缺少头文件和库文件的支持,不过如果你厌倦
了MASM的烦琐奇怪有时又容易产生歧义的伪操作符的话,试试Nasm的语法,相信会有所收获.NASM生成
obj的链接可以使用Alink.
fasm(flatassembler)是一个纯粹用汇编语言写成,并采用自展技术的正在开发的的编译器,fasm最大的优点
在于不需要额外的链接步骤而直接生成可执行文件,没有什么烦琐的伪命令,所以写出来的代码看起来
十分干净.另外用fasm写16bitexe或com可能是非常好的选择,简单而高效.此外在PE格式的
import,export,resource等的处理上也都别具一格.不过目前尚不完善...
4.其他
其他诸如spasm,a86等由于我没有用过,所以不妄加评论了.
所以如果你在写win32asm的话,MASM32仍然是最好的选择.其他:
ForCodingPleasure...
5.资源编译器
WIn32涉及到资源,你可以用与rc(resourcecompiler)任何兼容的资源编译器,比如用微软的
VC自带的资源编译器,或者BorlandresourceWorkshop.大部分开发包自带资源编译器.
(三)链接器(linker)
基本上述的种类的编译器,都附带有相应的链接器和资源编辑器.只有Nasm是个例外,与nasm配合使
用的链接器有很多,最普遍应用的是alink,目前版本是.
PartII:
MASM32宏(Macro)的使用
如果你已经使用了MASM,那么让我们来看一下masm是什么,masm是MACROassembler的简称,
你喜欢用Macro吗?
用MAcro可以缩短源代码,简化程序的编写,便于理解,而masm的宏还是比较强大
的,虽然有些地方不够贴心和简洁,下面结合我的头文件简单介绍一下几个常用的宏...
1)m2m在masm32包里面
mov指令不允许movmem1,mem,mem*代表地址,你每次都
moveax,mem
movmem1,eax
不会吧,实际上你可以定义一个m2m宏,为了不改变寄存器内容,使用的是堆栈
m2mMACROM1,M2
pushM2
popM1
ENDM
以后每次在mem到mem的移动就很方便了....
2)return在C里面经常遇到return语句,在win32asm里面也经常遇到需要返回值的地方,让我门来定义一个
return语句:
returnMACROarg:
=<
0>
moveax,arg
ret
ENDM
这样就可以方便地使用returnTRUE或者returnFALSE了...
不过这还不是最终的答案我们还可以根据返回的参数进一步优化一下,这是我的优化版本.
IFIDNI<
&
arg>
<
subeax,eax
ELSEIFIDNI<
1>
xoreax,eax
inceax
ELSE
ENDIF
3)CTEXT有时候你需要在asm里面定义一些字符串可能只用到一次,这时你就可以用CTEXT宏
CTEXTMACROy:
VARARG;
Thisisagoodmacro
LOCALsym
CONSTsegment
y>
>
symdb0
symdby,0
CONSTends
EXITM<
OFFSETsym>
这样你就可以用inokeLoadLibrary,CTEXT("
"
)方便地使用了,尤其是代码比较长的时候不用翻来翻去
定义数据,然后再offset****了...呵呵.
其他的下面的宏功能基本是一致的.
dsTextMACROname,Text:
VARARG
.data
namedbText,0
.code
下面这个宏用于在代码段里面定义数据,在链接的时候注意假如/SECTION:
.text,EWR否则读写这
类数据会产生非法操作.
szTextMACROname,Text:
jmp@f
@@:
你可以根据需要选用.
4)$invoke宏,用于inlineCoding,在C里面你肯定看到过GetModuleFileName(GetModuleHandle(0),&
buf);
的语句在
asm里面依然可以实现...那就是用下面的$invoke宏:
$invokeMacrofun:
REQ,args:
VARARG
IFNB<
args>
invokefun,&
args
invokefun
ENDIF
eax>
不过要注意寄存器争用的情况,比如第3个参数用到eax,那么第一、二个参数就不能用这个内嵌宏
.
5)RGB和$RGB
在GDI编程里面经常遇到用RGB值作为参数的情况,为了简化这以过程可以定义下面的宏
RGBMACROred,green,blue
xoreax,eax
movah,blue
shleax,8
movah,green
moval,red
然后在RGB宏后面用eax作为RGB值参数,这诗歌好想法,不过还不够好,因为占用了多余的代码行,
实际上我们需要的仅仅是一格RGB值,于是有了下面的宏:
$RGBMACROred:
REQ,green:
REQ,blue:
REQ;
Thisisbetter...
EXITM%(red+256*(green+(256*blue)))
6)pushm和popm
这时为了简化寄存器的入栈和出栈而设计的,很简单:
pushmMacroargs:
FORarg,<
pusharg
.ERR<
registersMustbeofferred!
EndM
popmMacroargs:
poparg
7)数据定义rb,rw,rd,rq....
你喜欢这种方式吗?
比如bufdb260dup(?
)是不是很烦琐用下面的宏就可以rbbuf,260是不是更简单呢?
这时我喜欢的....
rbMacrolabel:
REQ,count
count>
labeldb&
countdup(?
)
labeldb?
类似的是rw,rd,rq...等具体参见我的文件.
8)revargs将参数反向排列(specialthxtolyb)
在stdcall调用模式里面使用的是反向压入参数的调用约定,MASM的宏并没有提供反向参数的
机制,我们得字节写一个宏.
revargsMACROargs:
LOCALtarget
targetTEXTEQU<
count=0
targetCATSTR<
!
>
target
count=count+1
IFcountGT0
targetSUBSTRtarget,1,@SizeStr(%target)-1
EXITMtarget
用于需要反向排列参数的地方.
9)iWin32,iWin32i,避免jmptabel,有两种方法避免生成jmptabel(thxtoEliCZ'
smacro)
一种我以前写的一篇文章里面介绍过,就是利用声明
_imp__&
Win32Api&
Aproto:
DWORD,....
然后
calldwordptr[_imp__&
A]
格式另一种是ELiCZ的方法,就是声明
externdef_imp__&
A@NUM:
DWORD,其中NUM是参数个数
call_imp__&
A来调用.
由于用EliCZ的方法写的macro较长,下面根据我的方法写一个宏:
iWin32MacroWin32API:
LOCALsz1
sz1TEXTEQU<
%FORpxx,<
revargs(args)>
pxx>
pushpxx
sz1CATSTRsz1,<
:
DWORD>
sz1SUBSTRsz1,2,@SizeStr(%sz1)-1
sz1CATSTR<
Win32API>
PROTO>
sz1
sz1
callDWORDPTR[_imp__&
Win32API]
下面iWin32i可以根据情况生成对ansi或者UNICODE的调用,前提是定义UNICODE=0或者TRUE...
iWin32iMacroWin32API:
IFUNICODE
iWin32Win32API&
W,<
A,<
注意这个宏并没有参数检查,如果你不熟悉APi建议不要使用,你可以用masm包自带的工具
转换头文件来避免产生jmptabel...如果你喜欢宏,那么就用我这种方式.
宏不同于封装,我们可以用他来简化我们的工作而又可以清楚知道将产生什么代码,为什么
不用呢?