Delphi 7内联汇编中如何访问VAR参数记录的字段?
Delphi 7内联汇编访问VAR参数记录字段的正确方式
你的问题核心出在两个地方:VAR参数的指针处理错误,以及字段偏移的引用方式不对。
错误分析
VAR参数的指针误用:
声明var _rec: TMyRecord时,_rec在栈中存储的是传入变量的地址(即recMyRecord的首地址)。你代码里的Mov EBX,[EBX]是多余的——这一步把EBX从记录首地址变成了记录第一个字段Name的内容(Name是string类型,占4字节指针),导致后续所有地址计算都基于字符串内存而非记录内存,必然崩溃。字段偏移的引用错误:
汇编中直接写_rec.age时,Delphi编译器会将其解析为栈上参数_rec的位置加上Age字段的偏移,而不是你期望的“记录首地址+字段偏移”。正确的字段偏移应该基于记录类型本身,用offset TMyRecord.Age来获取。
修正后的代码
program compile; {$APPTYPE CONSOLE} uses SysUtils; type TMyRecord = record Name : string; Age : word; Sex : char; end; var recMyRecord : TMyRecord; procedure Test(var _rec: TMyRecord); begin ASM Mov EBX, _rec // EBX = recMyRecord的首地址(VAR参数直接给出变量地址) Mov AX, [EBX + offset TMyRecord.Age] // 正确读取Age字段的值,此时AX=99 // 也可以直接用常量偏移:因为Name是4字节string指针,Age偏移为4 // Mov AX, [EBX + 4] END; end; begin with recMyRecord do begin name := 'John Smith'; age := 99; sex := 'M' end; Test(recMyRecord); Writeln('Age: ', recMyRecord.Age); // 输出99,验证正确 Readln; end.
补充说明
- 如果需要修改字段值,直接反向操作即可:比如
Mov [EBX + offset TMyRecord.Age], AX就能修改Age的值。 - 用
offset TMyRecord.Age比硬编码常量偏移更可靠,后续修改记录结构时编译器会自动更新偏移值,避免手动维护出错。
内容的提问来源于stack exchange,提问作者Bruce Gavin
相关产品推荐
相关产品推荐

