梳理linux0.12知识点系列 之 A20地址线的打开

梳理linux0.12知识点系列

A20地址线的打开

背景

关于A20地址线的历史问题维基百科上有详细的描述
总体来说就是如果不开启A20地址线我们只能访问1M内存

也就是说这时能访问的最大内存地址是0xfffff

当我们想要访问0x100000的时候,cpu帮我们环绕到0x0处

linux 0.12的打开和检查方案

  1. linux 0.12在setup.S中进行了打开A20地址线的操作

     ...
     !144行开始
     call	empty_8042
     mov	al,#0xD1		! command write
     out	#0x64,al
     call	empty_8042
     mov	al,#0xDF		! A20 on
     out	#0x60,al
     call	empty_8042
     ...
     !204行开始
     empty_8042:
     	.word	0x00eb,0x00eb
     	in	al,#0x64	! 8042 status port
     	test	al,#2		! is input buffer full?
     	jnz	empty_8042	! yes - loop
     	ret
    
  2. 在head.s中进行了检查操作,如果不能通过检查,则进入死循环

     ...
     !33行开始
     1:	incl %eax		# check that A20 really IS enabled
     	movl %eax,0x000000	# loop forever if it isn't
     	cmpl %eax,0x100000
     	je 1b
    

思路很清晰

  • 首先使用8042键盘控制器的功能打开A20地址线

  • 然后不断的累加eax,放到0x0地址处,更0x100000地址处的值比较,如果相同就一致循环下去,如果不同说明不是环绕的地址,也就是可以访问1M以上的内存了,则退出循环

  • 所以上面的这个检查的逻辑可以很好的用c语言来表示

      void check_a20_valid()
      {
          unsigned char *p0 = 0x0;
          unsigned char *p1 = 0x100000;
          //这里指循环了10次
      	for (unsigned char i = 0; i < 10; ++ i) {
      		*p0 = i;   
      		if (*p0 != *p1) {
      			write_char('b');
      			break;
      		} else {
      			write_char('e');
      		}
      	}
      }
    

    具体代码见这里

  • 而在我们的head.s中,实现一个open_a20的函数,将书中的代码抄过来

      open_a20:
          call empty_8042
          mov al, 0xd1
          out 0x64, al
          call empty_8042
          mov al, 0xdf
          out 0x60, al
          call empty_8042
          ret
      
      empty_8042:
          dw 0x00eb
          dw 0x00eb
          in al, 0x64
          test al, 0x2
          jnz empty_8042
          ret
    
  • 在lan_main.c中调用open_a20

      extern void write_char(char ch);
      extern void open_a20();
      
      void check_a20_valid()
      {
          unsigned char *p0 = 0x0;
          unsigned char *p1 = 0x100000;
      	for (unsigned char i = 0; i < 10; ++ i) {
      		*p0 = i;   
      		if (*p0 != *p1) {
      			write_char('b');
      			break;
      		} else {
      			write_char('e');
      		}
      	}
      }
      
      void lan_main()
      {
      	write_char('L');
      	write_char('O');
      	write_char('V');
      	write_char('E');
      	open_a20();
      	check_a20_valid();
      	while(1);
      }
    

效果

  • 在A20被打开时
  • 如果我们注视掉open_a20();这句话
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值