zoukankan      html  css  js  c++  java
  • Win32汇编_变量

    Win32汇编_变量

    全局变量:
    全局变量的作用域是整个程序,Win32汇编的全局变量定义在.data.data?段内,可以同时定义变量的类型和长度.
    格式是:
    变量名     类型   初始值1, 初始值2, …
    变量名     类型   重复数量  dup  (初始值1, 初始值2, …)

    clip_image002

    :
    .data         ;
    全局变量的类型才可以用缩写
    wHour          dw       ?                     ;
    未初始化的word类型变量
    wMinute       dw       10                    ;
    初始化为10word类型变量
    _hWnd         dd       ?                       ;
    未初始化dword类型的变量
    Word_Buffer  dw       100  dup  (1, 2)    ;word
    类型数组,初始化0001,0002,0001,0002,…
    szBuffer        Byte     1024 dup (?)        ;byte
    数组,未初始化(未初始化其实就是全0)
    szText          db       ‘Hello, World!’        ;
    一个字符串
    ;
    byte类型变量的定义中,可以用引号定义字符串和数值定义的方法混用,假设要定义两个字符串’Hello, World!’’Hello again’,每个字符串后面跟回车和换行符,最后以一个0字符结尾.
    可以如下定义:
    szText     db   ‘Hello, World!’, 0dh, 0ah, ‘Hello again’, 0dh, 0ah, 0

    全局变量的定义中既可以指定初值,也可以用问号预留空间,data?段中,只能用问号预留空间.既然可以用问号预留空间,那么这个未初始化的值是随机的还是确定的.答题是0,所以问号指定的全局变量如果要以0为初始值的话,在程序中可以不必特地为这赋值.

    局部变量:
    局部变量的作用域是单个子程序,在进入子程序的时候,通过修改栈指针esp来预留出需要的空间,在用ret指令返回主程序之前,同样通过恢复esp丢弃这些空间,这些变量就随之无效了.它的缺点是因为空间是临时分配的,所以无法定义含有初始化值的变量,对局部变量的初始化一般在子程序中同指令完成.

    定义格式:
    local  
    变量名1[[重复次数]] [:类型], 变量名2[[重复次数]] [:类型]…
    local
    伪指令必须紧接在子程序定义的伪指令proc,其他指令开始前.
    1:
    可以有多个local语句.
    2:
    不能用类型缩写.
    3:
    定义结构体,可以用结构体的名称当做类型.
    4:
    定义dword类型的局部变量,类型可以省略
    5:
    定义数组时可以用[]括起来.
    6:
    不能使用定义全局变量的dup伪指令.
    7:
    不能和已经定义的全局变量重名.
    8:
    局部变量的起始值是随机的,所以局部变量的值一定要初始化,特别是定义结构体时
    :
    Local    loc1[1024]: Byte       ;1024
    长的字节数组
    Local    loc2                   ;
    默认为dword类型的局部变量
    Local    loc3:WNDCLASS          ;
    一个结构体类型

    结构体:
    结构体实际是由多个字段组成的数据样板,相当于自己定义的数据类型,结构体中间的每一个字段可以是字节,,双字,字符串或所有可能的数据类型.

    结构体定法如下:
    结构名   struct
    字段1   类型     ?
    字段1   类型     ?

    结构名   ends

    :
    WNDCLASS      struct
    style         DWORD     ?
    lpfnWndProc   DWORD     ?

    WNDCLASS      ends

    使用结构体在数据段中定义方法如下:
      .data?
    stWndClass  WNDCLASS   <>          ;
    未初始化的定义方法
    :
      .data
    stWndClass  WNDCLASS   <1, 1>     ;
    定义的同时指定初始值

    结构体的引用方法有好几种:
    mov    eax, stWndClass.lpfnWndProd

    在实际使用中,常常有使用指针存取结构体的情况:
    mov    esi, offset stWndClass
    mov    eax, [esi + WNDCLASS.lpfnWndProc]   ;
    注意是WNDCLASS. 而不是stWndClass.

    如果对一个结构体中的大量字段操作,上一种写法比较烦琐,MASM还有另一种方法,
    可以用assume伪指令把寄存器预先定义为结构指针:
    mov    esi, offset stWndClass
    assume esi: ptr WNDCLASS
    mov    eax, [esi].lpfnWndProc

    assume esi: nothing             ;
    不再使用esi做指针的时候得用这句取消定义
    这样寄存器可以用逗点引用字段名

    结构体的定义可以嵌套:
    NEW_WNDCLASS    struct
    dwOption        dword     ?
    oldWndClass     WNDCLASS  <>

    NEW_WNDCLASS    ends
    假设现在esi是指向一个NEW_WNDCLASS的指针,那么引用嵌套的oldWndClass中的lpfnWndProc字段时,
    就可以用下面的语句:
    mov    eax, [esi].oldWndClass.lpfnWndProc

    指定长度访问变量:
    类型  ptr  变量名
    :
    mov   eax, dword ptr szBuffer

    变量的尺寸:
    sizeof  
    变量名,数据类型,结构体  ;可以取得以字节为单位的长度
    lengthof
    变量名,数据类型,结构体  ;可以取得变量中数据的项数

    获取变量的地址:
    对于全局变量,地址在编译的时候已经由编译器确定,所以用:
    mov 
    寄存器, offset 变量名  ;offset伪指令操作是在编译时完成的

    取得局部变量的地址:
    addr 
    局部变量名或全局变量名
    后跟全局变量名时,编译器自动按照offset的用法使用,
    后面跟局部变量名的时候,编译器会自动用lea指令先把地址取到eax,然后用eax来代替变量地址.
    addr
    伪指令对局部变量取地址时,只能用在invoke的参数中,不能用在mov指令中.
    它的左边不能用eax,不然会被覆盖掉.

  • 相关阅读:
    RabbitMQ系列2 RabbitMQ安装与基础入门
    RabbitMQ系列1 什么是MQ
    数据结构与算法系列1之数组介绍与动态数组实现
    数据结构与算法系列3之从内存角度分析数组与链表的区别
    Dubbo学习
    Can't locate Pod/Text.pm问题分析及解决
    “画饼”陷阱论
    自述
    结构光、立体视觉、ToF三种3D传感原理
    游侠郭解是如何被无脑粉坑死的?
  • 原文地址:https://www.cnblogs.com/w413133157/p/1804456.html
Copyright © 2011-2022 走看看