Accessing the first byte AFTER a Delphi record, class etc. from assembly routine
Asked Answered
F

1

5

It’s well known for assembly coders in Delphi that any fields of a record, class etc. can be accessed from an asm code routine as shown in the example below:

type 

THeader = packed record
  field1: uint64;
  field2: uint32;
end;

(* some code here *)

asm
  mov rax, [rcx + THeader.field1]
  mov edx, [rcx + THeader.field2]
end;

But what if – as the name suggests – this is just a header of a big, unpredictable sized data stream and I want to access the actual start position of the data stream (that is, the first byte after the header)? A simple solution might be the one shown below (but I prefer something less unnatural, without defining a constant):

type

  THeader = packed record
    field1: uint64;
    field2: uint32;
  end;
  (* start_of_data_stream: byte; *)

const 
  SIZEOFTHEADER = sizeof(THeader);

(* some code here *)

asm
  mov al, [rcx + SIZEOFTHEADER] (* [rcx + THeader.start_of_data_stream] *)
end;

Any better ideas, maybe?

Five answered 22/1, 2020 at 12:21 Comment(3)
Not sure this warranted the d/vote.Scratchboard
BTW, in C you can do this without inline asm, with a flexible array member at the end of a struct. But if you are going to use asm, prefer movzx eax, byte [rcx + ...] for loading a single byte on modern CPUs. Merging into the low byte of an existing register (mov to AL) can be more expensive than a zero-extending load (movzx)Zareba
@PeterCordes Need Delphi and definitely asm for this particular purpose, so I have no choice here. Anyway, thanks for the zero extending load remark, at least this surely deserves an upvote.Has
G
9

You can use TYPE(typename) to find the size of the type in an asm expression. For example:

mov al, [rcx + TYPE(THeader)]

This (together with a number of other useful operators) is documented: http://docwiki.embarcadero.com/RADStudio/en/Assembly_Expressions#Expression_Operators

Grizzle answered 22/1, 2020 at 12:40 Comment(4)
Note that I did not know that this operator existed until I read the documentation.Grizzle
Right answer. Short, elegant. period.Has
Reading that page: "Numeric constants must be integers, and their values must be between 2,147,483,648 and 4,294,967,295." Looks like they dropped a -.Woodruff
@Woodruff indeed, and I bet that they also forgot to update it to account for 64 bitGrizzle

© 2022 - 2024 — McMap. All rights reserved.