汇编语言Macro宏库详解
INCLUDE Macros.inc
有些宏封装在了 Irvine32 链接库的过程中,这样传递参数就更加容易。其他宏则提供新的功能。下表详细介绍了每个宏。宏名 | 形式参数 | 说明 |
---|---|---|
mDump | varName, useLabel | 用变量名和默认属性显示一个变量 |
mDumpMem | abbress, itemCount, componentsize | 显示内存区域 |
mGotoxy | X,Y | 将光标位置设置在控制台窗口缓冲区 |
mReadString | varName | 从键盘读取一个字符串 |
mShow | itsName, format | 用各种格式显示一个变量或寄存器 |
mShowRegister | itsName, regValue | 显示32位寄存器名,并用十六进制显示其内容 |
mWrite | text | 向控制台窗口输出一个字符串文本 |
mWriteSpace | count | 向控制台窗口输出一个或多个空格 |
mWriteString | buffer | 向控制台窗口输岀一个字符串变量的内容 |
1) mDumpMem
宏 mDumpMem 在控制台窗口显示一个内存区域。向其传递的第一个实参为包含待显示内存偏移量的常数、寄存器或者变量,第二个实参应为待显示内存中存储对象的数量,第三个实参为每个存储对象的大小。宏在调用mDumpMem库过程时,分别将这三个实参分配给 ESI、ECX 和 EBX。现假设有一数据定义如下:
.data
array DWORD 1000h, 2000h, 3000h, 4000h
mDumpMem OFFSET array, LENGTHOF array, TYPE array
输出为:
Dump of offset 00405004
------------------------------
00001000 00002000 00003000 00004000
mDumpMem OFFSET array, SIZEOF array, TYPE BYTE
输出为:
Dump of offset 00405004
------------------------------
00 10 00 00 00 20 00 00 00 30 00 00 00 40 00 00
mov eax,0AAAAAAAAh
push eax
mov eax,0BBBBBBBBh
push eax
mov eax,OCCCCCCCCh
push eax
mov ebx,1
mov ecx,2
mov esi,3
mDumpMem esp, 8, TYPE DWORD
Dump of offset 0012FFAC
------------------------------
00000003 00000002 00000001 CCCCCCCC BBBBBBBB AAAAAAAA 7C816D4F
0000001A
mDumpMem MACRO address:REQ, itemCount:REQ, componentsize:REQ ;用 DumpMem 过程显示一个内存区域。 ;接收:内存偏移量、显示对象的数量,以及每个存储对象的大小。 ;避免用 EBX、ECX 和 ESI 传递实参。 push ebx push ecx push esi mov esi, address mov ecx, itemCount mov ebx, componentSize call DumpMem pop esi pop ecx pop ebx ENDM
2) mDump
宏 mDump 用十六进制显示一个变量的地址和内容。传递给它的参数有:变量名和(可选的)一个字符以表明在该变量之后应显示的标号。显示格式自动与变量的大小属性(BYTE、WORD 或 DWORD)匹配。下面的例子展示了对 mDump 的两次调用::
.data
diskSize DWORD 12345h
.code
mDump diskSize ; no label
mDump diskSize,Y ; show label
Dump of cffset 00405000
------------------------
00012345
Variable name: diskSize
Dump of offset 00405000
------------------------
00012345
;----------------------------------------------- mDump MACRO varName:REQ, useLabel ;用其已知属性显示一个变量。 ;接收:varName为变量名。 ;如果 useLabel 不为空,则显示变量名。 ;----------------------------------------------- call Crlf IFNB <useLabel> mWrite "Variable name: &varName" ENDIF mDumpMem OFFSET varName, LENGTHOF varName, TYPE varName ENDM&varName 中的符号 & 是替换操作符,它允许将 varName 形参的值插入到字符串文本中。
3) mGotoxy
宏 mGotoxy 把光标定位在控制台窗口缓冲区内指定的行列上。可以向其传递 8 位立即数、内存操作数和寄存器值:
mGotoxy 10,20 ;立即数
mGotoxy row, col ;内存操作数
mGotoxy ch,cl ;寄存器值
;----------------------------- mGotoxy MACRO X:REQ, Y:REQ ;设置光标在控制台窗口的位置。 ;接收:X和Y坐标(类型为BYTE)。避免用DH和DL传递实参。 ;----------------------------- push edx mov dh,Y mov dl,X call Gotoxy pop edx ENDM若宏的实参是寄存器,它们有时可能会与宏内使用的寄存器发生冲突。比如,调用 mGotoxy 时用了 DH 和 DL,那么就不会生成正确的代码。为了说明原因,现在来查看上述参数被替换后展开的代码:
1 push edx
2 mov dhr dl ;;行
3 mov dl,dh ;;列
4 call Gotoxy
5 pop edx
提示:只要有可能,宏定义应该用注释说明哪些寄存器不能用作实参。
4) mReadString
宏 mReadSrting 从键盘读取一个字符串,并将其存储在缓冲区。在这个宏的内部封装了一个对 ReadString 库过程的调用。需向其传递缓冲区名:
.data
firstName BYTE 30 DUP(?)
.code
mReadString firstName
;----------------------------------------- mReadString MACRO varName:REQ ;从标准输入读到缓冲区。 ;接收:缓冲区名。避免用 ECX 和 EDX 传递实参。 ;----------------------------------------- push ecx push edx mov edx,OFFSET varName mov ecx,SIZEOF varName call Readstring pop edx pop ecx ENDM
5) mShow
宏 mShow 按照主调者选择的格式显示任何寄存器或变量的名字和内容。传递给它的是寄存器名,其后可选择性地加上一个字母序列,以表明期望的格式。字母选择如下:H = 十六进制,D = 无符号十进制,I 二有符号十进制,B 二二进制,N = 换行。可以组合多种输出格式,还可以指定多个换行。默认格式为“HIN”。mShow 是一种有用的辅助调试工具,经常被 DumpRegs 库过程使用。可以把mShow当作调试工具,显示重要寄存器或变量的值。
【示例】下面的语句将 AX 寄存器的值显示为十六进制、有符号十进制、无符号十进制和二进制:
mov ax, 4096
mShow AX ;默认选项:HTN
mShow AX,DBN ;无符号十进制,二进制,换行
AX = 1000h +4096d
AX = 4096d 0001 0000 0000 0000b
;插入测试数值,显示4个寄存器:
mov ax, 1
mov bx, 2
mov cx, 3
mov dxz 4
mShow AX, D
mShow BX, D
mShow CX,D
mShow DX, DN
AX = Id BX = 2d CX = 3d DX = 4d
【示例】下面的代码调用 mShow,用无符号十进制格式显示 mydword 的内容,并换行:
.data
mydword. DWORD ?
.code
mS how mydword,DN
6) mShowRegister
宏 mShowRegister 显示单个 32 位寄存器的名称,并用十六进制格式显示其内容。传递给它的是希望被显示的寄存器名,其后紧跟寄存器本身。下面的宏调用指定了被显示的名称为 EBX:mShowRegister EBX, ebx
产生的输出如下:EBX=7FFD9000
下面的调用使用尖括号把标号括起来,其原因是标号内有一个空格:mShowRegister <Stack Pointer>, esp
产生输出如下:Stack Pointer=0012FFC0
实现宏的源代码如下:;------------------------------------ mShowRegister MACRO regName, regValue LOCAL tempStr ;显示寄存器名和内容。 ;接收:寄存器名,寄存器值 ;------------------------------------ .data tempStr BYTE " ®Name=",0 .code push eax ;显示寄存器名 push edx mov edx,OFFSET tempStr call WriteString pop edx ;显示寄存器内容 mov eax,regValue call WriteHex pop eax ENDM
7) mWriteSpace
宏 mWriteSpace 向控制台窗口输出一个或多个空格。可以选择性地向其传递一个整数形参,以指定空格数 ( 默认为一个 )。例如,下面的语句写了 5 个空格:mWriteSpace 5
实现mWriteSpace的源代码如下:;------------------------------------------- mWriteSpace MACRO count:=<1> ;向控制台窗口输出一个或多个空格。 ;接收:一个整数以指定空格数。 ;默认个数为l。 ;------------------------------------------- LOCAL spaces .data spaces BYTE count DUP(' '),0 .code push edx mov edx,OFFSET spaces call WriteString pop edx ENDM
8) mWriteString
宏 mWriteSrting 向控制台窗口输出一个字符串变量的内容。从宏的内部来看,它通过在同一语句行上传递字符串变量名简化了对 WriteString的调用。例如:
.data
str1 BYTE "Please enter your name: ", 0
.code
mWriteString str1
;------------------------------ mWriteString MACRO buffer:REQ ;向标准输出写一个字符串变量。 ;接收:字符串变量名。 ;------------------------------ push edx mov edx,OFFSET buffer call WriteString pop edx ENDM