超高难度问题,如何在WINDOWS里使用RDMSR指令(特邀wr960204参加讨论)(200分)

  • 主题发起人 主题发起人 weiliu
  • 开始时间 开始时间
W

weiliu

Unregistered / Unconfirmed
GUEST, unregistred user!
下面这个程序是我写的通过CPUID取得CPU的FAMILY,已经运行通过,在P4-2.0G的CPU上已经得到值为15,同CPU-Z是一样的:
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
TCPUIDResult = packed record
EAX: DWord;
EBX: DWord;
ECX: DWord;
EDX: DWord;
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

function CPUID(EAX: DWord): TCPUIDResult;
var
rEAX, rEBX, rECX, rEDX: DWord;
begin
asm
push EAX
push EBX
push ECX
push EDX
mov EAX,EAX
//******************************************************
//cpuid指令,因为Delphi的汇编编译器没有内置该指令,
//所以用该指令的机器语言代码$0F,$A2来实现
//******************************************************
db $0F,$A2
mov rEAX,EAX
mov rEBX,EBX
mov rECX,ECX
mov rEDX,EDX
pop EDX
pop ECX
pop EBX
pop EAX
end;
Result.EAX := rEAX;
Result.EBX := rEBX;
Result.ECX := rECX;
Result.EDX := rEDX;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
lvCPUID : TCPUIDResult;
begin
lvCPUID := cpuid(1);
showmessage(inttostr((lvCPUID.EAX and $F00) shr 8));
end;

end.

同样的代码,稍加修改,准备取得CPU其它的一些参数,想利用MSR,程序修改为如下:
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
TCPUIDResult = packed record
EAX: DWord;
EBX: DWord;
ECX: DWord;
EDX: DWord;
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

function RDMSR(ECX: DWord): TCPUIDResult;
var
rEAX, rEBX, rECX, rEDX: DWord;
begin
asm
push EAX
push EBX
push ECX
push EDX
mov EAX,EAX
//******************************************************
//rdmsr指令,因为Delphi的汇编编译器没有内置该指令,
//所以用该指令的机器语言代码$0F,$32来实现
//******************************************************
db $0F,$32
mov rEAX,EAX
mov rEBX,EBX
mov rECX,ECX
mov rEDX,EDX
pop EDX
pop ECX
pop EBX
pop EAX
end;
Result.EAX := rEAX;
Result.EBX := rEBX;
Result.ECX := rECX;
Result.EDX := rEDX;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
lvCPUID : TCPUIDResult;
begin
lvCPUID := RDMSR($198);
showmessage(inttostr((lvCPUID.EAX shr 8) and $FF));
end;

end.

运行后提示Privileged instruction(特权指令),失败。
查阅一些资料,看到RDMSR只能在实模式下运行,如果一定要在WINDOWS下运行,需要特别制做驱动,还有的资料说要提升权限CPL0,有谁知道具体的方法。
因为CPU-Z等一些软件,肯定是通过RDMSR来得到CPU的很多信息,比如倍频的,它们都可以在WINDOWS下运行。值得注意的是,早期版本的CPUZ,在执行的时候会自动产生一个CPUZ.VXD在程序所在的文件夹中,程序退出后就跟着被删除,这个VXD估计就是这驱动。
 
你反汇编一下CPU-z看有没有RDMSR
我估计是没有的,CPU-Z极有可能是通过API代理获取的,或者直接操作内核对象。
 
楼上的,WINDOWS的API能力太有限了,问题可以简化点,我就是想得到CPU的倍频信息,目前从SMBIOS我可以得到CPU的FSB,从RDTSC指令可以计算出CPU的主频,但是由于INTEL的CPU外频与FSB并不是简单的4倍关系,而且,从SMBIOS得到的FSB并不完全准确,特别是对于AMD的CPU,有时准有时不准,因此,想得到CPU的外倍,不能直接简单地用主频与外频来计算。
RDMSR指令可以得到CPU的倍频,但是由于它是特权指令,不能直接在WINDOWS下运行(在纯DOS的实模式下可以运行),需要自己制作驱动,提升CPL0才行。不知哪位大虾有这方面的资料,请赐教。
 
CPU-Z不是通过MSR寄存器读取的CPU信息,也无此必要。
另外,你写的代码有误,MSR寄存器读取操作时只能对EDX和ECX寄存器操作,还有,对Intel CPU来说所有大于13H的MSR都是非法......
 
weiliu
你好!
还记得吗?你给我一个配置电脑的方案。我最近出差北京配置一台电脑。
有一个问题,还得请你看看。
http://delphibbs.com/delphibbs/listq.asp?room=1&type=1&userfrom=listhano
 
to Lamb,
谢谢,那么请问CPU的倍频如果不通过RDMSR可以读出,还可以通过什么来得到呢?
我在看早期CPU-Z的版本的时候,发现它一运行就会产生一个VXD文件,运行完毕后就删除那个VXD,由此可见,早期版本的CPU-Z是通过了VXD方式来实现对硬件的信息的读取。
现在新版本的CPU-Z好像看不到VXD的出现了,是否用了WDM技术就很难说。
 
不出VXD就是出 Sys,打开CPU-Z的时候hook一下createfilea就知道了
 
参考
http://www.nsfocus.net/index.php?act=magazine&do=view&mid=2107
 
后退
顶部