admin管理员组文章数量:1625848
一、CPU重启问题
1.关于硬件重启有如下三种方式:KBC reset、PORT 92h(端口值控制SUS#)、Ware reset
# include <stdio.h>
#include <dos.h>
void main()
{
outportb(0x92,0x01);
outportb(0x64,0xFE);
outportb(0xcf9,0x04);
outportb(0xcf9,0x06);
}
实现循环重启并记录重启次数
**在dos中,重启之后各个寄存器的值会被clear,因此采用的思路是:创建一个文件,在文件中记录重启的次数,当重启后就读取该文件的值+1,就会避免记不到数的问题,详细如下:
#include <stdio.h>
#include <dos.h>
void main()
{
// int date=0xFE;
//int IoPost=0x64;
int num=0;
FILE *fp=fopen("ACCOUNT.TXT","r");//创建一个ACCOUNT.TXT文件,r表示已经有创建的文件,没有已创建的文件可使用“w”
fscanf(fp,"%d",&num);//读文件
fclose(fp);
num+=1;
printf("now reboot account is: %d\n",num);//打印重启次数
// sleep(3);
fopen("account.txt","w");//打开文件
// fputc(num,fp);//写文件
fprintf(fp,"%d",num);
fclose(fp);
// printf("now is :%d",num);
sleep(5);
outport(0x64,0xFE);//使用端口port64写入0xfe实现重启
// outportb(0x92,0x01);//同上方式,实现不同端口的重启
//outportb(0xcf9,0x04);
// outportb(0xcf9,0x06);
}
补充:0xcf9
补充:jmp ffff:0000
cpu寻址位在第一位开始ffff:0000,当寻址位在第一位的时候及0,会检测到当前地址0040:0072位是否为1234h,如果是1234h时,就不需要检测内存,如果不是1234h,就需要检测内存,就会重启
在dos中实现该方法:进入debug command -a 进入汇编
debug:
-a
-jmp ffff:0000
-
-g
二、CPU关机问题
cpu关机机制:
如上图:I/O Port Address:800h
offset Address:3-2h 是电源管理使能位
offset address:5-4h 是电源管理控制位
12:10位中001:是STR模式的关机
010:是STD模式的关机,从BCD码转位10进制
10010000:24
10100000:28
由此可以看出,关机位为0x805:0x28/0x24
debug实现关机只需要给端口输入值即可:o 805 28
在borland C++实现程序关机只用到了outportb()
#include <stdio.h>
#include <dos.h>
void main()
{
outportb(0x805,0x28);
}
三、CPU开机
如图,同关机原理,可得到开机位在0x803:0x05(00000101:05)
如同关机一样的方法实现开机,还需要使用到RTC定时寄存器,如下表
I/OPORT Address:70h&71h是实现RTC位的
70h:设置CMOS数据地址
71h:读写70hCMOS数据
可参考74h与75h,类似于70h,71h
table 9中解读信息如下
实例一:使用borland C++实现5S倒计时关机,计时时间显示在debug card 及打印现在的时间日期
# include <stdio.h>
# include <stdlib.h>
# include <dos.h>
# include <time.h>
int Bcd_int(int bcd);
int int_bcd(int in);
int main(void)
{
int y,m,d,h,mi,s;
outportb(0x70,0x09);
y=inportb(0x71);
outportb(0x70,0x08);
m=inportb(0x71);
outportb(0x70,0x07);
d=inportb(0x71);
outportb(0x70,0x04);
h=inportb(0x71);
outportb(0x70,0x02);
mi=inportb(0x71);
outportb(0x70,0x00);
s=inportb(0x71);
printf("now the time is:20%x.%x.%x %x:%x:%x\n",y,m,d,h,mi,s);
int s1,s2,s3,s4;
s1=Bcd_int(s);
s2=s1+5;
s3=int_bcd(s2);
s4=s2%10;
int i;
if(s1<55)
{
for(i=0;;i++)
{
system("cls");
printf("%d\n",s1+i);
outportb(0x80,s1+i);
outportb(0x70,0x00);
sleep(1);
if(inportb(0x71)==s3)
{
outportb(0x805,0x28);
}
}
}
else
{ for(i=0;;i++)
{
system("cls");
int s5=s1+i;
if(s5>59){
printf("%d\n",s5%10);
outportb(0x80,s5%10);
}
else
{
printf("%d\n",s1+i);
outportb(0x80,s1+i);
}
outportb(0x70,0x00);
sleep(1);
if(inportb(0x71)==s4)
{
outportb(0x805,0x28);
}
}
}
}
//bcd->10
int Bcd_int(int bcd)
{
return (0xff&(bcd>>4)*10+(0x0f&bcd));
}
//10->bcd
int int_bcd(int in)
{
return (((in/10)<<4)+(in%10));
}
实例二:实现系统关机后30S自动开机唤醒的循环测试
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
int Bcd_int(int bcd);
int Int_bcd(int in);
//bcd->10
int Bcd_int(int bcd)
{
return ((bcd>>4)*10+(0x0f&bcd));
}
//10->bcd
int Int_bcd(int in)
{
return (((in/10)<<4)+(in%10));
}
void main()
{
int num=0;
FILE *fp=fopen("SHUTDOWN.TXT","r");
fscanf(fp,"%d",&num);
fclose(fp);
num+=1;
printf("now the number is: %5d\n",num);
fopen("SHUTDOWN.TXT","w");
fprintf(fp,"%d",num);
fclose(fp);
//获取系统时间
int year,month,day,hour,minus,second;
outportb(0x70,0x09);
year=inportb(0x71);
outportb(0x70,0x08);
month=inportb(0x71);
outportb(0x70,0x07);
day=inportb(0x71);
outportb(0x70,0x04);
hour=inportb(0x71);
outportb(0x70,0x02);
minus=inportb(0x71);
outportb(0x70,0x00);
second=inportb(0x71);
printf("the time is :%x.%x.%x %x:%x:%x",year,month,day,hour,minus,second);
//系统时间转化为10进制
// int year_10=Bcd_int(year);
// int month_10=Bcd_int(month);
int day_10=Bcd_int(day);
int hour_10=Bcd_int(hour);
int minus_10=Bcd_int(minus);
int second_10=Bcd_int(second);
//当前10进制时间重新赋值
int second_30=second_10+15;//70
//int second_bcd=Int_bcd(second_30);
//将新的时间写入Alarm
outportb(0x70,0x0B);
outportb(0x71,0x22);
outportb(0x803,0x05);
int second_bcd_new;
int minus_bcd_new=minus;
int day_bcd_new=day;
int hour_bcd_new=hour;
int month_bcd_new=month;
if(second_30>59)
{
second_30=second_30-60;
second_bcd_new=Int_bcd(second_30);
minus_10=minus_10+1;
if(minus_10>59)
{
minus_10=minus_10-60;
minus_bcd_new=Int_bcd(minus_10);
hour_10=hour_10+1;
if(hour_10>23)
{
hour_10=hour_10-24;
hour_bcd_new=Int_bcd(hour_10);
day_10=day_10+1;
day_bcd_new=Int_bcd(day_10);
}
hour_bcd_new=Int_bcd(hour_10);
}
minus_bcd_new=Int_bcd(minus_10);
}
second_bcd_new=Int_bcd(second_30);
outportb(0x70,0x01);
outportb(0x71,second_bcd_new);
outportb(0x70,0x03);
outportb(0x71,minus_bcd_new);
outportb(0x70,0x05);
outportb(0x71,hour_bcd_new);
outportb(0x70,0x7D);
outportb(0x71,day_bcd_new);
outportb(0x70,0x7E);
outportb(0x71,month_bcd_new);
outportb(0x70,0x09);
outportb(0x71,year);
printf("the time is :%x.%x.%x %x:%x:%x",year,month_bcd_new,day_bcd_new,hour_bcd_new,minus_bcd_new,second_bcd_new);
sleep(3);
//outportb(0x803,0x05);
outportb(0x805,0x28);
}
本人水平有限,有不当或有错误的地方欢迎各位留言谈论,谢谢
版权声明:本文标题:X86硬件底层之硬件cpu 重启&关机&开机 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dongtai/1728932084a1180422.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论