Link to home
Start Free TrialLog in
Avatar of zmau
zmau

asked on

Assembly code for a simple function (32 + 64 bit).

Hello experts,

The following function has some mixed C + assembly code.
This gives me some troubles, while compiling (especially when compiling for 64 bit).
I want to move this code into a separate file which contains only assembly code  (and then compile it differently - according to examples which I have).
Can anyone help ?


    __int64 gettsc()
    {
      __int64 u_timetag;
      __int64 *putimetag;
      putimetag = &u_timetag;
      u_timetag = 0;
      _asm
      {
      push edx;
      push eax;
      push esi;
      mov esi,putimetag;
      _emit 0x0f;
      _emit 0x31;
      mov [esi+4],edx;
      mov [esi],eax;
      pop esi;
      pop eax;
      pop edx;
      }
   
      return u_timetag;
    }


The first question is to have an assembly code which compiles nicely for 32 bit
A second question would be to have a second assembly code which compiles nicely for 64 bit
You can see the following two attached examples


Thanks
zmau
x86--GetCurrentProcessorNumberXP.asm
amd64--GetCurrentProcessorNumberXP.asm
Avatar of noci
noci

This IS 32bit assembly the 64bit registers are called rax, rbx, ...

https://wiki.cdot.senecacollege.ca/wiki/X86_64_Register_and_Instruction_Quick_Start

So you are looking to create a 64bit example.

You can differentiate using #ifdef between the sizes..

#if sizeof(int) ==  8
    64 bit version
#else
   32 bit version
#endif
Avatar of zmau

ASKER

Thanks a lot, but I am not sure that I understand.

Basically the code for the should be :

 __int64 gettsc()
    {
      __int64 u_timetag;
      __int64 *putimetag;
      putimetag = &u_timetag;
      u_timetag = 0;

     _asm
      {
#if sizeof(int) =  8
      push rdx;
      push rax;
      push rsi;
      mov rsi,putimetag;
      _emit 0x0f;
      _emit 0x31;
      mov [rsi+4],rdx;
      mov [rsi],rax;
      pop rsi;
      pop rax;
      pop rdx;
#else
      push edx;
      push eax;
      push esi;
      mov esi,putimetag;
      _emit 0x0f;
      _emit 0x31;
      mov [esi+4],edx;
      mov [esi],eax;
      pop esi;
      pop eax;
      pop edx;
#endif
      }
   
      return u_timetag;
    }

Is this correct ?


Zmau
the = should be == (i fixed the typo in my earlier post as well).
Yes that should be it, if the 32 bit code worked the 64 bit code should also work..
(the emit's might need to be different..  64 bit version of opcodes??) .

From: http://ref.x86asm.net/coder32.html

http://ref.x86asm.net/coder32.html#x0F31

      0F      31                  P1+                  f2            RDTSC      EAX      EDX      IA32_TIM…                  


64 bit code still needs to save edx, eax... (eAX lower half of 64 bit rAX).
pushes, pops & pointer values need to be te 64 bit  version.
@noci: at what version of gcc does the preprocessor know about  sizeof? Even at 9.9.2 I get
21:32:19$ cat a.c
int main(void)
{
#if sizeof (int) == 4
#error 8
#else
#error 4
#endif
return 0;
}                                  /* int main() */
21:34:19$ gcc a.c
a.c: In function 'main':
a.c:3:12: error: missing binary operator before token "("
    3 | #if sizeof (int) == 4
      |            ^
a.c:6:2: error: #error 4
    6 | #error 4
      |  ^~~~~
21:34:24$ 

Open in new window

K&R2 on page 232 explicitly states (with regard to #if statement)
The resulting constant expression ($A7.19) is restricted: it may not contain sizeof, a cast, or an enumeration constant.
Instead of trying to use sizeof, I think the OP's problem is resolved by:
#ifdef __x86_64
{64-bit code}
#else
{32-bit code}
#endif
N.B. to get a list of predefined macros in any environment, enter e.g. touch foo.h; cpp -dM foo.h|less;rm foo.h
Avatar of zmau

ASKER

I am working with Visual Studio 2015.
Maybe I should have mentioned it from the beginning.
Avatar of zmau

ASKER

From: http://ref.x86asm.net/coder32.html

http://ref.x86asm.net/coder32.html#x0F31

      0F      31                  P1+                  f2            RDTSC      EAX      EDX      IA32_TIM…                  


64 bit code still needs to save edx, eax... (eAX lower half of 64 bit rAX).
pushes, pops & pointer values need to be te 64 bit  version.

Thanks a lot for the answer.
I honestly do not know how to understand these words.
Actually I have no experience with ASM.

Thanks
zmau
ASKER CERTIFIED SOLUTION
Avatar of noci
noci

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial