打印

X86底层软件の彻底裸奔

[复制链接]
4523|24
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
-兔子-|  楼主 | 2012-12-20 12:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
这个论坛有点冷,准备花点时间, 整理点东西,支持下版主,同时 供对X86有兴趣的同学参考, 不定时更新内容。
       为什么要裸奔,刺激啊, 就是要在同样的硬件环境下,实现软件的超频, 做到对硬件的完全掌控, 资源控制权独享, 构建自己的高效底层驱动, 踢掉所有操作系统提供的龟速级INT调用函数, 让自己的程序飞起来运行。实现:骑三轮超宝马,矮穷挫狂甩高富帅。
先构思一下大概可能涉猎的内容:
      
(1)      键盘接口(针对PS2接口)。
(2)      显示界面(针对VGASVGA标准协议)。
(3)      用足内存(针对扩展内存)。
(4)      其它杂项,如中断机制,获取时钟,RS232,自制键盘,外接触摸屏控制等。
(5)      文件系统? 费力不讨好,操不动了, 建议用现成的吧。
都是原创,感兴趣的同学请给点掌声。。。。
评分
参与人数 1威望 +5 收起 理由
dong_abc + 5 赞一个!

相关帖子

沙发
ymind| | 2012-12-20 14:05 | 只看该作者
有点吃力不讨好。先看看OpenBIOS等再说吧。
不过锻炼技术能力也是一条方法,我记得联想出过 不进操作系统也能看视频的PC的。

使用特权

评论回复
板凳
aozima| | 2012-12-20 14:36 | 只看该作者
帮顶

使用特权

评论回复
地板
-兔子-|  楼主 | 2012-12-20 18:51 | 只看该作者
本帖最后由 -兔子- 于 2012-12-20 20:11 编辑

先说一下标准PS键盘接口的读取程序, 本程序短小精悍, 新手可以学学真正的工程软件的设计思路和考虑问题的方式。

首先说明一下为什么要这样读取按键内容, 因为好处大大滴。
首先响应快, 其次去掉了按键中断对主程序的打扰, 你就是一屁股坐键盘上也不会发出一连串讨厌的嘟嘟声:D,
同时可以将这个小程序放到其它公共调用例程或将其它公共调用例程嵌入到这个小程序中。

本例程工作的前提是在程序前先关闭系统的键盘中断。
        Outp( 0x21,        inp(0x21) | 0x02 );
有了这条语句, 键盘的控制权就完全拿到手了,除了你定义的按键操作, 其它的如:Ctrl+break, Ctrl+Alt+Del大 法统统失效。
也切断了通过按键中断进行程序破译和追踪的可能性。

另外, 直接可在表格中很方便的换码。


// ==============  键盘扫描码表==>键值码表转换 ======================
const uint near keyLL[ 96 ] =
{
//                         ESC                1                2                3                4                5                6
//        [00]                [01]                [02]                [03]                [04]                [05]                [06]                [07]
        0x0000, 0x1B00,        0x0031,        0x0032,        0x0033,        0x0034,        0x0035,        0x0036,

//         7                8                9                0                -                =     BackSpace Tab
//        [08]                [09]                [0A]                [0B]                [0C]                [0D]                [0E]                [0F]
        0x0037, 0x0038,        0x0039,        0x0030,        0x002D,        0x003D,        0x003B,        0x0F00,

//         Q                W                E                R                T                Y                U                I
//        [10]                [11]                [12]                [13]                [14]                [15]                [16]                [17]
        0x0051, 0x0057,        0x0045,        0x0052,        0x0054,        0x0059,        0x0055,        0x0049,

//         O                P                [                ]                Enter        Ctrl    A                S
//        [18]                [19]                [1A]                [1B]                [1C]                [1D]                [1E]                [1F]
        0x004F, 0x0050,        0x2300,        0x2500,        0x0D00,        0x1D00,        0x0041,        0x0053,

//         D                F                G                H                J                K                L                ;
//        [20]                [21]                [22]                [23]                [24]                [25]                [26]                [27]
        0x0044, 0x0046,        0x0047,        0x0048,        0x004A,        0x004B,        0x004C,        0x2800,

//         '                `                   L_Shift        \                Z                X                C                V
//        [28]                [29]                [2A]                [2B]                [2C]                [2D]                [2E]                [2F]
        0x2900, 0x0025,        0x2A00,        0x003A,        0x005A,        0x0058,        0x0043,        0x0056,

//         B                N                M                ,                .                /                R_Shift        *
//        [30]                [31]                [32]                [33]                [34]                [35]                [36]                [37]
        0x0042, 0x004E,        0x004D,        0x002C,        0x002E,        0x002F,        0x3600,        0x002A,

//         Alt                Sp                                F1                F2                F3                F4                F5
//        [38]                [39]                [3A]                [3B]                [3C]                [3D]                [3E]                [3F]
        0x3800, 0x0020,        0x0000,        0x3B00,        0x3C00,        0x3D00,        0x3E00,        0x3F00,

//         F6                F7                F8                F9                F10                NumLock                Home
//        [40]                [41]                [42]                [43]                [44]                [45]                [46]                [47]
        0x4000, 0x4100,        0x4200,        0x4300,        0x4400,        0x002B,        0x0000,        0x4700,

//         ↑           PgUp        -                ←                 5_                 →                +                End
//        [48]                [49]                [4A]                [4B]                [4C]                [4D]                [4E]                [4F]
        0x4800, 0x4900,        0x4A00,        0x4B00,        0x003C,        0x4D00,        0x4E00,        0x4F00,

//         ↓                PgDn        Ins                Del                                                                F11
//        [50]                [51]                [52]                [53]                [54]                [55]                [56]                [57]
        0x5000, 0x5100,        0x5200,        0x5300,        0x0000,        0x0000,        0x0000,        0x5700,

//         F12                     L_Win   R_Win
//        [58]                [59]                [5A]                [5B]                [5C]                [5D]                [5E]                [5F]
        0x5800, 0x0000,        0x0000,        0x0028,        0x0029,        0x0000,        0x0000,        0x0000
};


