我找到的源程序是这样的:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TForm1 = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
type
TGate = record
Off2,op,seg,off1:WORD;
end;
const
_dsnlen=20; //硬盘序列号的位数,10个Word,必须是偶数
_dtplen=40; //硬盘生产厂家型号的位数,18个Word
_dcllen=8; //硬盘控制号的位数
var
IDTR : INT64;
SavedGate : TGate;
OurGate : TGate;
dd : array [0..256] of word;
dsn : array [0.._dsnlen-1] of char; //存放硬盘序列号
dtp : array [0.._dtplen-1] of char; //存放硬盘型号
dcl : array [0.._dcllen-1] of char;
// Ring0 中断服务例程 Ring0Proc ,通过端口读取硬盘参数
procedure Ring0Proc();
asm
// Wait for controller not busy
mov dx,01f7h
@1:in al,dx
cmp al,050h
jne @1
// Get first/second drive
dec dx //mov dx,01f6h
mov al,0a0h
out dx,al
// Get drive info data
inc dx //mov dx,01f7h
mov al,0ech
out dx,al
nop
nop
// Wait for data ready
@2:in al,dx
cmp al,058h
jne @2
nop
nop
// Read sector
xor ecx,ecx
mov dx,01f0h
@3:in ax,dx
mov word ptr dd[ecx*2],ax
inc ecx
cmp ecx,256
jne @3
iretd //中断返回
end;
//改变程序运行的特权级,以调用自定义中断程序 Ring0Proc
procedure Change2Ring0();
asm
mov eax, offset Ring0Proc
mov OurGate.off2, ax //将中断函数的地址填入新造的中断门描述符
shr eax, 16
mov OurGate.off1, ax
mov OurGate.op,0028h
mov OurGate.seg,0ee00h
mov ebx,offset IDTR
sidt [ebx]
//将中断描述符表寄存器(IDTR)的内容取出
mov ebx, dword ptr [IDTR+2]
//取出中断描述符表(IDT)基地址
add ebx, 8*3
//计算Int 3 的描述符应放置的地址选用
//Int3 是因为它在Win32 保护模式下未占用
mov edi, offset SavedGate
mov esi, ebx
movsd //保存原来的Int 9 描述符到SavedGate 以便恢复
movsd
mov edi, ebx
mov esi, offset OurGate
cli
movsd //替换原来的中断门描述符以安装中断服务例程
movsd
sti
mov eax,6200h
//用以测试放在EAX 中的数据能否正确传到 Ring0 中断
mov ecx,0
{用以测试放在 ECX 中的数据能否正确传到 Ring0 中断
因为很多VxD 服务都用此二寄存器传递参数}
int 3h
{人为触发中断, 平时会出现保护错误蓝屏或非法操作对话框,
现在安装了中断服务例程后,
就会通过 VMM 在Ring0 调用中断服务例程Ring0Proc}
mov edi, ebx
mov esi, offset SavedGate
cli
movsd //恢复原来的中断门描述符
movsd
sti
end;
//截取硬盘出厂参数:控制号,型号,序列号
procedure GetParameter;
begin
{硬盘的序列号存放于 dd[10] 开始的10个WORD中,使用时需要将每个WORD的
高低字节颠倒一下}
asm
xor ecx,ecx
mov ebx,offset dd[10*2]
@1:mov ax,[ebx]
cmp ah, 0 //
je @2 //
mov byte ptr dsn[ecx],ah
cmp al, 0 //
je @2 //
inc ecx
mov byte ptr dsn[ecx],al
inc ebx
inc ebx
inc ecx
cmp ecx, _dsnlen
jne @1
@2:
end;
{硬盘的型号存放于 dd[27] 开始的18个WORD中}
asm
xor ecx,ecx
mov ebx,offset dd[27*2]
@1:mov ax,[ebx]
cmp ah, 0 //
je @2 //
mov byte ptr dtp[ecx],ah
cmp al, 0 //
je @2 //
inc ecx
mov byte ptr dtp[ecx],al
inc ebx
inc ebx
inc ecx
cmp ecx, _dtplen
jne @1
@2:
end;
{硬盘的控制号存放于 dd[23] 开始的3个WORD中}
asm
xor ecx,ecx
mov ebx,offset dd[23*2]
@1:mov ax,[ebx]
cmp ah, 0 //
je @2 //
mov byte ptr dcl[ecx],ah
cmp al, 0 //
je @2 //
inc ecx
mov byte ptr dcl[ecx],al
inc ebx
inc ebx
inc ecx
cmp ecx, _dcllen
jne @1
@2:
end;
end;
end.