#### Archived

This topic is now archived and is closed to further replies.

# inline assembly code in c++???

This topic is 6050 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Now that I''ve got all my header files I need to know how to convert some code. This is what I''m useing under windows, I need to convert it to something that can compile under linux... __asm{ // cli pushfd pop eax mov ebx,eax xor eax, 0x00200000 push eax popfd pushfd pop eax // sti cmp eax,ebx jz NO_CPUID mov [CPUID_AVAILABLE] , 0x01 NO_CPUID: } I''ve tryed... asm pushfd asm pop eax asm mov ebx,eax asm xor eax,0x00200000 asm push eax asm popfd asm pushfd asm pop eax asm cmp eax,ebx asm jz NO_CPUID asm mov [CPUID_AVAILABLE], 0x01 asm NO_CPUID: and... asm{ pushfd pop eax mov ebx,eax xor eax,0x00200000 push eax popfd pushfd pop eax cmp eax,ebx jz NO_CPUID mov [CPUID_AVAILABLE], 0x01 NO_CPUID: } I even tryed replacing asm with _asm or __asm and I keep getting parse errors, any help would be appreciated...

##### Share on other sites
Assuming you''re using GCC...

Inline ASM with GCC is *very* different from VC++. Be prepared for statements like:
  asm("cld\n\t" "rep\n\t" "stosl" : : "c" (someVar), "a" (someOtherVar), "D" (extraVar) : "%ecx", "%edi");

~~~~~~~~~~
Martee

##### Share on other sites
As Martee has pointed out, GCC inline assembly is a different world from MSVC++. GCC uses GAS (the GNU Assembler) as its assembler, which employs a rather different syntax. His pointer to the Linux Documentation Project is the place to go for all the details.

Good luck!

##### Share on other sites
I just had to ask: is it imperative that you use assembly? Since I gather you''re just getting used to development under Linux, perhaps you might want to concentrate on C/C++ (or your language of preference) for now. Unless you really need to write low-level code, perhaps you should save your optimizations until your software as a whole is fully functional under Linux?

Just a thought.

##### Share on other sites
ok, that still hasn''t helped I still get the same errors...

gcc -Wall -c System.cpp
System.cpp: In method ''void SYSTEM::InterogateCPU()''"
System.cpp:102: parse error before ''{''
System.cpp:82: warning unused variable ''char CPUID_AVAILABLE''
Ssytem.cpp: At top level:

void SYSTEM::InterogateCPU(){
char CPUID_AVAILABLE = 0; //<<<<<<<<<<this is line 82
// Test to see if cpuid is available
#ifdef _WIN32
__asm{
// cli
pushfd
pop eax
mov ebx,eax
xor eax, 0x00200000
push eax
popfd
pushfd
pop eax
// sti
cmp eax,ebx
jz NO_CPUID
mov [CPUID_AVAILABLE] , 0x01
NO_CPUID:
}
#elif __linux__
asm{ // <<<<<<<<<this is line 102
pushfd
pop %eax
mov %eax,%ebx
xor $0x00200000,%eax push %eax popfd pushfd pop %eax cmp %ebx,%eax jz NO_CPUID mov$0x01,CPUID_AVAILABLE
NO_CPUID:
}
#else
CPUID_AVAILABLE = 0;
#endif
if(!CPUID_AVAILABLE)
return;

For the most part I''ve been able to get most of my program to compile now as it''s mostly ansi c/c++. However there are a few parts such as this that I''m having trouble with. What this function does is interogate the cpuid function to determine what features are available. This code snippit is the first part of the function that determins if the cpuid function is available and if not returns leaving the cpu data contining some default flags indicating that all info is unknown. This is the only place I have assembly language code and it''s just anoying the heck out of me that I can''t get it to work!

##### Share on other sites
quote:
Original post by Oluseyi
I just had to ask: is it imperative that you use assembly?

Yes, unless you know another way to call the cpuid function.

quote:
Original post by Oluseyi
Since I gather you''re just getting used to development under Linux, perhaps you might want to concentrate on C/C++ (or your language of preference) for now. Unless you really need to write low-level code, perhaps you should save your optimizations until your software as a whole is fully functional under Linux?

Just a thought.

My thought too. This one function could be completly bypassed in linux and one or two other minor changes made and the program should still work. On the other hand I want this to function work!

##### Share on other sites
Head over to linuxassembly.org, they might have some info you want.

Also, don''t you need a ; after the asm{} thing? I''m not sure because I do my asm in nasm then link the .o files.

##### Share on other sites
Head over to linuxassembly.org, they might have some info you want.

Also, don''t you need a ; after the asm{} thing? I''m not sure because I do my asm in nasm then link the .o files.

##### Share on other sites
quote:
Original post by gph-gw
Head over to linuxassembly.org, they might have some info you want.

Also, don''t you need a ; after the asm{} thing? I''m not sure because I do my asm in nasm then link the .o files.

Great link, I''ve almost got it all working now. And yes it needed a semicolon and it was also supposed to be () and not {} pluss the asm needed double underlines before AND after it __asm__
I''ve now got almost all the assembly code compiling. I just have two more problems if you (or anyone) can help me figure it out...

the first is I have to push and pop the eflags register (pushfd, popfd) I can''t however find the equivelant operation under linux and they come up with the warning "no such 386 instruction"

example...
"pushfd\n\t"
produces the error "/tmp/ccjs1zp.s: 305: no such 386 instruction: ''pushfd''"

the next problem I have is durring linking. I have to access several C variables and I end up with the errors "undefined reference to ''variable name''" but it compiled fine.

example...
int info = 0;
__asm__(
"mov $0x01,%eax\n\t" "cpuid\n\t" "mov$info,%eax\n\t"
);
then I get the error "System.o(.text+0x30a): undefined reference to ''info''" durring linking

I''ll keep working on it myself but if anyone has any tips please let me know,
thx,

##### Share on other sites
You can''t directly use variables in inline ASM. I think this might do what you''re looking for:

int info = 0;
__asm__(
"mov $0x01,%eax\n\t" "cpuid\n\t" :"=a"(info) ); ~~~~~~~~~~ Martee #### Share this post ##### Link to post ##### Share on other sites quote: Original post by Martee You can''t directly use variables in inline ASM. I think this might do what you''re looking for: int info = 0; __asm__( "mov$0x01,%eax\n\t"
"cpuid\n\t"
:"=a"(info)
);

~~~~~~~~~~
Martee

Tryed that, it generates parse errors (as does any of the input output syntexing stuff) I can''t even get the sample code from linuxassembly.org to compile with out the same errors. However they do also say that the way I have it should work and at least it compiles, but it then just can''t resolve the variables in the linker

##### Share on other sites
main() {    int info = 0;     __asm__ (        "mov \$0x01, %%eax        cpuid"        : "=edx" (info)    );     printf("cpuid=%d\n", info);     if (info & 0x00800000) printf("MMX supported\n");    if (info & 0x00200000) printf("SSE supported\n");    if (info & 0x00400000) printf("SSE2 supported\n");     return 1;}

compiles (note the double % on eax in the instructions. that's needed when you have an input/output/modifier).

After careful deliberation, I have come to the conclusion that Nazrix is not cool. I am sorry for any inconvienience my previous mistake may have caused. We now return you to the original programming

Edited by - Godfree^ on July 21, 2001 8:52:43 AM

Edited by - Godfree^ on July 21, 2001 8:54:45 AM

##### Share on other sites
Thanks Godfree^, That''s it! MY PROGRAM WORKS! That''s what I missed. When I went back and looked at linux assembly.org again I realized that I must have missed that part.
Thanks to everyone that helped! And happy coding...

##### Share on other sites
Well, not entirly...
I went back through all the code cleaning up my comments and getting rid of all the commented out test lines of code and found that I still had one section commented out becuase it had anotherer error, the following is copyed from a previous post of mine...

I have to push and pop the eflags register (pushfd, popfd) I can''t however find the equivelant operation under linux and they come up with the warning "no such 386 instruction"

example...
"pushfd\n\t"
produces the error "/tmp/ccjs1zp.s: 305: no such 386 instruction: ''pushfd''"

I''ve searched Sandpile.org and can''t find any info there eather.
thanks,
Rob

##### Share on other sites
Well, I found it...
pushfd in msvc is pushf in gas.
I figured it out by looking at the disasembly of my win32 version to get the opcode then looked up the opcode at sandpile.org to get the mnemonic.

Again, thanks for the help everyone.

##### Share on other sites
Why don''t you just read out /proc/cpuinfo for CPUID on Linux?

Of course this thread was worth it for the sake of learning ASM, but the /proc/cpuinfo can give you other details (esp. on SMP systems).

cu,
Prefect

One line of sourcecode says more than a thousand words.

##### Share on other sites
Prefect, parsing /proc/cpuinfo can be quite a hefty chunk of code, where cpuid is a lot quicker, and you get a nice value which you can check bits on.

It''s more efficient to use cpuid....