Converting rdpmc_reference_cycles to 64-bit in MASM

107 views Asked by At

I've been using the following code in assembly language to read performance-monitoring counters using the RDPMC instruction:

rdpmc_reference_cycles proc
    mov ecx, 1h
    shl ecx, 30
    add ecx, 2
    xor eax, eax
    xor edx, edx
    rdpmc
    ret
rdpmc_reference_cycles endp

This works fine for a 32-bit environment, but now I'm transitioning to a 64-bit system and I'm having trouble adapting the code. After the rdpmc instruction, the 32-bit value in eax contains the lower half of the result, and the 32-bit value in edx contains the upper half.

I need to combine these two 32-bit values to produce a 64-bit result. However, I'm not sure how to achieve this in MASM. I've tried a few approaches, but they didn't work as expected. Could anyone guide me on how to modify this code so that it produces a 64-bit result?

2

There are 2 answers

0
Sep Roland On BEST ANSWER

The RDPMC instruction only depends on the ECX register for an input (in the 64-bit environment the high dword of RCX is ignored). And the result is returned in EDX:EAX with the high dwords of RAX and RDX reset to zero.

Your code

mov ecx, 1h
shl ecx, 30
add ecx, 2
xor eax, eax
xor edx, edx
rdpmc

is convoluted because

  • it uses 3 instructions to load ECX instead of the one mov ecx, 40000002h (equivalent to mov ecx, (1<<30) + 2).
  • it clears both RAX and RDX for no good reason

So to read the counter and deliver the 64-bit result in the single RAX register, you can do:

mov   ecx, (1<<30) + 2
rdpmc                   ; -> EDX:EAX
shl   rdx, 32
or    rax, rdx

The shl rdx, 32 shifts the contents of EDX into the high dword of RDX.
The or rax, rdx combines both dwords in RAX.
It is important to note that this or could only work well because the shl made the low dword of RDX zero, and because the rdpmc made the high dword of RAX zero.

0
daniel On

I appreciate the time everyone has taken to read and consider my question. I was struggling to adapt my 32-bit assembly code using the RDPMC instruction to a 64-bit environment, specifically in combining the 32-bit results from the EAX and EDX registers into a 64-bit result.

After some further research and trials, I've managed to find a solution that works. Here's the modified version of the code that successfully combines the results into a full 64-bit result

rdpmc_reference_cycles proc
    mov ecx, 1h
    shl ecx, 30
    add ecx, 2
    xor eax, eax
    xor edx, edx
    rdpmc
    shl rdx, 32          ; Shift the high 32 bits to their place
    or rax, rdx          ; Combine the high 32 bits (now in rdx) and low 32 bits (in eax)
    ret
rdpmc_reference_cycles endp

In this solution, I've shifted the higher 32 bits from EDX to their appropriate place in a 64-bit number (RDX). After this shift, I've combined (OR operation) the resulting RDX with the lower 32 bits from EAX. This way, I've been able to form a full 64-bit result in RAX.

I hope this solution can help others who might be facing a similar issue. I welcome any further insight or suggestions from the community. Thank you!