/**************************************************************************
键盘扫描程序:
uint        KEY_search( )
代入变量: 无
返回变量: 无
程序返回值: =0:无按键, =xxxx:按键值.
**************************************************************************/
uint        KEY_search( )
{
static uint near keyn;                // 保存上次调用返回键码值!
uchar        keyc;
uint        k;

        keyc=inp(0x60);        // 扫描键盘端口.
        if ( keyc == 0xE0 ) return( keyn );
        k = keyLL[ keyc ]; // 键码转换
        if ( keyc <= 0x5F && k != 0 ) keyn = k; else keyn = 0;
        return( keyn );
}

/**************************************************************************
键盘等待程序(判按键抬起有效)
uint        KEY_wait( )
代入变量: 无
返回变量: 无
程序返回值: xxxx:按键值(非零值).
**************************************************************************/
uint        KEY_wait( )
{
uint        keyc;

        while( TRUE )
        {
        keyc = KEY_search( );

                if ( keyc != 0 )
                {
                        do{ } while( KEY_search( ) == keyc );
                break;
                }
        }
        return( keyc );
}

声明下, 主程序退出时别忘了恢复中断, 否则就只好关机了。

使用特权

评论回复
5
-兔子-|  楼主 | 2012-12-20 19:49 | 只看该作者
ymind 发表于 2012-12-20 14:05
有点吃力不讨好。先看看OpenBIOS等再说吧。
不过锻炼技术能力也是一条方法,我记得联想出过 不进操作系统也 ...

木事,就图个乐呵, 主要针对搞工控的朋友交流下。。。:D

使用特权

评论回复
6
-兔子-|  楼主 | 2012-12-20 19:50 | 只看该作者
aozima 发表于 2012-12-20 14:36
帮顶

多谢, 你的鼓励就是俺的动力。

使用特权

评论回复
7
yapcc| | 2012-12-26 13:32 | 只看该作者
支持, 言之有物!

使用特权

评论回复
8
mcu818| | 2013-1-7 20:59 | 只看该作者
兔子大哥,11年10月在北京和你见过一面,已经过了一年多了,现在一统江湖了没?

对了,你说过你现在开发都是用TC++3.0还是BORLAND C的? 那一个比较好用?

使用特权

评论回复
9
f8-0| | 2013-1-11 09:36 | 只看该作者
看看CoreBoot或许有用

使用特权

评论回复
10
dong_abc| | 2013-1-13 23:24 | 只看该作者
支持原创~

使用特权

评论回复
11
dong_abc| | 2013-1-13 23:28 | 只看该作者
这个版块都荒了,就看楼主了。

使用特权

评论回复
12
-兔子-|  楼主 | 2013-1-19 10:39 | 只看该作者
再整理点东西, 本来按原列表(2)应该先写有关显示部分的,现在先整理(3), 因为显示部分也用到了这部分内容。

