关于A20

A20是什么

1981年8月,IBM 公司最初推出的个人计算机所使用的 CPU 是 Intel 8088。在该微机中地址线只有 20 根(A0~A19)。当时,计算机的 RAM 只有几百 KB 或不到 1MB 时,20 根地址线已足够用来寻址。其所能寻址的最高地址是0xffff:0xffff,即0x10ffef。对于超出 0x100000(1MB)的寻址地址, 将默认回卷到0x0ffef

IBM 公司于 1985 年引入 AT 机时,使用的是 Intel 80286 CPU,具有 24 根地址线,最高可寻址 16MB,并且有一个与 8088 完全兼容的实模式运行方式。

然而,在寻址值超过 1MB 时它却不能象 8088 那样实现地址的回卷。但是当时已经有一些程序是利用这种地址环绕机制进行工作的。为了实现完全的兼容性,IBM 公司发明了一种方法——使用一个开关来开启或禁止地址线的比特位20到23。

由于当时的 8042 键盘控制器上恰好有空闲的端口引脚(输出端口P2,引脚名是 P21 ),于是便使用了该引脚来作为与门控制这个地址比特位。该信号被称为 A20。如果它为零,则比特 20 及以上地址都被清除。

在机器启动时,默认条件下,A20 地址线是禁止的,所以操作系统必须使用适当的方法来开启它。但是由于各种兼容机所使用的芯片集不同,要做到这一点是非常麻烦的,通常要在几种控制方案中选择。

怎样控制A20

方案一:键盘控制器

对 A20 信号线进行控制的常用方法是通过设置键盘控制器的端口值。
比如以下代码可以开启A20

    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

empty_8042:
    .word   0x00eb,0x00eb !机器码,跳转到下一句,为了延时
    in  al,#0x64          ! 8042 status port
    test al,#2            ! is input buffer full?
    jnz empty_8042        ! yes - loop
    ret

方案二:端口0x92

有些操作系统将 A20 的开启和禁止作为实模式与保护模式之间进行转换的标准过程的一部分。由于键盘控制器的速度很慢,因此就不能使用键盘控制器对 A20 线来进行操作。为此引进了一个 A20 快速门选项(Fast Gate A20),它使用 I/O 端口 0x92 来处理 A20 信号线。

比如

    in al,0x92                         ;南桥芯片内的端口 
    or al,0000_0010B
    out 0x92,al                        ;打开A20

方案三:INT 15 中断

/*
 * 打开A20
 * 返回结果:
 *    成功:CF=0,  AH=0
 *    失败:CF=1, AH=0x01   键盘控制器处于secur模式
 *               AH=0x86   功能不支持
 */
    mov ax, 0x2401
    int 0x15

方案四:0xee端口

还有一种方式是通过读 0xee 端口来开启 A20 信号线,写该端口则会禁止 A20 信号线。

    in al,0xee   ;开启A20
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
///////////////////////////////////////////////////////////////////// //功 能:寻卡 //参数说明: req_code[IN]:寻卡方式 // 0x52 = 寻感应区内所有符合14443A标准的卡 // 0x26 = 寻未进入休眠状态的卡 // pTagType[OUT]:卡片类型代码 // 0x4400 = Mifare_UltraLight // 0x0400 = Mifare_One(S50) // 0x0200 = Mifare_One(S70) // 0x0800 = Mifare_Pro(X) // 0x4403 = Mifare_DESFire //返 回: 成功返回MI_OK ///////////////////////////////////////////////////////////////////// signed char PcdRequest(unsigned char req_code,unsigned char *pTagType) { signed char status; unsigned int unLen; unsigned char ucComMF522Buf[MAXRLEN]; ClearBitMask(Status2Reg,0x08); WriteRawRC(BitFramingReg,0x07); SetBitMask(TxControlReg,0x03); ucComMF522Buf[0] = req_code; status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen;); if ((status == MI_OK) && (unLen == 0x10)) { *pTagType = ucComMF522Buf[0]; *(pTagType+1) = ucComMF522Buf[1]; } else { status = MI_ERR; } return status; } ///////////////////////////////////////////////////////////////////// //功 能:防冲撞 //参数说明: pSnr[OUT]:卡片序列号,4字节 //返 回: 成功返回MI_OK ///////////////////////////////////////////////////////////////////// signed char PcdAnticoll(unsigned char *pSnr) { signed char status; unsigned char i,snr_check=0; unsigned int unLen; unsigned char ucComMF522Buf[MAXRLEN]; ClearBitMask(Status2Reg,0x08); WriteRawRC(BitFramingReg,0x00); ClearBitMask(CollReg,0x80); ucComMF522Buf[0] = PICC_ANTICOLL1; ucComMF522Buf[1] = 0x20; status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen;); if (status == MI_OK) { for (i=0; i<4; i++) { *(pSnr+i) = ucComMF522Buf[i]; snr_check ^= ucComMF522Buf[i]; } if (snr_check != ucComMF522Buf[i]) { status = MI_ERR; } } SetBitMask(CollReg,0x80); return status; } ///////////////////////////////////////////////////////////////////// //功 能:选定卡片 //参数说明: pSnr[IN]:卡片序列号,4字节 //返 回: 成功返回MI_OK ///////////////////////////////////////////////////////////////////// signed char PcdSelect(unsigned char *pSnr) { signed char status; unsigned char i; unsigned int unLen; unsigned char ucComMF522Buf[MAXRLEN]; ucComMF522Buf[0] = PICC_ANTICOLL1; ucComMF522Buf[1] = 0x70; ucComMF522Buf[6] = 0; for (i=0; i<4; i++) { ucComMF522Buf[i+2] = *(pSnr+i); ucComMF522Buf[6] ^= *(pSnr+i); } CalulateCRC(ucComMF522Buf,7,&ucComMF522Buf;[7]); ClearBitMask(Status2Reg,0x08); status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&unLen;); if ((status == MI_OK) && (unLen == 0x18)) { status = MI_OK; } else { status = MI_ERR; } return status; } ///////////////////////////////////////////////////////////////////// //功 能:验证卡片密码 //参数说明: auth_mode[IN]: 密码验证模式 // 0x60 = 验证A密钥 // 0x61 = 验证B密钥 // addr[IN]:块地址 // pKey[IN]:密码 // pSnr[IN]:卡片序列号,4字节 //返 回: 成功返回MI_OK ///////////////////////////////////////////////////////////////////// signed char PcdAuthState(unsigned char auth_mode,unsigned char addr,unsigned char *pKey,unsigned char *pSnr) { signed char status; unsigned int unLen; unsigned char i,ucComMF522Buf[MAXRLEN]; ucComMF522Buf[0] = auth_mode; ucComMF522Buf[1] = addr; for (i=0; i<6; i++) { ucComMF522Buf[i+2] = *(pKey+i); } for (i=0; i<6; i++) { ucComMF522Buf[i+8] = *(pSnr+i); } // memcpy(&ucComMF522Buf;[2], pKey, 6); // memcpy(&ucComMF522Buf;[8], pSnr, 4); status = PcdComMF522(PCD_AUTHENT,ucComMF522Buf,12,ucComMF522Buf,&unLen;); if ((status != MI_OK) || (!(ReadRawRC(Status2Reg) & 0x08))) { status = MI_ERR; } return status; }

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值