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
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
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
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.
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
#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
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$
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
ASKER
I am working with Visual Studio 2015.
Maybe I should have mentioned it from the beginning.
Maybe I should have mentioned it from the beginning.
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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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