使用特权

评论回复
13
-兔子-|  楼主 | 2013-1-19 10:40 | 只看该作者
yapcc 发表于 2012-12-26 13:32
支持, 言之有物!

多谢支持。

使用特权

评论回复
14
-兔子-|  楼主 | 2013-1-19 10:42 | 只看该作者
mcu818 发表于 2013-1-7 20:59
兔子大哥,11年10月在北京和你见过一面,已经过了一年多了,现在一统江湖了没?

对了,你说过你现在开发都是用T ...

革命尚未成功, 继续努力中。。。:D

实模式下终极版本, 不烂的C好些。

使用特权

评论回复
15
-兔子-|  楼主 | 2013-1-19 10:43 | 只看该作者
dong_abc 发表于 2013-1-13 23:24
支持原创~

多谢鼓励。

使用特权

评论回复
16
-兔子-|  楼主 | 2013-1-19 10:57 | 只看该作者
(3)      用足内存(针对扩展内存)。
为什麽说要用足内存, 这还是问题吗? 别说, 对早期的x86体系, 这还真是一个坎。
由于历史原因, x86的发展从早期的只有可怜的几MB字节内存发展到现在的动不动就几GB内存, 经历了相当长的时间, 为了保证向下兼容, INTEL 基本就是在原8086体系基础上打各种补丁,
结果搞得x86体系从硬件上和软件上都比较复杂和低效。

当然, 现在的应用基本上都不用太考虑硬件资源的限制, 在window等系统的支持下也不用自己来设计多任务多进程等软件设计。
但这种榨干资源的用法对现在还有意义吗? 当然有。
对于一些特殊行业, 比如军工,工控等, 要求苛刻的场合。

使用特权

评论回复
17
-兔子-|  楼主 | 2013-1-19 11:05 | 只看该作者
用x86搞过设计的都知道, 一般情况下, 实模式下系统程序都在基本的1M内存中运行, 数据量小的话也放在这可怜的1M内存中, 如果数据量大, 则要考虑在系统安装的扩展内存中使用。
但这是相当麻烦的事情, 就是实模式和保护模式的动态切换,且不能对主程序的运行产生打扰等不良影响, 就已经使很多人头痛了。
但在实模式下, 那么多的扩展内存就不用了吗? 当然要用, 而且要很简单的用, 很高效的用。 这就是要达到的目的。

复杂吗,太Easy了, 就像从左兜掏东西放右兜。。。。:lol

使用特权

评论回复
18
-兔子-|  楼主 | 2013-1-19 11:08 | 只看该作者
本帖最后由 -兔子- 于 2013-1-19 11:20 编辑

闲话少说。

在程序全面先放上这段启动代码:

// -------- x86使用扩展内存变量区: ----------
const ulong near GDT_Table[]=
{
0,0,    //NULL   - 00H
0x0000FFFF,0x00CF9A00,  //Code32 - 08H Base=0 Limit=4G-1 Size=4G
0x0000FFFF,0x00CF9200  //Data32 - 10H Base=0 Limit=4G-1 Size=4G
};
uchar near OldIDT[6]={0};  //Save The IDTR before Enter Protect Mode.
uchar near pdescr_tmp[6]={0}; //NULL The IDTR,IDTR's Limit=0 will

