作 者: hjjdebug
时 间: 2008-06-18, 20:07
虽然我们不提倡用宏,宏本质上只不过是一种替换而已。
但宏汇编语言控制台程序中却大量使用了宏。经研究后,发现某些宏用起来确实方便。
这里推荐4个,chr$, str$,print,input
当然,象那些简单的宏例如exit 宏,就随你意愿可用可不用了。
下面是控制台程序中常用的宏:
1. 控制台程序 print 宏的完全解析
例子程序可以参考宏汇编的tutorial\console 下的程序,我们重点分析一句代码:
print chr$("Hey, this actually works.",13,10)
先看chr$ 宏
chr$ MACRO any_text:VARARG
LOCAL txtname
.data
txtname db any_text,0
.code
EXITM <OFFSET txtname>
ENDM
chr$ 是带一个参数的宏。
1. 在数据区中定义一个标号txtname,这个标号是局部的,意思是说,仅在该宏中有意义。
然后把后续的参数定义到数据区中,尾巴补0.
2. 宏结束,返回一个标号地址。
再看print 宏
print MACRO arg1:REQ,varname:VARARG ;; display zero terminated string
invoke StdOut,reparg(arg1)
IFNB <varname>
invoke StdOut,chr$(varname)
ENDIF
ENDM
1. print 宏似乎带2个参数的宏?一个arg1, 一个varname, varname 可以为空。当为空时,只替代第一句。
invoke StdOut, reparg(arg1)
再看reparg (arg1) 宏
; -----------------------------------------------------------
; This macro replaces quoted text with a DATA section OFFSET
; and returns it in ADDR "name" format. It is used by other
; macros that handle optional quoted text as a parameter.
; -----------------------------------------------------------
reparg MACRO arg
LOCAL nustr
quot SUBSTR <arg>,1,1
IFIDN quot,<"> ;; if 1st char = "
.data
nustr db arg,0 ;; write arg to .DATA section
.code
EXITM <ADDR nustr> ;; append name to ADDR operator
ELSE
EXITM <arg> ;; else return arg
ENDIF
ENDM
1. 判断参数第一个字符是否为", 如是, 定义为数据区,末尾补0,返回地址。否则,直接退出。返回原arg.
可见,args 经replace 宏替代后,可以不用chr$ 宏
; ---------------------------------------------------------------------------
分析完后,可以做个新实验。
改原句为如下,应也可工作
print "Hey, this actually works.",13,10
虽然打印结果没有变化,但实际宏的控制过程却是改变了的。
实际宏的工作过程是,将print 后所跟参数看成两个参数, "Hey, this actually works." 为第一参数,replace 参数,
第二部分13,10 ... 为可变参数,print 的第二参数, 用chr$ 宏修饰之。所以编译的结果形成两条语句。
invoke StdOut,reparg(arg1) .data
??0019 db "Hey, this actually works.",0
.code
invoke StdOut,ADDR ??0019
invoke StdOut,chr$(varname) .data
??001A db 13,10,0
.code
invoke StdOut,OFFSET ??001A
也一样能满足要求。
如此看来,用chr$ 修饰字符串,有更高的效率。
print chr$("Hey, this actually works.",13,10) .data
??0019 db "Hey, this actually works.",13,10,0
invoke StdOut,OFFSET ??0019
; ---------------------------------------------------------------------------
说了一大堆,到底得出点什么结论呢?两点最重要
1. chr$ 是个宏,用来定义0字终结字符串。
2. print 是个宏,用来执行StdOut 函数。
另外,关于exit 宏:如下定义
; --------------------------------------------------------
; exit macro with an optional return value for ExitProcess
; --------------------------------------------------------
exit MACRO optional_return_value
IFNDEF optional_return_value
invoke ExitProcess, 0
ELSE
invoke ExitProcess,optional_return_value
ENDIF
ENDM
也就是说,根据exit 宏是否带参数,将被翻译成不同的ExitProcess 函数。
[课程]Linux pwn 探索篇!