第3章 使用masm

作者: sunnnnnnnnnny | 来源:发表于2020-12-25 08:58 被阅读0次

    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.inc
    include     user32.inc
    includelib  user32.lib
    include     kernel32.inc
    includelib  kernel32.lib
    ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    ; 数据段
    ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
            .data
    szCaption   db  'A MessageBox !',0
    szText      db  'Hello, World !',0
    ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    ; 代码段
    ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
            .code
    start:
            invoke  MessageBox,NULL,offset szText,offset szCaption,MB_OK
            invoke  ExitProcess,NULL
    ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
            end start
    
    

    程序的结构

    .386
    .model flat,stdcall
    option 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 szHello
    int 21h
    

    windows api的dll

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

    win32 api使用堆栈来传递参数
    可参考
    下载地址
    http://www.phatcode.net/articles.php?id=238#:~:text=Microsoft%20Win32%20Programmer%27s%20Reference.%20The%20Microsoft%20Win32%20Programmer%27s,always%20view%20the%20latest%20API%20information%20at%20MSDN.
    需要winhlp32.exe才能打开,这个工具的win10版本的下载地址
    https://softpedia-secure-download.com/dl/dac9bc2da8ce59b76f2f4e840b6a7e88/5fe2b789/100259976/software/authoring/winhlp32.msi

    调用api

    windows api的数据类型可参考下面这篇文章
    https://blog.csdn.net/ritman/article/details/50441717

    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 uType
    push lpCaption
    push lpText
    push hWnd
    call 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.inc
    include kernel32.inc
    

    includelib

    语法

    includelib 文件名
    或 includelib <文件名>
    
    include user32.lib
    include 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

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

    .data
    wHour   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]:byte
    local loc2
    local loc3:WNDCLASS
    

    使用

    image.png
    生成的pe文件后,反汇编得到以下指令
    image.png
    注意 FFFFFFF8表示-8 请参考https://blog.csdn.net/moshiyaofei/article/details/88353435
    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

    相关文章

      网友评论

        本文标题:第3章 使用masm

        本文链接:https://www.haomeiwen.com/subject/djkenktx.html