I have a problem. I have following x86 delphi code which is written in ASM. I need to port this to AMD64?
type
TCPUID = array[1..4] of Longint;
function GetCID : TCPUID; assembler; register;
asm
push ebx
push edi
mov edi, eax
mov eax, 1
dw $A20F
stosd
mov eax, ebx
stosd
mov eax, ecx
stosd
mov eax, edx
stosd
pop edi
pop ebx
end;
I have never programmed in assembly, does anyone know what the port would be or how I would go about changing it.
I am not Win64 assembler guru, but the next translation worked for me (tested on 64-bit free pascal):
program project1;
{$mode delphi}
{$asmmode intel}
type
TCPUID = array[1..4] of Longint;
function GetCID: TCPUID;
asm
push rbx
push rdi
mov rdi, rcx
mov eax, 1
cpuid
mov [rdi],eax
add rdi,4
mov [rdi],ebx
add rdi,4
mov [rdi],ecx
add rdi,4
mov [rdi],edx
pop rdi
pop rbx
end;
var ID: TCPUID;
begin
ID:= GetCID;
Writeln(ID[1], '-', ID[2], '-', ID[3], '-', ID[4]);
Readln;
end.
Here's my version, for both x86 and x64:
function GetCPUID: TCPUID;
asm
{$IF Defined(CPUX86)}
push ebx
push edi
mov edi, eax
mov eax, 1
xor ecx,ecx
cpuid
mov [edi+$0], eax
mov [edi+$4], ebx
mov [edi+$8], ecx
mov [edi+$c], edx
pop edi
pop ebx
{$ELSEIF Defined(CPUX64)}
mov r8, rbx
mov r9, rcx
mov eax, 1
cpuid
mov [r9+$0], eax
mov [r9+$4], ebx
mov [r9+$8], ecx
mov [r9+$c], edx
mov rbx, r8
{$IFEND}
end;
One of the nice things about x64 is that there are a lot more registers available, many of which are volatile. So we can make use of that scratch space and avoid touching main memory at all. Well obviously we have to touch main memory to return the result.
Since RBX is nonvolatile we preserve its value. All the other registers that we modify are volatile and so we need not preserve them. I can't think of any way to simplify this further.
This can readily be extended to allow the input to CPUID
to be passed as an argument:
function GetCPUID(ID: Integer): TCPUID;
asm
{$IF Defined(CPUX86)}
push ebx
push edi
mov edi, edx
xor ecx,ecx
cpuid
mov [edi+$0], eax
mov [edi+$4], ebx
mov [edi+$8], ecx
mov [edi+$c], edx
pop edi
pop ebx
{$ELSEIF Defined(CPUX64)}
mov r8, rbx
mov r9, rcx
mov eax, edx
cpuid
mov [r9+$0], eax
mov [r9+$4], ebx
mov [r9+$8], ecx
mov [r9+$c], edx
mov rbx, r8
{$ELSE}
{$Message Fatal 'GetCPUID has not been implemented for this architecture.'}
{$IFEND}
end;
This assumes a sub-leaf value of 0, passed in ECX. Again, if you wish to pass that, it is easy enough:
function GetCPUID(Leaf, Subleaf: Integer): TCPUID;
asm
{$IF Defined(CPUX86)}
push ebx
push edi
mov edi, ecx
mov ecx, edx
cpuid
mov [edi+$0], eax
mov [edi+$4], ebx
mov [edi+$8], ecx
mov [edi+$c], edx
pop edi
pop ebx
{$ELSEIF Defined(CPUX64)}
mov r9,rcx
mov ecx,r8d
mov r8,rbx
mov eax,edx
cpuid
mov [r9+$0], eax
mov [r9+$4], ebx
mov [r9+$8], ecx
mov [r9+$c], edx
mov rbx, r8
{$ELSE}
{$Message Fatal 'GetCPUID has not been implemented for this architecture.'}
{$IFEND}
end;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With