/**************************************************************************
将 x86 CPU的FS段寻址寄存器设置为可寻址4GB.
**************************************************************************/
void LoadFSLimit4G(void)
{
// 开放CPU A20 地址线.
{
{while(inportb(0x64)&2);}
outportb(0x64,0xD1);
{while(inportb(0x64)&2);}
outportb(0x60,0xDF); //Enable A20 with 8042.
{while(inportb(0x64)&2);}
outportb(0x64,0xFF);
{while(inportb(0x64)&2);}
}
//**************************************
//*       Disable ints & Null IDT      *
//**************************************
asm {
  CLI             //Disable inerrupts
  SIDT OldIDT  //Save OLD IDTR
  LIDT pdescr_tmp //Set up empty IDT.Disable any interrupts,
  }   //Include NMI.
//***************************************
//*   Load GDTR  *
//***************************************
asm { //The right Code is Real,But BC++'s Linker NOT Work with 32-bits Code.
  db 0x66  //32 bit Operation Prefix in 16 Bit DOS.
  MOV CX,DS    //MOV ECX,DS
  db 0x66    //Get Data segment physical Address
  SHL CX,4    //SHL ECX,4
  MOV word ptr pdescr_tmp[0],(3*8-1) //MOV word ptr pdescr_tmp[0],(3*8-1)
  db 0x66
  XOR AX,AX    //XOR EAX,EAX
  MOV AX,offset GDT_Table  //MOV AX,offset GDT_Table
  db 0x66
  ADD AX,CX    //ADD EAX,ECX
  MOV word ptr pdescr_tmp[2],AX //GDTR Base high16 bits
  db 0x66
  SHR AX,16    //SHR EAX,16
  MOV word ptr pdescr_tmp[4],AX //GDTR Base high16 bits
  LGDT pdescr_tmp   //Load GDTR
  }
//**************************************
//*  Enter 32 bit Flat Protected Mode  *
//**************************************
// Set CR0 Bit-0 to 1 Enter 32 Bit Protection
//Mode,And NOT Clear machine perform cache,It Meaning
//the after Code HAD Ready To RUN in 32 Bit Flat Mode,
//Then Load Flat Selector to FS and Description into it's
//Shadow register,After that,ShutDown Protection Mode
//And ReEnter Real Mode immediately.
// The FS holds Base=0 Size=4G Description and
//it can Work in Real Mode as same as Pretect Mode,
//untill FS be reloaded.
// In that time All the other Segment Registers are
//Not Changed,except FS.(They are ERROR Value holded in CPU).
asm {
  MOV DX,0x10   //The Data32 Selector
  db 0x66,0x0F,0x20,0xC0 //MOV EAX,CR0
  db 0x66
  MOV BX,AX   //MOV EBX,EAX
  OR AX,1
  db 0x66,0x0F,0x22,0xC0 //MOV CR0,EAX //Set Protection enable bit
  JMP Flush
  }    //Clear machine perform cache.
Flush: //Now In Flat Mode,But The CS is Real Mode Value.
asm { //And it's attrib is 16-Bit Code Segment.
  db 0x66
  MOV AX,BX   //MOV EAX,EBX
  db 0x8E,0xE2  //MOV FS,DX //Load FS now
  db 0x66,0x0F,0x22,0xC0 //MOV CR0,EAX //Return Real Mode.Now FS's Base=0 Size=4G
  LIDT OldIDT   //LIDT OldIDT  //Restore IDTR
  STI    //STI  //Enable INTR
  }
}

细节就不多解释了。。。

使用特权

评论回复
19
-兔子-|  楼主 | 2013-1-19 11:11 | 只看该作者
现在, 超过1M以上内存的应用就随便搞了。

以存取1个字节数据举例:

/**************************************************************************
从 x86 扩展内存[可寻址4GB]装入数值子程序(char/uchar)
char load_Emem_C( ulong Address )
代入变量:
  Address 内存地址: 0x00000000 - 0xFFFFFFFF
返回变量: 无.
程序返回值: 存储内容(由AL返回).
注: 使用FS.
**************************************************************************/
char load_Emem_C( ulong Address )
{
char n;
_asm{
MOV EBX,Address;
MOV AL,FS:BYTE PTR [EBX];
MOV n,AL;
}
return( n );
}
/**************************************************************************
向x86扩展内存[可寻址4GB]写入数值子程序(char/uchar)
void save_Emem_C( ulong Address, char n )
代入变量:
  Address 内存地址: 0x00000000 - 0xFFFFFFFF
n 数值
返回变量: 无.
程序返回值: 无.
注: 使用FS.
**************************************************************************/
void save_Emem_C( ulong Address, char n )
{
_asm{
  MOV EBX,Address;
  MOV AL,n;
  MOV FS:BYTE PTR [EBX],AL;
     }
}

简单吧, 在此基础上, 存取一串数据不就跟玩似得。。。:D

使用特权

评论回复
20
-兔子-|  楼主 | 2013-1-19 11:14 | 只看该作者
本帖最后由 -兔子- 于 2013-1-19 11:16 编辑

举几个应用小例子:

// ------ 测试系统安装的扩展内存容量大小(单位MB) ------
uint get_Emem_size( )
{
uint i,j;
i = 1;
addr = 0x001FFFFF; // 1M 最末单元
while( TRUE )
{
  j = load_Emem_I( addr );
  save_Emem_I( addr, 0x55AA );
  if ( load_Emem_I( addr ) == 0x55AA )
  {
  i++;
  save_Emem_I( addr, j );
  addr += 0x00100000; // 1M 间隔
  }
  else
  break;
}
return( i );
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:good good study, day day up!

16

主题

320

帖子

2

粉丝