masm32汇编
masm32汇编
〇、环境配置
下载安装:
- 注 Win10 下可能安装失败。(兼容打开,或关闭防火墙)
环境配置:
变量名 | 变量值 |
---|---|
include | D:\masm32\include |
lib | D:\masm32\lib |
PATH | D:\masm32\bin |
执行:
编译:
ml /c /coff eg.asm
(源程序:*.asm
,包含文件:*.inc
(列表文件:*.lst
))链接:
link /subsystem:console eg.obj [eg.lib...]
指明库文件编译:
link /OUT:eg.lib eg.obj
(目标模块文件:*.obj
,库文件:*.lib
)
事先设置好后使用:MAKE32.BAT 1.asm |
一、masm32汇编
1 基础汇编
1.1 寄存器
扩展寄存器:EAX,EBX,ECX,EDX,ESI,EDI,EBP,ESP,EIP
未扩展寄存器:CS,DS,ES,FS,GS
1.2 头文件
伪指令 | 功能 | 伪指令 | 功能 |
---|---|---|---|
.8086 | 仅接受8086指令(缺省状态) | .387 | 接受80387数学协处理器指令 |
.186 | 接受80186指令 | .No87 | 取消使用协处理器指令 |
.286 | 接受除特权指令外的80286指令 | .586 | 接受除特权指令外的Pentium指令 |
.286P | 接受全部80286指令,包括特权指令 | .586P | 接受全部的Pentium指令 |
.386 | 接受除特权指令外的80386指令 | .686 | 接受除特权指令外的Pentium Pro指令 |
.386P | 接受全部80386指令,包括特权指令 | .686P | 接受全部Pentium Pro指令 |
.486 | 接受除特权指令外的80486指令,包括浮点指令 | .MMX | 接受MMX指令 |
.486P | 接受全部80486指令,包括特权指令和浮点指令 | .K3D | 接受AMD处理器的3D指令 |
.8087 | 接受8087数学协处理器指令 | .XMM | 接受SSE,SSE2和SSE3指令 |
.287 | 接受80287数学协处理器指令 |
1.3 io32.inc中的输入输出
C语言格式符 | 子程序名 | 参数 | 常用功能 |
---|---|---|---|
printf(“%s”,a) | dispmsg | 入口:EAX=字符串地址 | 显示字符串(以0结尾) |
printf(“%c”,a) | dispc | 入口:AL=ASCII码 | 显示一个字符 |
printf(“\n”) | dispcrlf | 光标回车换行,到下一行首位置 | |
disprd | 显示8个32为通用寄存器内容(十六进制) | ||
disprf | 显示6个状态标志的状态 | ||
print(“%X”,a) | disphd | 入口:EAX=32b数据 | 以16进制显示8位数据 |
print(“%u”,a) | dispuid | 入口:EAX=32b数据 | 显示无符号十进制数 |
print(“%d”,a) | dispsid | 入口:EAX=32b数据 | 显示有符号十进制数 |
scanf(“%s”,&a) | readmsg | 入口:EAX=缓冲区地址。出口:EAX=实际输入的字符个数(不含结尾0),字符串以0结尾 | 输入一个字符串(回车结束) |
scanf(“%c”,&a) | readc | 出口:AL=ASCII码 | 输入一个字符(回显) |
scanf(“%X”,&a) | readhd | 出口:EAX=32b数据 | 输入8为十六进制数 |
scanf(“%u”,&a) | readuid | 出口:EAX=32b数据 | 输入无符号十进制数 |
scanf(“%d”,&a) | readsid | 出口:EAX=32b数据 | 输入有符号十进制数 |
2 数据表示与寻址
2.1 伪指令
;等价EQU,等号= |
2.2 变量定义
定义
- 变量 变量定义伪指令 处置表
- 变量定义伪指令 重复次数 dup(重复参数)
除了如下定义汇编还支持:Structure(结构),Record(记录),Union(联合)
老版 | 新版 | 作用 |
---|---|---|
db | byte | 1B |
dw | word | 2B |
dd | dword | 4B |
df | fword | 6B,多用于16b段选择器和32b偏移地址的48b指针地址 |
dq | qword | 8B |
dt | tbyte | 10B,多用于BCD码,浮点运算 |
2.3 变量指令
属性 | 操作符 | 作用 |
---|---|---|
地址 | [] | 将括起的表达式作为存储器地址指针 |
$ | 返回当前偏移地址 | |
offset 变量名 | 返回变量名所在段的偏移地址 | |
seg 变量名 | 返回段基地址(实地址存储模型) | |
类型 | 类型名 ptr 变量名 | 将变量名按照指定的类型使用 |
type 变量名 | 返回一个字量数值,表明变量名的类型 | |
lengthof 变量名 | 返回整个变量的数据项数(即元素数) | |
sizeof 变量名 | 返回整个变量占用的字节数 |
;伪指令,将参数表达的偏移地址作为当前偏移地址 |
3 通用数据处理指令
3.1 数据操作指令
;数据交换 |
3.2 标志位操作
指令 | 功能 | 指令 | 功能 |
---|---|---|---|
clc | 复位进位标志:CF=0 | lahf | 标志寄存器低字节内容传送到AH中 |
stc | 置位进位标志:CF=1 | sahf | AH内容传送到标志寄存器最低位 |
cmc | 求反进位标志:0变1,1变0 | pushf | 标志寄存器地16位入栈 |
cld | 复位方向标志:DF=0,串操作后地址增大 | popf | 堆栈顶部一个字量数据弹出到标志寄存器低16位 |
std | 复位方向标志:DF=1,串操作后地址减小 | pushfd | 32位标志寄存器内容全部压入堆栈 |
cli | 复位中断标志:IF=0,禁止可屏蔽中断 | popfd | 当前堆栈顶部一个双字数据弹出到标志寄存器 |
sti | 置位中断标志:IF=1,允许可屏蔽中断 |
;取ZF标志位值存入寄存器中(用于 == ) |
4 程序结构
4.1 跳转
助记符 | 标志位 | 英文含义 | 中文说明 |
---|---|---|---|
JZ / JE | ZF=1 | Jump if Zero / Equal | 等于零/相等 |
JNZ / JNE | ZF=0 | Jump if Not Zero / Not Equal | 不等于零/不相等 |
JS | SF=1 | Jump if Sign | 符号为负 |
JNS | SF=0 | Jump if Not Sign | 符号为正 |
JP / JPE | PF=1 | Jump if Parity / Parity Even | 1的个数为偶 |
JNP / JPO | PF=0 | Jump if Not Parity / Parity Odd | 1的个数为奇 |
JO | OF=1 | Jump if Overflow | 溢出 |
JNO | OF=0 | Jump if Not Overflow | 无溢出 |
JC / JB / JNAE | CF=1 | Jump if Carry / Below / Not Above or Equal | 进位/低于/不高于等于 |
JNC / JNB / JAE | CF=0 | Jump if Not Carry / Not Below / Above or Equal | 无进位/不低于/高于等于 |
JBE / JNA | CF=1 or ZF=1 | Jump if Below or Equal / Not Above | 低于等于/不高于 |
JNBE / JA | CF=0 or ZF=0 | Jump if Not Below or Equal / Above | 不低于等于/高于 |
JL / JNGE | SF != OF | Jump if Less / Not Greater or Equal | 小于/不大于等于 |
JNL / JGE | SF=OF | Jump if Not Less / Greater or Equal | 不小于/大于等于 |
JLE / JNG | SF != OF or ZF=1 | Jump if Less or Equal / Not Greater | 小于等于/不大于 |
JNLE / JG | SF=OF and ZF=0 | Jump if Not Less or Equal / Greater | 不小于等于/大于 |
4.2 分支循环
;ecx=0跳转,否则向下 |
4.3 结构体
;定义结构体 |
5 模块化编程
5.1 源程序框架
; 源程序框架 |
5.2 函数传参
ret ;无参返回:出栈返回地址 |
5.3 头文件
;引用头文件 |
5.4 宏定义
;;宏 |
宏操作符 | 作用 |
---|---|
& | 替换操作符,用于将参数与其他字符分开。如果参数紧接在其他字符之前或之后,或者参数出现在带引号的字符串中,就必须使用该伪操作符 |
<> | 字符串传递操作符,用于括起字符串。在宏调用中,如果传递的字符串实参数含有逗号、空格等间隔符号、则必须用这对操作符,以保证字符串的完整 |
! | 转义操作符,用于指示其后的一个字符作为一般字符,而不含特殊意义 |
% | 表达式操作符,用在宏调用中,表示将后跟的一个表达式的值作为实参,而不是将表达式本身作为参数 |
;; | 宏注释符,用于表示在宏定义中的注释。采用这个符号的注释,在宏展开时不出现 |
: reg | 说明宏定义设定的参数在调用时不可缺少 |
: =默认值 | 设定参数默认值 |
格式 | 功能说明 |
---|---|
if 表达式 | 汇编程序求出表达式的值,不为0满足条件 |
ife 表达式 | 汇编程序求出表达式的值,为0满足条件 |
ifdef 符号 | 符号已定义(内部定义或声明外部定义),则满足条件 |
ifndef 符号 | 符号未定义,则满足条件 |
ifb <形参> | 用在宏定义体内。如果宏调用没有用实参替代该形参,则满足条件 |
ifnb <形参> | 用在宏定义体内。如果宏调用用实参替代该形参,则满足条件 |
ifidn <字符串1>,<字符串2> | 字符串1与字符串2相同则条件满足;区分大小写 |
ifdif <字符串1>,<字符串2> | 字符串1与字符串2不相同则条件满足;区分大小写 |
ifidni <字符串1>,<字符串2> | 字符串1与字符串2相同则条件满足;不区分大小写 |
ifdifi <字符串1>,<字符串2> | 字符串1与字符串2不相同则条件满足;不区分大小写 |
5.5 简单案例
;弹窗显示hello world |
二、Windows编程
1 库调用
连接:
静态连接(.lib):连接程序会自动从库文件中抽取需要的子程序插入到可执行代码中。
动态连接(.dll):每次需要执行指定代码时才会去动态连接库中找到对应的代码执行。
库:
kernel32.dll:系统服务函数,主要处理内存管理和进度调度。
user32.dll:用户接口函数,主要控制用户界面。
gdi32.dll:图形设备函数,主要负责图形方面的操作。
;过程声明 |
2 控制台程序
句柄:32位无符号整数,用来唯一确定一个对象,如输入设备、输出设备或一个文件、图形等。
API 函数返回值保存在 EAX 中。
输出函数:
Windows 95/98 操作系统不支持以W结尾的函数。
Windows NT/2000/XP 操作系统的内置字符集是 Unicode,在这些操作系统中如果调用以A结尾的函数,操作系统会首先将ANSI字符转换成Unicode字符,然后再调用以W结尾的对应函数。
在微软MSDN文档中,函数名尾部的字母 A 或 W 被省略,汇编语言使用时需要重新声明。
;控制台函数都存在kernel32.dll中,所以要导入kernel32.lib |
3 图形化界面
;消息窗口。(在USER32.dll中)创建失败返回0 |
4 高级语言特性
;定义子程序 |
操作符(大于小于与或非同C语言) | 功能 |
---|---|
& | 位测试 |
CARRY? | CF=1? |
OVERFLOW? | OF=1? |
PARITY? | PF=1? |
SIGH? | SF=1? |
ZERO? | ZF=1? |
三、与 C++ 混合编程
1 VS配置
- 项目——生成依赖项——生成自定义——masm
- Debug模式要是x86
- x64配置方式
2 嵌入汇编
#include <iostream> |
四、DOS环境程序设计
1 DOS编程
2 串操作
3 输入输出
4 中断
五、扩展
1 浮点指令
1.1 浮点数
浮点数:
单精度:1位符号位,8位指数,23位有效数字。(D31-D0)
双精度:1位符号位,11位指数,52位有效数字。(D63-D0)
浮点寄存器:
- x87FPU浮点寄存器:80位数据寄存器,2位标记寄存器。分别是FPR0、tag0,FPR1、tag1…FPR7、tag7。
- x87FPU的8个数据寄存器存取是栈原则且首尾循环。
- 在OD中显示的是st0-st7。
标记寄存器标记:
- 00——对应数据寄存器存有有效数据。
- 01——对应数据寄存器数据为0。
- 10——对应数据寄存器数据是特殊数据,如NaN,无限大或非规格化数据。
- 11——对应数据寄存器内无数据。
浮点状态寄存器:
1.2 浮点指令
;push [] -> st |
2 多媒体指令
寄存器是MMX。使用的寄存器也是st0-7,但是名称为MM0-MM7。
3 64位指令
六、编程技巧
;清空ebx |