设为首页 加入收藏

TOP

5.10 汇编语言:汇编过程与结构(四)
2023-08-26 21:10:31 】 浏览:199
Tags:5.10 程与结
t,stdcall option casemap:none include windows.inc include kernel32.inc includelib kernel32.lib .code main PROC ; 定义局部变量,自动压栈/平栈 LOCAL var_byte:BYTE,var_word:WORD,var_dword:DWORD LOCAL var_array[3]:DWORD ; 填充局部变量 mov byte ptr ds:[var_byte],1 mov word ptr ds:[var_word],2 mov dword ptr ds:[var_dword],3 ; 填充数组方式1 lea esi,dword ptr ds:[var_array] mov dword ptr ds:[esi],10 mov dword ptr ds:[esi + 4],20 mov dword ptr ds:[esi + 8],30 ; 填充数组方式2 mov var_array[0],100 mov var_array[1],200 mov var_array[2],300 invoke ExitProcess,0 main ENDP END main

在上述示例代码中,main过程使用LOCAL指令定义了几个局部变量,包括一个字节类型的变量var_byte、一个字类型的变量var_word、一个双字类型的变量var_dword和一个包含三个双字元素的数组var_array

在代码中,我们使用mov指令填充这些变量的值。对于字节类型、字类型和双字类型的变量,使用mov byte ptr ds:[var_byte], 1mov word ptr ds:[var_word], 2mov dword ptr ds:[var_dword], 3指令将相应的常数值存储到变量中。在填充数组时,分别使用了两种不同的方式。一种方式是使用lea指令将数组的地址加载到esi寄存器中,然后使用mov dword ptr ds:[esi],10等指令将相应的常数值存储到数组中。另一种方式是直接访问数组元素,如mov var_array[0], 100等指令。需要注意,由于数组元素在内存中是连续存储的,因此可以使用[]操作符访问数组元素。

在汇编中使用LOCAL伪指令来实现自动计算局部变量空间,以及最后的平栈操作,将会极大的提高开发效率。

10.4 USES/ENTER

USES是汇编语言中的伪指令,用于保存一组寄存器的状态,以便函数调用过程中可以使用这些寄存器。使用USES时,程序可以保存一组需要保护的寄存器,汇编器将在程序入口处自动向堆栈压入这些寄存器的值。读者需注意,我们可以在需要保存寄存器的程序段中使用USES来保护寄存器,但不应在整个程序中重复使用寄存器。

ENTER也是一种伪指令,用于创建函数调用过程中的堆栈帧。使用ENTER时,程序可以定义一个名为ENTER的指定大小的堆栈帧。该指令会将新的基准指针ebp 压入堆栈同时将当前的基准指针ebp存储到另一个寄存器ebx中,然后将堆栈指针esp减去指定大小的值,获取新的基地址,并将新的基地址存储到ebp 中。之后,程序可以在此帧上创建和访问局部变量,并使用LEAVE指令将堆栈帧删除,将ebp恢复为旧的值,同时将堆栈指针平衡。

在使用USES和ENTER指令时,需要了解这些指令在具体的平台上的支持情况,以及它们适用的调用约定。通常情况下,在函数开头,我们将使用ENTER创建堆栈帧,然后使用USES指定需要保护的寄存器。在函数末尾,我们使用LEAVE删除堆栈帧。

  .386p
  .model flat,stdcall
  option casemap:none

include windows.inc
include kernel32.inc
includelib kernel32.lib

.code
  ; USES 自动压入 eax,ebx,ecx,edx
  my_proc PROC USES eax ebx ecx edx x:DWORD,y:DWORD
    enter 8,0          ; 自动保留8字节堆栈空间
    add eax,ebx
    leave
  my_proc endp

  main PROC
    mov eax,10
    mov ebx,20
    call my_proc
    
    int 3
  main ENDP
END main

10.5 STRUCT/UNION

STRUCT和UNION是汇编语言中的数据类型,STRUCT是一种复合数据类型,它将多个不同类型的变量按顺序放置在一起,并使用单个名称来引用集合。使用STRUCT时,我们可以将不同类型的变量组合成一个结构体并定义其属性,如结构体中包含的成员变量的数据类型、名称和位置。

例如,下面是一个使用STRUCT定义自定义类型的示例:

; 定义一个名为 MyStruct 的结构体,包含两个成员变量。
MyStruct STRUCT
   Var1 DWORD ?
   Var2 WORD ?
MyStruct ENDS

在上述示例代码中,我们使用STRUCT定义了一个名为MyStruct 的结构体,其中包含两个成员变量Var1Var2。其中,Var1DWORD类型的数据类型,以问号?形式指定了其默认值,Var2WORD类型的数据类型。

另一个数据类型是UNION,它也是一种复合数据类型,用于将多个不同类型的变量叠加在同一内存位置上。使用UNION时,程序内存中的数据将只占用所有成员变量中最大的数据类型变量的大小。与结构体不同,联合中的所有成员变量共享相同的内存位置。我们可以使用一种成员变量来引用内存位置,但在任何时候仅能有一种成员变量存储在该内存位置中。

例如,下面是一个使用UNION定义自定义类型的示例:

; 定义一个名为 MyUnion 的联合,包含两个成员变量。
MyUnion UNION
   Var1 DWORD ?
   Var2 WORD ?
MyUnion ENDS

在上述示例代码中,我们使用UNION定义了一个名为MyUnion的联合,其中包含两个不同类型的成员变量Var1Var2,将它们相对应地置于联合的同一内存位置上。

读者在使用STRUCTUNION时,需要根据内存分布和变量类型来正确访问成员变量的值。在汇编语言中,结构体和联合主要用于定义自定义数据类型、通信协议和系统数据结构等,如下一段代码则是汇编语言中实现结构体赋值与取值的总结。

  .386p
  .model flat,stdcall
  option casemap:none

include windows.inc
include kernel32.inc
includelib kernel32.lib

; 定义坐标结构
MyPoint Struct
  pos_x DWORD ?
  pos_y DWORD ?
  pos_z DWORD ?
MyPoint ends

; 定义人物结构
MyPerson Struct
  Fname db 20 dup(0)
  fAge  db 100
  fSex  db 20
MyPerson ends

.data
  ; 声明结构: 使用 <>,{}符号均可
  PtrA MyPoint <10,20,30>
  PtrB MyPoint {100,200,300}
  
  ; 声明结构: 使用MyPerson声明结构
  UserA MyPerson <'lyshark',24,1>
首页 上一页 1 2 3 4 5 6 下一页 尾页 4/6/6
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇两数相加 下一篇ImGui界面优化:使用图标字体、隐..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目