5
votes

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?

1
Not sure this warranted the d/vote.Alex James
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)Peter Cordes
@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.Zoltán Bíró

1 Answers

9
votes

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