On 21/08/15 15:24, Jeffrey Walton wrote: > I'm trying to compile some C code with inline assembly. I already have > the ASM code, so I don't need anything generated. Effectively, all I > need to do is map a C variable to an ASM symbolic name so I can use > the variables directly in MASM-like fashion. There are a number of issues here. I am not a particular expert on inline assembly, and the experience I have is all on embedded targets rather than x86. But maybe I can be of some help, so you know what to look for in the gcc manuals or general web search. First, gcc supports two inline assembly syntaxes for the x86. The default one (due to tradition on *nix and inertia) is AT&T, and it has a number of differences from the Intel assembly syntax used by MASM. You have two options - learn (or copy from the web) the difference so that you can use AT&T syntax in such inline assembly (this is the best option, I think, since it is the default syntax). Or learn the settings, command-line options, pragmas, or whatever it takes to enable MASM syntax in gcc. I have no idea what these might be, since I don't use them myself, but I bet the gcc documentation can give you a hint :-) Second, you are trying to do pushes, pops, register allocations, etc., manually in your assembly. Don't do that - let gcc's inline assembly do it. It is much safer (it will work regardless of other code, inlining, optimisations, etc.), easier, and clearer. It is also often faster, though I doubt that matters here. When you try to use registers or variables like this behind the compiler's back, you will cause yourself trouble - gcc does not know what you have done unless you tell it clearly in the clobber lists. In general assembly code, this lets gcc pick the registers or memory modes to use - in cases like this where you have specific register requirements for the assembly, you use constraints that tell gcc to put variables into the specific registers. <http://softpixel.com/~cwright/programming/simd/cpuid.php> It is common for inline assembly in gcc to have nothing more than a single instruction such as "cpuid" - all the "housekeeping" register and variable manipulation is generated by the compiler. Note that this is in contrast to inferior compilers such as MSVC, where you are expected to re-invent the wheel for inline assembly (with no guarantee that the same wheel will fit on the next version of the compiler). Thirdly, as far as I understand it gcc has better ways of detecting the capabilities, such as builtins for checking for given capabilities that you might want to use : <https://gcc.gnu.org/onlinedocs/gcc/x86-Built-in-Functions.html> There is also the "cpuid.h" header that has a cpuid function - it is better to use this than writing the inline assembly yourself. mvh., David > > I'd like to use a constraint that says, "this is a C variable", but > there does not seem to be one. I'd also like to use a "no constraint" > specifier because all I am doing is mapping C names to ASM symbolic > names, but there does not seem to be one. An empty constraint string > on outputs produces an error. > > I think the next closet constraint is the "X" one, but its causing > trouble. For example, with "X", the machinery is doing nonsensical > things like (from --save-temps): > > /APP > # 155 "cpu.cpp" 1 > .att_syntax > .att_syntax > pushl %ebx > movl $-2147483647, %eax > movl $0, %ecx > cpuid > movl %eax, %xmm0 > movl %ebx, %xmm1 > movl %ecx, %ebp > movl %edx, %xmm2 > popl %ebx > > How do I (1) map C variables to ASM symbolic names and (2) tell the > machinery to *not* generate any code because I've already provided it. > > ********** > > Here's the MASM-like code I am trying to use: > > "\t pushl %%ebx \n" > > "\t movl %[__FUNC], %%eax \n" > "\t movl %[__SUBFUNC], %%ecx \n" > > "\t cpuid \n" > > "\t movl %%eax, %[__EAX] \n" > "\t movl %%ebx, %[__EBX] \n" > "\t movl %%ecx, %[__ECX] \n" > "\t movl %%edx, %[__EDX] \n" > > "\t popl %%ebx \n" > > __FUNC, __SUBFUNC, etc shadow a 32-bit C variable. That's all they do. > > ********** > > Here's the stream of errors its producing: > > g++: warning: -pipe ignored because -save-temps specified > cpu.s: Assembler messages: > cpu.s:129: Error: operand type mismatch for `mov' > cpu.s:130: Error: operand type mismatch for `mov' > cpu.s:131: Error: operand type mismatch for `mov' > cpu.s:153: Error: operand type mismatch for `mov' > cpu.s:154: Error: operand type mismatch for `mov' > cpu.s:156: Error: operand type mismatch for `mov' > cpu.s:342: Error: operand type mismatch for `mov' > cpu.s:473: Error: operand type mismatch for `mov' > cpu.s:474: Error: operand type mismatch for `mov' > cpu.s:475: Error: operand type mismatch for `mov' > cpu.s:497: Error: operand type mismatch for `mov' > cpu.s:498: Error: operand type mismatch for `mov' > cpu.s:500: Error: operand type mismatch for `mov' > cpu.s:684: Error: operand type mismatch for `mov' >