码迷,mamicode.com
首页 > 编程语言 > 详细

在c语言中嵌入汇编语句,对于我来说相当难。

时间:2015-06-18 07:05:17      阅读:205      评论:0      收藏:0      [点我收藏+]

标签:

今天早上在csdn论坛上看到一个帖子http://topic.csdn.net/u/20120917/14/82f42e17-977a-4824-95bd-7b79db15d283.html:“C语言中嵌入汇编,究竟有何意义?”

 

其中看到一个例子是在c语言中插入一段汇编代码获取CPU的主频,制造商和型号的:

 

//=====================================================================================
/*                 CPUID指令是intel IA32架构下获得CPU信息的汇编指令,
                   可以得到CPU类型,型号,制造商信息,商标信息,序列号,
                   缓存等一系列CPU相关的东西。
*/
#include <windows.h>
#include <iostream>
#include <string>

using namespace std;


//用来存储eax,ebx,ecx,edx四个寄存器的信息
DWORD deax;
DWORD debx;
DWORD decx;
DWORD dedx;

void ExeCPUID(DWORD veax)  //初始化CPU
{
__asm
{
    mov eax,veax
    cpuid
    mov deax,eax
    mov debx,ebx
    mov decx,ecx
    mov dedx,edx
}
}

/*    在Intel Pentium以上级别的CPU中,有一个称为“时间戳(Time Stamp)”的部件,
    它以64位无符号整型数的格式,记录了自CPU上电以来所经过的时钟周期数。
    由于目前的CPU主频都非常高,因此这个部件可以达到纳秒级的计时精度。
    这个精确性是上述两种方法所无法比拟的。
    在Pentium以上的CPU中,提供了一条机器指令RDTSC(Read Time Stamp Counter)
    来读取这个时间戳的数字,并将其保存在EDX:EAX寄存器对中
*/
long GetCPUFreq()       //获取CPU频率,单位: MHZ
{
    int start,over;
    _asm 
    {
        RDTSC
        mov start,eax
    }
    Sleep(50);
    _asm 
    {
        RDTSC
        mov over,eax
    }
    return (over-start)/50000;
}

 

/*   把eax = 0作为输入参数,可以得到CPU的制造商信息。
     cpuid指令执行以后,会返回一个12字符的制造商信息,
     前四个字符的ASC码按低位到高位放在ebx,中间四个放在edx,最后四个字符放在ecx。
*/
string GetManID()   //获取制造商信息
{
    char ID[25];        
    memset(ID,0,sizeof(ID));
    
    ExeCPUID(0);          //初始化
    memcpy(ID+0,&debx,4); //制造商信息复制到数组
    memcpy(ID+4,&dedx,4);
    memcpy(ID+8,&decx,4);
    
    return string(ID);
}


/*  在我的电脑上点击右键,选择属性,可以在窗口的下面看到一条CPU的信息,
    这就是CPU的商标字符串。CPU的商标字符串也是通过cpuid得到的。
    由于商标的字符串很长(48个字符),所以不能在一次cpuid指令执行时全部得到,
    所以intel把它分成了3个操作,eax的输入参数分别是0x80000002,0x80000003,0x80000004,
    每次返回的16个字符,按照从低位到高位的顺序依次放在eax, ebx, ecx, edx。
    因此,可以用循环的方式,每次执行完以后保存结果,然后执行下一次cpuid。
*/
string GetCPUType()
{
    const DWORD id = 0x80000002; //从0x80000002开始,到0x80000004结束
    char CPUType[49];//用来存储CPU型号信息
    memset(CPUType,0,sizeof(CPUType));//初始化数组
    
    for(DWORD t = 0 ; t < 3 ; t++ )
    {
        ExeCPUID(id+t);
        //每次循环结束,保存信息到数组
        memcpy(CPUType+16*t+ 0,&deax,4);
        memcpy(CPUType+16*t+ 4,&debx,4);
        memcpy(CPUType+16*t+ 8,&decx,4);
        memcpy(CPUType+16*t+12,&dedx,4);
    }
    
    return string(CPUType);
}

void main() 

    cout<<"本机CPU信息如下:"<<endl;
    cout<<"CPU 主 频: "<<GetCPUFreq()<<" MHZ"<<endl;
    cout<<"CPU 制造商: "<<GetManID()<<endl;
    cout<<"CPU 型 号: "<<GetCPUType()<<endl;
    cin.get();

}

 

顿时来了兴趣,这个例子是用c++语法写的,我打开CodeBlocks简单的改了几处地方就变成c了,然后编译,出现了一大堆的错误。

 

经过一个多小时的探索,首先搞明白了,在CodeBlocks + GCC里可以嵌入汇编语句,这是肯定的。

因为我在网上找到了一个简单的例子:

#include <stdio.h>

 

//这个是vc6下面的写法

/*

int sum(int a,int b)
{
__asm
{
mov eax, [ebp+8]
add eax, [ebp+0Ch]
}
}

*/

 

//这个是gcc下面的写法

int sum(int a, int b)
{
    __asm__
    (
        "movl 8(%ebp), %eax;"
        "addl 12(%ebp), %eax;"
    );
}


int main()
{
    printf("1 + 2 = %d\n", sum(1,2));

    return 0;
}

 

程序能正常的编译和执行。

 

但为什么那个获取CPU信息的代码编译时老是提示:

too   many   memory   references   for   mov 

 

后来又找到这么一篇:http://topic.csdn.net/u/20070416/13/82e4047a-c812-43d4-a28e-e67ddf6c9ad6.html

 

网友主要提示:

你应该先学习一下ATT语法。 
__asm__   ( "subl   %0,   %%esp "   :   : "m "(paramnumber)); 
__asm__   ( "movl   %0,   %%ecx "   :   : "m "(paramnumber)); 
__asm__   ( "movl   %0,   %%esi "   :   : "m "(parameters)); 
__asm__   ( "movl   %esp,   %edi "); 
__asm__   ( "rep   movsb "); 

 

看到这个,我打算放弃改写了,这个ATT语法看着头大,不打算再搞了。

如果将来哪天需要用到,再从头学起吧。

 

2012-09-20

在c语言中嵌入汇编语句,对于我来说相当难。

标签:

原文地址:http://www.cnblogs.com/personnel/p/4584820.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!