在c语言中嵌入汇编语句,对于我来说相当难。
今天早上在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语言中嵌入汇编语句,对于我来说相当难。的更多相关文章
- [汇编] C语言中嵌入汇编
>_<" 下面是在C语言中嵌入汇编的例子,下面是三点要注意的~ 1.内联式汇编 2._asm关键字 3.并不是所有中断都能被支持 #include<iostream> ...
- 实验--使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用(杨光)
使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用 攥写人:杨光 学号:20135233 ( *原创作品转载请注明出处*) ( 学习课程:<Linux内核分析>MOOC课程 ...
- 在C语言中嵌入汇编语言
TMS320C28x编译器允许在C程序中嵌入汇编指令,通过下面声明实现: asm(“assembler text”); 其中assembler text指汇编代码.asm指令一般用来处理C/C++语句 ...
- 在C中嵌入汇编
早前公布了C和汇编混编的温度控制器程序,收到一些朋友的询问,他们无法在自己程序中使用我的18B20的汇编子程序或无法正常通过混编后的程序编译. 其实在KEIL中嵌入汇编的方法很简单.如图一,在C文件中 ...
- linux内核分析作业4:使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用
系统调用:库函数封装了系统调用,通过库函数和系统调用打交道 用户态:低级别执行状态,代码的掌控范围会受到限制. 内核态:高执行级别,代码可移植性特权指令,访问任意物理地址 为什么划分级别:如果全部特权 ...
- C语言中嵌入式SQL语句
原文:[转载]C语言中嵌入式SQL语句 http://blog.csdn.net/cnlht/archive/2007/12/12/1930960.aspx原文地址 实验内容: 掌握SQL Serve ...
- LInux内核分析--使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用
实验者:江军 ID:fuchen1994 实验描述: 选择一个系统调用(13号系统调用time除外),系统调用列表参见http://codelab.shiyanlou.com/xref/linux-3 ...
- 实验四——使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用
实验目的: 使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用 实验过程: 查看系统调用列表 get pid 函数 #include <stdio.h> #include & ...
- Linux内核设计第四周学习总结 使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用
陈巧然原创作品 转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 实验目的: 使用库函数A ...
随机推荐
- tkinter 对键盘和鼠标事件的处理
鼠标事件 <ButtonPress-n> <Button-n> <n> 鼠标按钮n被按下,n为1左键,2中键,3右键 <ButtonRelease-n> ...
- oracle移动数据/修改数据文件路径
参考:http://wwyz998.blog.163.com/blog/static/321867852011117111832334/ oracle移动数据文件 1.连接到数据库 [oracle@l ...
- STM32之HAL库、标准外设库、LL库
标准外设库(Standard Peripherals Library),应该是最早推出的版本,以前用STM32F103的时候,用的多 HAL(Hardware Abstraction Layer),硬 ...
- python3获取主机名、主机IP
python3可以通过socket模块获取主机名及主机IP 代码如下: *********************************************************** 学习永远 ...
- LOJ#6354. 「CodePlus 2018 4 月赛」最短路[最短路优化建图]
题意 一个 \(n\) 个点的完全图,两点之间的边权为 \((i\ xor\ j)*C\) ,同时有 \(m\) 条额外单向路径,问从 \(S\) 到 \(T\) 的最短路. \(n\leq 10^5 ...
- pycharm如何在虚拟环境中引入别人的项目
如果你想引入别人的项目,但是呢引入的项目可能与自己原先装的模块的版本产生冲突,而且如果引入一个项目就在本地进行运行使用,每个项目用的依赖包都不大相同,就会导致解释器安装包过多,就会导致加载过慢,甚至会 ...
- FFMPEG的基础使用
由于最近要将yuv视频下采样,于是使用ffmpeg快速将yuv视频下降分辨率.在此记录ffmpeg的基础使用方法和所遇到的问题: 下载,可到官网下载:https://www.ffmpeg.org/ . ...
- Inno Setup脚本
某天夜晚一场狂风暴雨,由于办公室座位旁的窗户没关,笔记本电脑泡了一夜水,无法开机,无奈送修,里面的大量资料也不知道会不会丢失. is的脚本只有重新写了,重新研究了一下检测程序是否正在运行的判断方法,另 ...
- GPT & UEFI Install Windows7
安装介质以FAT或者FAT32分区安装介质添加UEFI支持文件(Windows7及其以前的系统,不支持UEFI启动) 从Windows8的安装文件中提取Bootmgfw.efi文件,重命名为BOOTX ...
- 贪心算法HURUST题目
题目描述: Yogurt factory The cows have purchased a yogurt factory that makes world-famous Yucky Yogurt. ...