Self is in RBX!
Your answer is wrong. On both Win64 and SysV ABIs. On Win64 the first non-floating point parameter is passed in
RCX and on Sys V it's passed in
RDI. For both ABIs RBX is considered non-volatile.
Thanks all. Just tested accessing the object (self) data field via [rcx] and that works.
You can simplyfy the assembly code a bit more (FPC's assembler readers are quite capable
):
Type Ttest = object
lowQ : qword;
highQ : qword;
{ the "nostackframe" is important! }
procedure getLow(var a : qword); assembler; nostackframe; register;
end;
procedure Ttest.getLow(var a : qword); assembler; nostackframe; register;
asm
mov rax, Self.lowQ // get self.lowQ
mov a, rax // store result in var param "a"
end;
This will result in the following assembly code for the whole of
getLow:
# [13] asm
# [15] mov rax, Self.lowQ // get self.lowQ
movq %rcx,%rax
# [16] mov a, rax // store result in var param "a"
movq %rax,%rdx
# [17] end;
ret
RAX can be used because it is a volatile register and is intended for the function result anyway. This way you don't even need to manipulate the stack.
Though I don't know why you don't let the compiler simply do its magic and access lowQ directly?
var
t: TTest;
q: QWord;
begin
t.lowQ := 42;
q := t.lowQ;
end.
# [24] q := t.lowQ;
movq U_$P$TASMTEST_$$_T(%rip),%rax
movq %rax,U_$P$TASMTEST_$$_Q(%rip)
This way there won't even be a call.
And if you should have more complex code using Pascal code and
inline would be better anyway (though as of now inlining won't work if
var or
out parameters are involved, so you should use
Result in that case).