介绍

CPU可以直接读写:

  1. CPU的寄存器
  2. 内存单元
  3. 端口

    端口

    各种接口卡(网卡``显卡)上的接口芯片,控制着接口卡的工作
    这些芯片中都具有能被CPU直接读写的寄存器,通过总线与CPU相连,因此被当作端口
    端口地址范围为64KB0~65535(0000H~FFFFH)

    写入

    8 位端口

    1. out 20h,al ; 20h 端口写入一个字节
    1. out 20h,ax ; 20h 端口写入两个字节

    16 位端口

    1. mov dx,3f8h
    2. out dx,al ; 3f8h 端口写入一个字节

    读取

    1. in al,20h
    1. out 20h,al

    写入和读取只能使用axal

COMS RAM

包含一个实时钟128存储单元的RAM
时间信息保存在0~d单元
存在两个端口70h71h,分别为地址端口和数据端口

读取 2 号单元数据

  1. 2送入70h
  2. 71h读出数据 ``` assume cs:code

code segment

start: mov al,2 out 70h,al ; 将 al 送入端口 70h in al,71h ; 从端口 71h 处读出单元内容 mov ax,4c00h int 21h

code ends

end start

  1. <a name="jbVQV"></a>
  2. ### 读取时间
  3. 时间信息为`秒``分``时``日``月``年`,每个占一个字节<br />使用`BCD`码保存,因此一个字节可以表示两位的十进制<br />`BCD`码 + `30h` = 十进制对应的`ASCII`

assume cs:code

code segment

start: mov al,8 ; CMOS RAM 的 8 号单元 out 70h,al in al,71h

  1. mov ah,al
  2. mov cl,4
  3. shr ah,cl ; 将两个BCD码右移 4 位得到十位数
  4. and al,00001111b ; 去掉十位数得到个位数
  5. add ah,30h ; 加上 30h 得到 ASCII
  6. add al,30h
  7. ; 写入显存中
  8. mov bx,0b800h
  9. mov es,bx
  10. mov byte ptr es:[160*12+40*2],ah
  11. mov byte ptr es:[160*2+40*2+2],al
  12. mov ax,4c00h
  13. int 21h

code ends

end start

  1. <a name="Mnq9p"></a>
  2. ## 逻辑左移 shl
  3. 内存单元的数据左移,最低位用`0`补齐,最后移出去的保存在`cf`中

assume cs:code

code segment start:mov al,11001000B shl al,1 ; 左移一位

  1. mov ax,4c00h
  2. int 21h

code ends end start

  1. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/2327383/1642752483000-b08ad514-e4b9-4dc2-ba37-2f9737612bec.png#clientId=u76955362-745d-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=190&id=u6d71a90f&margin=%5Bobject%20Object%5D&name=image.png&originHeight=537&originWidth=1691&originalType=binary&ratio=1&rotation=0&showTitle=false&size=128840&status=done&style=none&taskId=u94c7ae7f-f456-4382-b0c9-a4a2d80d919&title=&width=599.3333740234375)
  2. <a name="OvNt7"></a>
  3. ### 移出位数大于 1

assume cs:code

code segment start:mov al,11001000B mov cl,3 shl al,cl ; 左移一位

  1. mov ax,4c00h
  2. int 21h

code ends end start

  1. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/2327383/1642752758262-718f2b4e-1ca2-4dd7-aa75-39370b43b37f.png#clientId=u76955362-745d-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=253&id=u598f37e9&margin=%5Bobject%20Object%5D&name=image.png&originHeight=671&originWidth=1510&originalType=binary&ratio=1&rotation=0&showTitle=false&size=144658&status=done&style=none&taskId=u6f1ac387-6e18-4dc0-b306-953e61a441a&title=&width=568.3333740234375)
  2. <a name="DzIMI"></a>
  3. ### 计算 ax·10

assume cs:code

code segment

start: mov ax,10 ; Ah mov bx,ax shl ax,1 ; 左移 1 位 (ax)=(ax)×2 mov cl,3 shl bx,cl ; 左移 3 位 (bx)=(ax)×8 add ax,bx ; (ax)=(ax)×2+(ax)×8 ; 结果 (ax)=64h

  1. mov ax,4c00h
  2. int 21h

code ends

end start ```

逻辑右移 shr

最高位用0补齐,最后移出的放在cf