博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
第3章 使用masm
阅读量:2061 次
发布时间:2019-04-29

本文共 4934 字,大约阅读时间需要 16 分钟。

1. win32汇编程序的结构

例子

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>; Sample code for < Win32ASM Programming 3rd Edition>; by 罗云彬;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>; Hello.asm; 使用 Win32ASM 写的 Hello, world 程序;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>; 使用 nmake 或下列命令进行编译和链接:; ml /c /coff Hello.asm; Link /subsystem:windows Hello.obj;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>        .386 ;指定使用的指令集        .model flat,stdcall ;指定内存模式和语言模式(即程序的调用模模式),影响最后生成的可执行文件                ;stdcall WINDOWS api使用stdcall模式 规定了参数传递的次序        option casemap:none ;定义了程序中的变量和子程序名大小写敏感;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>; Include 文件定义;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>include     windows.incinclude     user32.incincludelib  user32.libinclude     kernel32.incincludelib  kernel32.lib;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>; 数据段;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>        .dataszCaption   db  'A MessageBox !',0szText      db  'Hello, World !',0;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>; 代码段;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>        .codestart:        invoke  MessageBox,NULL,offset szText,offset szCaption,MB_OK        invoke  ExitProcess,NULL;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>        end start

程序的结构

.386.model flat,stdcalloption casemap:none
<一些include语句>
.stack [堆栈段 的大小] ;不必定义,系统会自动分配 可读可写可执行 可用于缓冲区溢出.data
<一些初始化过的变量定义>
;可读可写的数据,存放在pe文件的_DATA节中.data?
<一些没有初始化过的变量定义>
;未定义变量,临时变量在PE文件的_BSS节.const
<一些常量定义>
;可读不可写.code ;在PE文件的_TEXT节 不可写的,可通过修改PE头来可写
<代码>
<开始标号>
<其它语句>
end 开始标号 ;指定程序的开始位置,由开始标号指定,被其它程序调用时可不指定入口;;表示 注释 \用来换行 \后面可加注释

2. 调用API

在DOS汇编程序中,使用软中断来调用系统api

如打印字符

mov ah,9 ;中断的编号 9表示屏幕显示  需要查询中断表mov dx, offset szHelloint 21h

windows api的dll

kernel32.dll 系统服务功能 如内存管理、任务管理和动态链接等gdi32.dll  图形设备功能user32.dll 用户接口功能 建立窗口和传送消息Wsock32.dll TCP/IP协议通信

win32 api使用堆栈来传递参数

可参考
下载地址.
需要winhlp32.exe才能打开,这个工具的win10版本的下载地址

调用api

windows api的数据类型可参考下面这篇文章

MessageBox的定义

