Intel® ISA Extensions
Use hardware-based isolation and memory encryption to provide more code protection in your solutions.
1094 Discussions

x64/ia64 Assemly Instructions in Code Porting

gangti
Beginner
421 Views
refer to:
http://software.intel.com/en-us/articles/use-explicit-prototyping/#comment-26974

May someone give an answer???

Contents:
file.c
==================================================
#undef NULL
#define NULL 0
void main() {
func(NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
}
void func(char *arg1, char *arg2, char *arg3,
char *arg4, char *arg5, char *arg6,
char *arg7, char *arg8, char *arg9)
{
//
}
==================================================

When I port above code from x86 to x64/ia64, I found:
A.
In windows x64 platform, when compiled with cl
(vs2005's x64 cross compiler)the first four param
will be transferred to func with universal registers,
using mov(same as movzx) assembly instructions, so
the upper 32 bits will be zeroed.
So in the above code, arg1~arg4 will be transferred
correctly, although arg5~arg9 may have problem.

But in linux x64 platform, when compiled with cc(gcc's
component), I found the first sixth parm will be
transferred with universal registers.
So in the above code, arg1~arg6 will be transferred
correctly, although arg7~arg9 may have problem.

B.
In windows ia64 platform, when compiled with cl
(vs2005's ia64 cross compiler)the first eight param
will be transferred to func with universal registers,
using mov(upper bits will be signed extended)assembly
instruction. In this case, that is 0 extended for the
upper bits. The other params will be put in the stack
memory, but they will be first put to registers, and
then stack memory.
So in the above code, all params will be transferred
correctly.

So the questions is, whether I am right or not?
May I rely on the knowledge of intermediate assembly
code, and just modify the code as follows for windows
x64??????
==================================================
#undef NULL
#define NULL 0
void main() {
func(NULL,NULL,NULL,NULL,(char*)NULL,
(char*)NULL,(char*)NULL,(char*)NULL,(char*)NULL);
}
void func(char *arg1, char *arg2, char *arg3,
char *arg4, char *arg5, char *arg6,
char *arg7, char *arg8, char *arg9)
{
//
}
==================================================

Another questions is that, why linux x64 put the first
six params to registers while windows x64 put the first
four params to registers????
The hardware(cpu especially) is the same, so why shouldn't
the calling conventions is the same????

--the end--
0 Kudos
3 Replies
srimks
New Contributor II
421 Views
Quoting - gangti
refer to:
http://software.intel.com/en-us/articles/use-explicit-prototyping/#comment-26974

May someone give an answer???

Contents:
file.c
==================================================
#undef NULL
#define NULL 0
void main() {
func(NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
}
void func(char *arg1, char *arg2, char *arg3,
char *arg4, char *arg5, char *arg6,
char *arg7, char *arg8, char *arg9)
{
//
}
==================================================

When I port above code from x86 to x64/ia64, I found:
A.
In windows x64 platform, when compiled with cl
(vs2005's x64 cross compiler)the first four param
will be transferred to func with universal registers,
using mov(same as movzx) assembly instructions, so
the upper 32 bits will be zeroed.
So in the above code, arg1~arg4 will be transferred
correctly, although arg5~arg9 may have problem.

But in linux x64 platform, when compiled with cc(gcc's
component), I found the first sixth parm will be
transferred with universal registers.
So in the above code, arg1~arg6 will be transferred
correctly, although arg7~arg9 may have problem.

B.
In windows ia64 platform, when compiled with cl
(vs2005's ia64 cross compiler)the first eight param
will be transferred to func with universal registers,
using mov(upper bits will be signed extended)assembly
instruction. In this case, that is 0 extended for the
upper bits. The other params will be put in the stack
memory, but they will be first put to registers, and
then stack memory.
So in the above code, all params will be transferred
correctly.

So the questions is, whether I am right or not?
May I rely on the knowledge of intermediate assembly
code, and just modify the code as follows for windows
x64??????
==================================================
#undef NULL
#define NULL 0
void main() {
func(NULL,NULL,NULL,NULL,(char*)NULL,
(char*)NULL,(char*)NULL,(char*)NULL,(char*)NULL);
}
void func(char *arg1, char *arg2, char *arg3,
char *arg4, char *arg5, char *arg6,
char *arg7, char *arg8, char *arg9)
{
//
}
==================================================

Another questions is that, why linux x64 put the first
six params to registers while windows x64 put the first
four params to registers????
The hardware(cpu especially) is the same, so why shouldn't
the calling conventions is the same????

--the end--

Ans.: The calling convention for 64-bit Windows is - the first parameter is transferred in RCX if it is an integer or in XMM0 if it is a float or double, second in RDX or XMM1, third in RB or XMM2 and fourth in R9 or in XMM9. No more than 4 parameters can be transferred in registers, ragardless of types. Any further parameters are transferred on the st...









0 Kudos
gangti
Beginner
421 Views

I appreciate you answer of my question, and the whole knowledge of calling conventions.

My problem is that I just want tomodify the arguments from 5 to 9 as following
code shows, for windows x64.Am I right or not?
I want to get an official answer from intel to persuade my boss. So I am looking
forward to you reply...
==================================================
#undef NULL
#define NULL 0
void main() {
func(NULL,NULL,NULL,NULL,(char*)NULL,
(char*)NULL,(char*)NULL,(char*)NULL,(char*)NULL);
}
void func(char *arg1, char *arg2, char *arg3,
char *arg4, char *arg5, char *arg6,
char *arg7, char *arg8, char *arg9)
{
//
}
==================================================

Though another way to approach this is to give an explictit prototype, I give the
above approach first.It's apity that I cannot change the approach now.
0 Kudos
jimdempseyatthecove
Honored Contributor III
421 Views

Use function prototype

[cpp]#undef NULL
#define NULL 0
// declare forward reference to function func
void func(char *arg1, char *arg2, char *arg3, 
char *arg4, char *arg5, char *arg6, 
char *arg7, char *arg8, char *arg9);

void main() {
  func(NULL,NULL,NULL,NULL,NULL,
  NULL,NULL,NULL,NULL);
}

void func(char *arg1, char *arg2, char *arg3, 
char *arg4, char *arg5, char *arg6, 
char *arg7, char *arg8, char *arg9)
{
//
}
[/cpp]
0 Kudos
Reply