【asm基础】汇编中的结构体

结构体的定义

在汇编中定义结构体的基本形式如下:

name STRUCT
  ;具体定义
name ENDS

具体定义中可以包含以下的内容:

1. 未定义:用“?”表示;

2. 字符串:用双引号包围;

3. 整数:可以是常量或者表达式;

4. 数组:使用DUP操作符来初始化数组;

下面是一个例子:

Employee STRUCT
  IdNum          BYTE  "000000000"  ; 9   个字节
  Lastname       BYTE  30 DUP(0)    ; 30  个字节
  Years          WORD  ?            ; 2   个字节
  SalaryHistory  DWORD 0,0,0,0      ; 16  个字节
Employee ENDS                       ; 共57个字节

上面就是一个汇编结构体的定义,但是它存在一个小问题,即结构体中的某些成员并不是对称的,这在一定程度上会影响到CPU访问成员的速度,因此可以有以下的改进:

Employee STRUCT
  Idnum          BYTE  "000000000"  ; 9   个字节
  Reserved1      BYTE  0            ; 增加一个字节,使Years能按双字节对齐
  Lastname       BYTE  30 DUP(0)    ; 30  个字节
  Years          WORD  ?            ; 2   个字节
  Reserved2      WORD  0            ; 增加两个字节,使SalaryHistory能按四字节对齐
  SalaryHistory  DWORD 0,0,0,0      ; 16  个字节
Employee ENDS                       ; 共60个字节

另外,还可以使用masm中的伪指令ALIGN来达到相同的目的:

Employee STRUCT
  Idnum          BYTE  "000000000"  ; 9   个字节
  Lastname       BYTE  30 DUP(0)    ; 30  个字节
  ALIGN          WORD               ; 增加1个字节,使Years能按双字节对齐
  Years          WORD  ?            ; 2   个字节
  ALIGN          DWORD              ; 增加2个字节,使SalaryHistory能按四字节对齐
  SalaryHistory  DWORD 0,0,0,0      ; 16  个字节
Employee ENDS                       ; 共60个字节

不过这个伪指令并不是在所有的汇编编译器上都能够使用的,所以还是建议使用前者。

结构体变量的使用

下面是结构体的以下声明:

.data
worker1    EmpLoyee <>                  ; 未初始化的结构体变量
worker2    Employee <"123456789">       ; 初始化了一部分成员的结构体变量
worker3    Employee <,"John">           ; 初始化了一部分成员的结构体变量2
worker4    Employee {, "Jack"}          ; 除了使用<>也可以使用{}
workerCount = 10
department Employee workerCount DUP(<>) ; 结构体数组

以及结构体的一般使用:

.code
main PROC
  mov worker1.SalaryHistory, 1000h        ; worker1.SalaryHistory本身就是一个内存地址了,
                                          ; 所以可以直接传值
  mov eax, worker1.SalaryHistory
  mov ebx, OFFSET Employee.SalaryHistory  ; 通过OFFSET可以得到成员在结构体中的便宜,
                                          ; 注意这里需要使用Employee,而不能使用worker1
  mov ecx, TYPE Employee                  ; 通过TYPE可以得到结构体的大小。
  call DumpRegs
  exit
main ENDP
END main

另一个稍微复杂一点的例子:

.code
main PROC
  mov edi, 0		  ; 数组偏移,第一次是0
  mov ecx, workerCount	  ; 人数,表示的是循环次数
  mov eax, 1		  ; 赋的初值,没有特殊意义
L1:
  mov (Employee PTR department[edi]).Years, ax   ; 因为Years是WORD,所以这里需要使用ax
  add edi, TYPE Employee  ; 指向像下一个结构体
  loop L1                 ; 根据ecx中的循环次数做循环,循环的时候会将ecx中的值减1

  exit
main ENDP
END main
  • 10
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值