int MessageBox(    HWND hWnd,  // handle of owner window    LPCTSTR lpText, // address of text in message box    LPCTSTR lpCaption,  // address of title of message box      UINT uType  // style of message box   );

使用汇编调用

伪指令 invoke

invoke MessageBox,NULL,offset szText,offset szCaption,MB_OK

等价于

push uTypepush lpCaptionpush lpTextpush hWndcall MessageBox

api的返回值

返回值 的类型对于汇编程序来说只有dword类型,存放于eax中

若返回值 不能存储在eax中,会将返回值缓冲区的地址存入eax

函数 的声明

函数名 proto [距离] [语言] [参数1]:数据类型,[参数2]:数据类型...

MessageBox的声明

MessageBox Proto hWnd:dword,lpText:dword,lpCaption:dword,uType:dword参数名可省略MessageBox Proto :dword,:dword,:dword,:dword

include语句

语法

include 文件名或 include 
<文件名>
include user32.incinclude kernel32.inc

includelib

语法

includelib 文件名或 includelib 
<文件名>
include user32.libinclude kernel32.lib

函数的代码放在dll文件中

函数的定位信息和参数数目等信息存放在Lib文件中
链接器和链接时会到指定的库文件中去找api函数的位置信息

API参数中的等值定义

在windows api定义了许多常量,包含在windows.inc文件中

需要在汇编程序中包含这个文件

include windows.inc

3. 标号 变量和数据结构

MASM变量的命名规范

可以用字母 数字 下划线和@ $ ?第一个符号不能是数字长度小于240不能使用指令名等关键字在作用域中必须唯一

3.1 标号

语法

标号名:   目的指令 ;在当前 的子程序中跳转或标号名::  目的指令 ;在当前程序中跳转

当用@@作标号时,可以用@F 和@B来引用 @F表示本条指令后的第一个@@标号,@B表示本条指令前的第一个@@标号,程序中可以有多个@@标号

image.png

3.2 全局变量

数据类型

image.png

只有在定义全局变量时可使用缩写

示例

.datawHour   dw ?  ;word类型未初始化wMinute  dw   10  ;word类型变量wMinute 值为10_hWnd    dd   ?  ;双字类型 未初始化word_Buffer  dw 100 dup (1,2)  ;定义了一个word数组  1,2重复100遍szBuffer  byte  1024 dup (?) ;定义了一个1024字节的缓冲区szText db 'Hello World!'  ;定义了一个12字节的字符串szText db 'hello world!',0dh,0ah,'jlfajflafj',0dh,0ah,0;byte类型变量定义时,引号定义的字符串和数值定义的方法可混用

未初始化的变量为0

3.3 局部变量

使用栈来管理局部变量

语法

local 变量名1[[重复数量][:类型]]

不能使用类型缩写

定义dword类型的变量时,可省略类型
不能使用dup指令
不能与全局变量重名
例子

local loc1[1024]:bytelocal loc2local loc3:WNDCLASS

使用

image.png
生成的pe文件后,反汇编得到以下指令
image.png
注意 FFFFFFF8表示-8 请参考
leave指令 相当于 mov esp,ebp pop ebp
上例中局部变量排列的顺序
局部变量的初始值是随机的,使用局部变量一定要初始化

3.4 数据结构

C语句结构体的定义

汇编中结构体的定义

汇编定义
使用结构体来定义数据

引用

mov eax,stWndClass.lpfnWndProc

也可以这样

image.png

嵌套定义结构体

image.png

movzx指令

sizeof lengthof

sizeof 变量名 类型名或数据结构 名lengthof 变量名 类型名或数据结构名sizeof伪指令可以取变量 数据类型或数据结构以字节为单位的长度lengthof可以取变量中数据的项数

lstrlen用于记录字符串的长度

offset 对于全局变量

用于获取变量的地址 编译时已经确定
对于局部变量是使用ebp来取其地址的,所以不可以用offset来获取它的地址

addr

addr 局部变量名和全局变量名
当addr后接全局变量时,编译器会自动按照offset的用法来
当addr后接局部变量时,编译器会自动用lea指令先把地址取到eax中,然后用eax来代替变量地址使用

4 使用子程序

4.1 子程序的定义

子程序的定义
image.png

4.2 参数传递和堆栈平衡

image.png
image.png

C类型和stdcall类型是先把右边的参数先压入堆栈。

PASCAL类型先把左边的参数压入堆栈
C类型的调用者使用call指令完成后,自行用add esp,8指令将参数空间清除
PASCAL和stdcall则不管这个事,子程序会使用ret 8来实现堆栈平衡
win32 api的调用方式是stdcall

ebp指针 参数和局部变量的关系

5 高级语法

5.1 条件测试

条件测试伪指令会被翻译成cmp test之类的汇编指令

image.png

限制 表达式的左边只能是变量或寄存器,不能为常数

表达式的两边不能同时为变量,但可以同时为寄存器
标志位

image.png

5.2 分支语句

MASM的if伪指令和对应的汇编指令

注意.if 和if的区别

image.png

5.3 循环语句

伪指令语法

伪指令

伪指令

汇编指令

对应的汇编指令

6 代码风格

6.1 变量和函数的

匈牙利表示法

image.png

约定

image.png

转载地址:http://ieqlf.baihongyu.com/

你可能感兴趣的文章
工程师应该怎么学习
查看>>
记一次 Kubernetes 机器内核问题排查
查看>>
记一次 Kubernetes 中严重的安全问题
查看>>
在业务系统中寻找技术含量
查看>>
拥抱云原生,基于 eBPF 技术实现 Serverless 节点访问 K8S Service
查看>>
有了 Docker 就不用再深入学习 MySQL 了?
查看>>
持续监控集群中的镜像漏洞
查看>>
终于可以像使用 Docker 一样丝滑地使用 Containerd 了!
查看>>
张磊大神的《深入剖析Kubernetes》终于出书啦!
查看>>
KubeSphere 团队(青云QingCloud) 全职开源职位等你加入!
查看>>
真棒!3 种方法限制 Pod 磁盘容量,瞬间豁然开朗
查看>>
高并发、高可用、高可靠微服务架构7大顶级设计思维模型
查看>>
如何使用 registry 存储的特性
查看>>
凉了,stress 无论如何也无法打满 CPU
查看>>
除了 k8s,留给 k 和 s 中间的数字不多了!
查看>>
使用 wrk 压测并精细控制并发请求量
查看>>
Ceph 故障排查笔记 | 万字经验总结
查看>>
使用 Go 从零开始实现 CNI 可还行?
查看>>
KubeSphere 3.1.0 GA:混合多云走向边缘,让应用无处不在
查看>>
Containerd 1.5 发布:重磅支持 docker-compose!
查看>>