-
Intel syntax on MinGW ?
This is a CPUID code.
It successfully compiled on Pelles C.
Code:
//Author - Niloy Mondal
//Reference - Intel Instruction Set Reference Volume 2
#include <stdio.h>
#include <conio.h>
int main()
{
char *strFeatures[32]={ "FPU - x87 FPU on Chip",
"VME - Virtual 8086 Enhancement",
"DE - Debugging Extensions",
"PSE - Page Size Extensions",
"TSC - Time Stamp Counter",
"MSR - RDMSR and WRMSR Support",
"PAE - Physical Address Extensions",
"MCE - Machine Check Exception",
"CX8 - CMPXCHG8B instruction",
"APIC - Advanced Programmable Interrupt Controller on Chip",
" ", //Reserved
"SEP - SYSENTER and SYSEXIT",
"MTRR - Memory Type Range Register",
"PGE - PTE Global Bit",
"MCA - Machine Check Architecture",
"CMOV - Condtional Move/Compare Instruction",
"PAT - Page Attribute Table",
"PSE-32 - Page Size Extension",
"PSN - Processor Serial Number",
"CLFSH - CFLUSH Instruction",
" ", //Reserved
"DS - Debug Store",
"ACPI - Thermal Monitor and Clock Control",
"MMX - MMX Technology",
"FXSR - FXSAVE/FXRSTOR",
"SSE- SSE Extensions",
"SSE2 - SSE2 Extensions",
"SS - Self Snoop",
"HTT - Hyper Threading Tech",
"TM - Thermal Monitor",
" ", //Reserved
"PBE - Pend. Brk. En"};
char VendorID[13];
unsigned char SteppingID;
unsigned char Model;
unsigned char Family;
unsigned char ProcessorType;
unsigned char Brand;
unsigned long VersionInfo;
unsigned long FeatureInfo;
_asm
{
mov eax,0
cpuid //CPUID Instruction
mov dword ptr [VendorID],ebx
mov dword ptr [VendorID+4],edx
mov dword ptr [VendorID+8],ecx
mov byte ptr [VendorID+12],0
}
//Show the Vendor ID. Should be "GenuineIntel" if the processor is Intel"/////////////
printf("Your processor is a %s\n",VendorID);
//Store all the required information in memory////////////////////////////////////////
_asm
{
mov eax,1
cpuid //CPUID Instruction
mov VersionInfo,eax //Store Version Information
mov FeatureInfo,edx //Store Feature Information
mov Brand,bl //Store Brand Information
}
//////////////////////////////////////////////////////////////////////////////////////
//Extract the SteppingID, model and family from the bit encoded VersionInfo and display
SteppingID = VersionInfo & 0x0F; //Stepping ID
Model = (VersionInfo & 0xF0)>>4; //Model
Family = (VersionInfo & 0x0F00)>>8; //Family
ProcessorType = (VersionInfo & 3000)>>12; //Processor Type
printf("Stepping ID : %5d\n",SteppingID);
printf("Model : %5d\n",Model);
printf("Family : %5d\n",Family);
//////////////////////////////////////////////////////////////////////////////////////
//Show the Processor Type/////////////////////////////////////////////////////////////
switch(ProcessorType)
{
case 0:
printf("Processor Type : Original OEM Processor\n");
break;
case 1:
printf("Processor Type : Intel OverDrive Processor\n");
break;
case 2:
printf("Processor Type : Dual Processor\n");
break;
case 3:
printf("Processor Type : Intel reserved\n");
}
//////////////////////////////////////////////////////////////////////////////////////
//Show the Computer Brand/////////////////////////////////////////////////////////////
printf("Your Computer Brand is :- ");
switch(Brand)
{
case 0x00:
printf("This Processor does not support the brand identification feature");break;
case 0x01:
printf("Intel Celeron processor");break;
case 0x02:
printf("Intel Pentium III processor");break;
case 0x03:
printf("Intel Pentium III Xeon or Intel Celeron processor");break;
case 0x04:
printf("Intel Pentium III processor");break;
case 0x06:
printf("Mobile Intel Pentium III processor-M");break;
case 0x07:
printf("Mobile Intel Celeron processor");break;
case 0x08:
printf("Intel Pentium 4 processor");break;
case 0x09:
printf("Intel Pentium 4 processor");break;
case 0x0A:
printf("Intel Celeron processor");break;
case 0x0B:
printf("Intel Xeon processor or Xeon processor MP");break;
case 0x0C:
printf("Intel Xeon processor MP");break;
case 0x0E:
printf("Mobile Intel Pentium 4 or Intel Xeon processor");break;
case 0x0F:
printf("Mobile Intel Celeron processor");break;
case 0x13:
printf("Mobile Intel Celeron processor");break;
case 0x16:
printf("Intel Pentium M processor");break;
default:
printf("Future Processor");
}
printf("\n---------------------Press any key to continue more----------------\n");
_getch();
/////////////////////////////////////////////////////////////////////////////////////
//Show the Processor Features////////////////////////////////////////////////////////
printf("Your Processor has the following Features:-\n");
for(long i=0;i<32;i++)
{
_asm xor ebx,ebx
_asm mov ebx,i
_asm bt FeatureInfo,ebx //"bt" is opcode to test a particular bit(on/off) in a string
//The bit number to test is provided as the second operand
//The result is stored in the carry flag
_asm jnc Feature_not_installed
printf("%s\n",strFeatures[i]);
Feature_not_installed:
;
}
//////////////////////////////////////////////////////////////////////////////////////
printf("************************Programmer - Niloy Mondal***********************");
return 1;
}
So I'd like to compile it on MinGW. Since I don't wanna use the AT&T syntax, I change the code a little bit
like these :
Code:
#include <stdio.h>
int main()
{
char *strFeatures[32] = {
"FPU - x87 FPU on Chip","VME - Virtual 8086 Enhancement",
"DE - Debugging Extensions","PSE - Page Size Extensions",
"TSC - Time Stamp Counter","MSR - RDMSR and WRMSR Support",
"PAE - Physical Address Extensions","MCE - Machine Check Exception",
"CX8 - CMPXCHG8B Instruction","APIC - Advance Programmable Interrupt Controller On Chip",
" ","SEP - SYSENTER and SYSECIT","MTRR - Memory Type Range Register","PGE - PTE Global Bit",
"MCA - Machine Check Architecture","CMOV - Conditional Move/Compare Instruction",
"PAT - Page Attribute Table","PSE-32 - Page Size Extension",
"PSN - Processor Serial Number","CFLUSH - CFLUSH Instruction",
"", "DS - Debug Store","ACPI - Thermal Monitor and Clock Control","MMX - MMX Technology",
"FXSR - FXSAVE/FXRSTOR","SSE - SSE Extensions","SSE2 - SSE2 Extensions",
"SS - Self Snoop","HTT - Hyper Threading Tech","TM - Thermal Monitor",
" ","PBE - Pend. Brk. En"};
long i;
char VendorID[13];
unsigned char SteppingID;
unsigned char Model;
unsigned char Family;
unsigned char ProcessorType;
unsigned char Brand;
unsigned long VersionInfo;
unsigned long FeatureInfo;
asm(".intel_syntax noprefix\n");
asm("mov eax,0\n");
asm("cpuid\n");
asm("mov dword ptr [VendorID],ebx\n");
asm("mov dword ptr [VendorID+4],edx\n");
asm("mov dword ptr [VendorID+8],ecx\n");
asm("mov byte ptr [VendorID+12],0\n");
printf("Your processor is a %s\n",VendorID);
asm("mov eax,1\n");
asm("cpuid\n");
asm("mov VersionInfo,eax\n");
asm("mov FeatureInfo,edx\n");
asm("mov Brand,bl\n");
SteppingID = VersionInfo & 0x0F;
Model = (VersionInfo & 0xF0) >> 4;
Family = (VersionInfo & 0xF00) >> 8;
ProcessorType = (VersionInfo & 3000) >> 12;
printf("SteppingID : %5d\n",SteppingID);
printf("Model : %5d\n",Model);
printf("Family : %5d\n",Family);
switch(ProcessorType)
{
case 0:
printf("Processor type : Original OEM processor\n");
break;
case 1:
printf("Processor type : Intel OverDrive processor\n");
break;
case 2:
printf("Processor type : dual processor\n");
break;
case 3:
printf("Processor type : Intel reserved\n");
break;
}
printf("Your computer brand is : ");
switch(Brand)
{
case 0x00:
printf("This procesor doesn't support the brand identification feature");
break;
case 0x01:
printf("Intel Celeron processor");
break;
case 0x02:
printf("Intel Pentium III processor");
break;
case 0x03:
printf("Intel Pentium III Xeon or Intel Xeon processor");
break;
case 0x04:
printf("Intel Pentium III processor");
break;
case 0x06:
printf("Mobile Intel Pentium III processor");
break;
case 0x07:
printf("Mobile Intel Celeron processor");
break;
case 0x08:
printf("Intel Pentium 4 processor");
break;
case 0x09:
printf("Intel Pentium 4 processor");
break;
case 0x0A:
printf("Intel Celeron processor");
break;
case 0x0B:
printf("Intel Xeon processor or Xeon processor MP");
break;
case 0x0C:
printf("Intel Xeon processor MP");
break;
case 0x0E:
printf("Mobile Intel Pentium 4 or Intel Xeon processor");
break;
case 0x0F:
printf("Mobile Intel Celeron processor");
break;
case 0x13:
printf("Mobile Intel Celeron processor");
break;
case 0x16:
printf("Intel Pentium M processor");
break;
default:
printf("Future processor");
}
printf("\n--------------- Press any key to continue ---------------\n");
getch();
printf("Your processor has the following features :\n");
for (i = 0; i < 32; i++)
{
asm("xor ebx,ebx\n");
asm("mov ebx,i\n");
asm("bt FeatureInfo,ebx\n");
asm("jnc Feature_not_installed\n");
printf("%s\n",strFeatures[i]);
asm("Feature_not_installed: \n");
}
return 1;
}
Try to compile using this command :
gcc -masm=intel cpuid.c -o cpuid
And these are the error messages :
Code:
C:/DOCUME~1/ADMINI~1.DIV/LOCALS~1/Temp/cceKbaaa.o:cpuid.c:(.text+0x5c): undefined reference to `VendorID'
C:/DOCUME~1/ADMINI~1.DIV/LOCALS~1/Temp/cceKbaaa.o:cpuid.c:(.text+0x62): undefined reference to `VendorID'
C:/DOCUME~1/ADMINI~1.DIV/LOCALS~1/Temp/cceKbaaa.o:cpuid.c:(.text+0x68): undefined reference to `VendorID'
C:/DOCUME~1/ADMINI~1.DIV/LOCALS~1/Temp/cceKbaaa.o:cpuid.c:(.text+0x6e): undefined reference to `VendorID'
C:/DOCUME~1/ADMINI~1.DIV/LOCALS~1/Temp/cceKbaaa.o:cpuid.c:(.text+0x91): undefined reference to `VersionInfo'
C:/DOCUME~1/ADMINI~1.DIV/LOCALS~1/Temp/cceKbaaa.o:cpuid.c:(.text+0x97): undefined reference to `FeatureInfo'
C:/DOCUME~1/ADMINI~1.DIV/LOCALS~1/Temp/cceKbaaa.o:cpuid.c:(.text+0x9d): undefined reference to `Brand'
C:/DOCUME~1/ADMINI~1.DIV/LOCALS~1/Temp/cceKbaaa.o:cpuid.c:(.text+0x30e): undefined reference to `i'
C:/DOCUME~1/ADMINI~1.DIV/LOCALS~1/Temp/cceKbaaa.o:cpuid.c:(.text+0x315): undefined reference to `FeatureInfo'
collect2: ld returned 1 exit status
So how should I use Intel syntax on MinGW ?
-
Intel syntax only refers to marker characters and argument ordering. It still doesn't change that the compiler doesn't replace symbols in the assembly, i.e. it doesn't care that you use VendorID in that assembly and definitely won't replace it with the local variable's address.
You need to use GCC's register allocation method instead. See a GCC reference for more info. It's more complicated than the VC++ way, but IMO more powerful.
-
I haven't looked over your code, but if you don't want to use AT&T syntax, you can always just assemble your assembly to an object file using something like YASM/FASM and then just link it into your C program and have it call the assembly's subroutines.