-
November 17th, 2009, 01:09 PM
#1
Can't seem to compile this with VC++
I'm compiling a module that was originally written for the gcc compiler. It contains a few sections of x86 assembly language that look something like this:-
Code:
asm volatile (
"fxsave (%0)"
:
: "r" (fxbuf)
: "memory"
);
The code builds fine with Cygwin gcc but MSVC++ doesn't seem to like it at all. Firstly, it doesn't seem to recognise the volatile keyword (or at least it doesn't like it being used with asm). But even if I comment that out, the rest of the code doesn't compile either. I don't know much about assmebly language but I think the colons might be screwing things up.
Can anyone suggest how I could modify this to keep MSVC++ happy?
"A problem well stated is a problem half solved.” - Charles F. Kettering
-
November 22nd, 2009, 09:40 PM
#2
Re: Can't seem to compile this with VC++
John, inline assembly is compiler specific and is not portable.
I am not sure what did you comment out but asm keyword does not exist; it is AT&T C++ keyword. VS is using MASM assembly equivalent therefore you will have to stick to MASM rules so use __asm.
I do not think VS compiler supports fxsave. I think you are trying to write some kind of floating point arithmetic’s routine. Are you sure that you have to use assembly?
There are only 10 types of people in the world:
Those who understand binary and those who do not.
-
November 23rd, 2009, 03:36 AM
#3
Re: Can't seem to compile this with VC++
This code is compiled in VS2005, does not cause exceptions an blue screen:
Code:
int _tmain(int argc, _TCHAR* argv[])
{
char memory[512];
__asm
{
fxsave memory
};
// do something ...
__asm
{
fxrstor memory
};
return 0;
}
It saves the current state of the x87 FPU, MMX technology, XMM, and MXCSR registers
to a 512-byte memory location, and then restores it from this memory. Possibly, original code writer has reasons to do this.
See details in the Intel® 64 and IA-32 Architectures Software Developer's Manual
Volume 2A: Instruction Set Reference, A-M, which can be downloaded from here:
http://www.intel.com/products/processor/manuals/
Direct download link:
http://www.intel.com/Assets/PDF/manual/253666.pdf
-
November 23rd, 2009, 09:19 PM
#4
Re: Can't seem to compile this with VC++
As I already stated I hardly ever use inline assembly. Last time I used MASM was about 20 years ago still using it for DOS.
Do you have any additional options/add-ins installed?
fxsave/fxsave is not recognized in 2005 nor is it recognized in 2005.
Is it part of the x86 family instructions set?
There are only 10 types of people in the world:
Those who understand binary and those who do not.
-
November 23rd, 2009, 10:23 PM
#5
Re: Can't seem to compile this with VC++
0100 0111 0110 1111 0110 0100 0010 0000 0110 1001 0111 0011 0010 0000 0110 0110 0110 1111 0111 0010
0110 0101 0111 0110 0110 0101 0111 0010 0010 0001 0010 0001 0000 0000 0000 0000 0000 0000 0000 0000
-
November 23rd, 2009, 11:23 PM
#6
Re: Can't seem to compile this with VC++
Interesting. . .
Thanks for the input.
There are only 10 types of people in the world:
Those who understand binary and those who do not.
-
November 24th, 2009, 01:44 AM
#7
Re: Can't seem to compile this with VC++
Thanks for all the input guys. Apart from Alex's example it's quite difficult to find any examples of using these extensions for MASM. although I did find a few examples for translating AT&T instructions into MASM instructions. Fortunately though, I also come across a site called the MASM forum. If I can't figure this out myself, I might join that forum and see if anyone can help.
"A problem well stated is a problem half solved.” - Charles F. Kettering
-
November 24th, 2009, 01:52 AM
#8
Re: Can't seem to compile this with VC++
C++ inline Assembly is not MASM, this is plain Assembly for Intel processors. Any valid Intel Assembly instructions must compile. The interesting point here why code author needs to use fxsave command. Maybe to restore processor state later with fxrstor command, in this case what does he do between these commands? Or to analyze memory region filled by this command. The answer is in the code you are working with. Understandinf this, maybe it is possible to find another way to complete the same task without Assembly.
-
November 24th, 2009, 03:08 AM
#9
Re: Can't seem to compile this with VC++
Hmmm.... you've confused me now. The syntax is definitely AT&T syntax. I'd been assuming this was the reason why it wouldn't compile under Visual C++ (remember, the code was originally written to build under gcc).
FYI the memory state doesn't get restored - but once it's in the buffer, the buffer contents get examined (a few lines later) and used to set a particular flag. The next few lines look like this:-
Code:
uint32_t mxcsr_mask = *((uint32_t*) &fxbuf[28]);
/* if the mask is zero, set its default value (from intel specs) */
if (mxcsr_mask == 0) {
mxcsr_mask = 0xffbf;
}
if (mxcsr_mask & (1<<6)) {
_flags = Flags (_flags | HasDenormalsAreZero);
}
free (fxbuf);
Last edited by John E; November 24th, 2009 at 03:11 AM.
"A problem well stated is a problem half solved.” - Charles F. Kettering
-
November 24th, 2009, 04:13 AM
#10
Re: Can't seem to compile this with VC++
Code:
char fxbuf[512];
__asm
{
fxsave fxbuf
}
// use fxbuf
I beleive this is quite enough to get the same functionality as in original code.
In the Intel document pointed in my first post, you can find memory structure returned by fxsave command. This can help to understand what is the source of these flags.
In VC++ 2005 this code is compiled. Posiibly some oldest VC version does not know this command, because it was developed when this command did not exis yet. What version do you use?
Last edited by Alex F; November 24th, 2009 at 04:39 AM.
-
November 24th, 2009, 04:32 AM
#11
Re: Can't seem to compile this with VC++
I'm using VC++2005 Express Alex. I'll try your suggestion later. Thanks.
Last edited by John E; November 24th, 2009 at 04:34 AM.
"A problem well stated is a problem half solved.” - Charles F. Kettering
-
December 2nd, 2009, 11:23 AM
#12
Re: Can't seem to compile this with VC++
Alex, if it's not too much trouble could you translate this for me from AT&T syntax into MASM syntax...?
Code:
unsigned long cpuflags = 0;
asm volatile (
"mov $1, %%eax\n"
"pushl %%ebx\n"
"cpuid\n"
"movl %%edx, %0\n"
"popl %%ebx\n"
: "=r" (cpuflags)
:
: "%eax", "%ecx", "%edx", "memory"
);
I could probably figure out the instructions mov, pushl, popl etc. But I'm not sure what 'memory' is, or 'cpuid', or what exactly it's doing with cpuflags.
[Edit...] After doing some research on the internet I realised that this line:-
: "%eax", "%ecx", "%edx", "memory"
is just a list of clobbered registers that tells gcc not to assume that these will remain intact. I couldn't find any mention of a clobbored register list in any of the examples for MASM so I assumed it wasn't relevant. Armed with this information I made a brave attempt at converting the code myself - but didn't get very far....
Code:
__asm volatile { // <-- MASM doesn't accept 'volatile' here
mov eax, 1
pushl ebx // <-- MASM didn't recognise 'pushl'
cpuid
movl edx, 0 // <-- MASM didn't recognise 'movl'
popl ebx // <-- MASM didn't recognise 'popl'
// Do something here with 'cpuflags' that I don't understand
};
Last edited by John E; December 3rd, 2009 at 12:46 AM.
"A problem well stated is a problem half solved.” - Charles F. Kettering
-
December 3rd, 2009, 01:34 AM
#13
Re: Can't seem to compile this with VC++
VC++ has CPUID sample which shows how to work with this command in inline Assembly. If you don't have this sample, download all VC++ samples from Microsoft. I hope you can find all answers there.
If VC++ doesn't support volatile, just don't use it.
I don't understand why are you talking about MASM. If you work with inline Assembly in C++, use Intel Manuals as reference, MASM is not relevant.
VC++ samples can be downloaded here:
http://www.microsoft.com/downloads/d...displaylang=en
Fill free to ask me if CPUID sample doesn't solve your problems.
-
December 4th, 2009, 03:31 AM
#14
Re: Can't seem to compile this with VC++
Thanks Alex but my problem isn't really to do with cpuid any more; it's with the other highlighted items - specifically:-
1) I don't understand the line ': "=r" (cpuflags)' in the original code. I assume it must either be saving some values to cpuflags or maybe comparing a register with cpuflags but I don't know how to implement that line in Intel syntax.
2) volatile - From what I've read on the internet, inline assembly code which doesn't produce (or appear to produce) an output will usually get optimised away to NOP by the underlying compiler. With gcc, volatile is used to prevent this optimization from happening. Maybe it's just not a problem with VC++ inline assembly? Or maybe some other technique should be used?
3) I assumed that inline assembly in VC++ would just get passed to MASM but that mustn't be true from what you said. So my third problem is that the VC++ inline assembler doesn't recognise movl, popl, and pushl. That seems strange if they are valid processor instructions. I wondered if I might just have the syntax wrong. Or should I just use mov, pop and push?
Last edited by John E; December 4th, 2009 at 03:36 AM.
"A problem well stated is a problem half solved.” - Charles F. Kettering
-
December 4th, 2009, 09:51 AM
#15
Re: Can't seem to compile this with VC++
I didn't hear about Assembly optimization in C++. AFAIK, inline Assembly is executed as is, so don't care about volatile keyword.
Don't use instructions with l in the end, it looks like defaul mov, push, pop are OK for these registers.
I strongly recommend to read Intel CPUID instruction reference. You need to understand what is the meaning of this code. Here are some reference fragments:
CPUID returns processor identification and feature information in the EAX, EBX, ECX,
and EDX registers. The instruction’s output is dependent on the contents of the EAX
register upon execution.
Table 3-20. Information Returned by CPUID Instruction
Initial EAX Value 01H
Information Provided about the Processor
EAX
EBX
ECX
EDX
Version Information: Type, Family, Model, and Stepping ID
Bits 7-0: Brand Index
Bits 15-8: CLFLUSH line size (Value ∗ 8 = cache line size in bytes)
Bits 23-16: Maximum number of addressable IDs for logical processors
in this physical package*.
Bits 31-24: Initial APIC ID
Feature Information (see Figure 3-7 and Table 3-23)
Feature Information (see Figure 3-8 and Table 3-24)
...
Looks like all this related to this code. If you cannot find somebody which can translate this to Intel Assembly, you need to do this yourself. I don't know this Assembly version. It looks like your code fragment should be:
Code:
__asm
{
mov eax, 1
push ebx
cpuid
mov edx, 0
pop ebx
};
Read also this:
http://www.microsoft.com/msj/0298/hood0298.aspx
http://www.microsoft.com/msj/0698/hood0698.aspx
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|