基础结构
.386 .model flat,stdcall option casemap:none <一些include语句> .stack [堆栈段的大小] .data <一些初始化过的变量定义> .data? <一些没有初始化过的变量定义> .const <一些常量定义> .code <代码> <开始标号> <其他语句> end 开始标号
;这里是注释 分行的办法是在一行的最后用反斜杠(\)做换行符
变量定义初始值放.data 未初始值.data? ;定义在 .data?段中不会增大 .exe文件的大小
表3.2 变量的类型
名 称 表示方式 缩 写 长度(字节) | |||
字节 |
byte |
db |
1 |
字 |
word |
dw |
2 |
双字(doubleword) |
dword |
dd |
4 |
三字(farword) |
fword |
df |
6 |
四字(quadword) |
qword |
dq |
8 |
十字节BCD码(tenbyte) |
tbyte |
dt |
10 |
有符号字节(signbyte) |
sbyte |
|
1 |
有符号字(signword) |
sword |
|
2 |
有符号双字(signdword) |
sdword |
|
4 |
单精度浮点数 |
real4 |
|
4 |
双精度浮点数 |
real8 |
|
8 |
10字节浮点数 |
real10 |
|
10 |
szBuffer db 100 * 1024 dup (?)
szChar db ‘Hello, world;‘,0dh,0ah
1. 局部变量的定义
MASM用local伪指令提供了对局部变量的支持。定义的格式是:
local 变量名1[[重复数量]][:类型],变量名2[[重复数量]][:类型]……
local loc1[1024]:byte ;例1
local伪指令必须紧接在子程序定义的伪指令proc后、其他指令开始前,这是因为局部变量的数目必须在子程序开始的时候就确定下来
3. 获取变量地址
全局变量 mov 寄存器,offset 变量名
局部变量 lea eax,[ebp-4]
该指令可以在运行时按照ebp的值实际计算出地址放到eax中。
如果要在invoke伪指令的参数中用到一个局部变量的地址,该怎么办呢?参数中是不可能写入lea指令的,用offset又是不对的。MASM对此有一个专用的伪操作符addr,其格式为:
addr 局部变量名和全局变量名
当addr后跟全局变量名的时候,用法和offset是相同的;当addr后面跟局部变量名的时候,编译器会自动用lea指令先把地址取到eax中,然后用eax来代替变量地址使用。注意addr伪操作符只能在invoke的参数中使用
调用API
原型 MessageBox Proto hWnd:dword,lpText:dword,lpCaption:dword,uType:dword
调用 invoke MessageBox,NULL,offset szText,offset szCaption,MB_OK 或
push uType
push lpCaption
push lpText
push hWnd
call MessageBox
函数的声明
函数名 proto [距离] [语言] [参数1]:数据类型,[参数2]:数据类型,...
例 参数名可省略
MessageBox Proto hWnd:dword,lpText:dword,lpCaption:dword,uType:dword
MessageBox Proto :dword,:dword,:dword,:dword