汇编:结构体

在32位汇编中,结构体(structures)用于组织和管理复杂的数据类型,结构体可以包含多个不同类型的数据项(成员);在MASM(Microsoft Macro Assembler)中,使用结构体可以让我们更有条理地处理数据。下面是一个定义和使用结构体的示例。

结构体定义格式
复制代码
STRUCT_NAME STRUCT
    MEMBER_NAME1 TYPE1 [NUMBER_OF_ELEMENTS1] [INITIAL_VALUE1]
    MEMBER_NAME2 TYPE2 [NUMBER_OF_ELEMENTS2] [INITIAL_VALUE2]
    ; 更多成员...
STRUCT_NAME ENDS

STRUCT_NAME: 结构体的名称。

MEMBER_NAME: 结构体成员的名称。

TYPE: 成员的数据类型,如 BYTE, WORD, DWORD, DB, DW, DD 等。

NUMBER_OF_ELEMENTS: 可选,成员的元素个数,用于定义数组。

INITIAL_VALUE: 可选,成员的初始值。

示例:假设我们要定义一个表示人的结构体,其中包含姓名(字符串)和年龄(整数)。
复制代码
Person struct 
    szName db 32 dup(?)
    nAge dd ?
Person ends

在这个示例中,Person结构体包含两个成员:

  • name: 一个32字节的字符数组,用于存储人的姓名。

  • age: 一个32位的整数,用于存储人的年龄。

声明和初始化结构体变量
复制代码
.data
wolven Person <"wolven Chan",24>

这行代码声明了一个名为wolvenPerson结构体变量,并初始化其szName"wolven Chan"nAge24

访问结构体成员
复制代码
.code
main proc
    mov eax,wolven.nAge
    mov ebx,offset wolven.szName
main endp

wolvennAge成员的值移动到eax寄存器;将wolvenszName成员的地址偏移值移动到ebx寄存器。

程序执行完后的EAXEBX寄存器分别为上述结构体变量初始化时的值。

示例代码:

代码展示了如何定义一个结构体,并通过自定义过程printfS输出结构体的成员。

复制代码
.586
.model flat,stdcall
option casemap:none
​
;结构体定义
Person struct 
    szName db 32 dup(?)
    nAge dd ?
Person ends
​
;数据段
.data
szFormatS db '%s',0
wolven Person <"wolven Chan",24>
​
;代码段
.code
;①自定义过程,打印字符串
printfS proc szFormat:DWORD,szValue:DWORD   
    xor eax,eax
    mov eax,szValue
    push eax
    mov eax,szFormat
    push szFormat
    call printf
    add esp,8
    ret
printfS endp
​
;②程序入口
main proc
    mov eax,wolven.nAge
    mov ebx,offset wolven.szName
    invoke printfS,offset szFormatS,ebx
main endp
end 
结构体定义:

Person struct: 定义了一个名为Person的结构体。

szName db 32 dup(?): 一个32字节的字符数组,用于存储姓名。

nAge dd ?: 一个32位的整数,用于存储年龄。

Person ends: 结束结构体定义。

数据段:

szFormatS db '%s',0: 定义了一个以零结尾的字符串,表示格式化字符串%s,用于打印字符串。

wolven Person <"wolven Chan",24>: 定义了一个名为wolvenPerson结构体变量,并初始化szName"wolven Chan"nAge24

代码段
①自定义过程

printfS proc szFormat:DWORD,szValue:DWORD: 定义一个名为printfS的过程,接受两个参数,szFormatszValue

xor eax,eax: 将eax寄存器清零。

mov eax,szValue: 将第二个参数szValue的值移动到eax寄存器。

push eax: 将eax的值压入堆栈。

mov eax,szFormat: 将第一个参数szFormat的值移动到eax寄存器。

push szFormat: 将szFormat的值压入堆栈。

call printf: 调用C运行时库的printf函数。

add esp,8: 调整堆栈指针,移除之前压入的两个参数(每个参数占4个字节)。

ret: 返回到调用printfS的地方。

为什么自定义过程要先将第二个参数压入栈中
复制代码
在汇编中,自定义过程(函数)使用的参数传递方式与调用约定有关;展示代码采用了stdcall调用约定,在这种约定中,参数是按从右到左的顺序压入堆栈的,这样函数就可以按照从左到右的顺序来访问参数。
②程序入口(main)

mov eax,wolven.nAge: 将结构体变量wolvennAge成员的值移动到eax寄存器。

mov ebx,offset wolven.szName: 将结构体变量wolvenszName成员的地址移动到ebx寄存器。

invoke printfS,offset szFormatS,ebx: 调用自定义过程printfS,传入szFormatSwolven.szName的地址。

最后结构体变量wolven的nAge成员值被放入eax中,且黑窗口中打印szName成员内容:

相关推荐
我在人间贩卖青春5 天前
汇编之伪指令
汇编·伪指令
我在人间贩卖青春5 天前
汇编之伪操作
汇编·伪操作
济6175 天前
FreeRTOS基础--堆栈概念与汇编指令实战解析
汇编·嵌入式·freertos
myloveasuka5 天前
汇编TEST指令
汇编
我在人间贩卖青春5 天前
汇编编程驱动LED
汇编·点亮led
我在人间贩卖青春5 天前
汇编和C编程相互调用
汇编·混合编程
myloveasuka6 天前
寻址方式笔记
汇编·笔记·计算机组成原理
请输入蚊子6 天前
《操作系统真象还原》 第六章 完善内核
linux·汇编·操作系统·bochs·操作系统真像还原
myloveasuka6 天前
指令格式举例
汇编·笔记·计算机组成原理
我在人间贩卖青春7 天前
汇编之分支跳转指令
汇编·arm·分支跳转