鱼C论坛

 找回密码
 立即注册
查看: 2561|回复: 0

[学习笔记] X86汇编语言-从实模式到保护模式—笔记(11)

[复制链接]
发表于 2017-11-2 21:17:47 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 兰陵月 于 2017-12-5 21:55 编辑

第8、9章  硬盘和显卡的访问与控制、中断和动态时钟显示

例程理解学习

一、实时时钟程序

实时时钟程序源代码~
  1.          ;代码清单9-1
  2.          ;文件名:c09_1.asm
  3.          ;文件说明:用户程序
  4.          ;创建日期:2011-4-16 22:03

  5. ;===============================================================================
  6. SECTION header vstart=0                     ;定义用户程序头部段
  7.     program_length  dd program_end          ;程序总长度[0x00]

  8.     ;用户程序入口点
  9.     code_entry      dw start                ;偏移地址[0x04]
  10.                     dd section.code.start   ;段地址[0x06]

  11.     realloc_tbl_len dw (header_end-realloc_begin)/4
  12.                                             ;段重定位表项个数[0x0a]

  13.     realloc_begin:
  14.     ;段重定位表
  15.     code_segment    dd section.code.start   ;[0x0c]  ;已被加载
  16.     data_segment    dd section.data.start   ;[0x14]
  17.     stack_segment   dd section.stack.start  ;[0x1c]

  18. header_end:

  19. ;===============================================================================
  20. SECTION code align=16 vstart=0           ;定义代码段(16字节对齐)
  21. new_int_0x70:
  22.       push ax
  23.       push bx
  24.       push cx
  25.       push dx
  26.       push es

  27.   .w0:
  28.       mov al,0x0a                        ;阻断NMI。当然,通常是不必要的
  29.       or al,0x80
  30.       out 0x70,al
  31.       in al,0x71                         ;读寄存器A
  32.       test al,0x80                       ;测试第7位UIP
  33.       jnz .w0                            ;以上代码对于更新周期结束中断来说
  34.                                          ;是不必要的
  35.       xor al,al
  36.       or al,0x80
  37.       out 0x70,al
  38.       in al,0x71                         ;读RTC当前时间(秒)
  39.       push ax

  40.       mov al,2
  41.       or al,0x80
  42.       out 0x70,al
  43.       in al,0x71                         ;读RTC当前时间(分)
  44.       push ax

  45.       mov al,4
  46.       or al,0x80
  47.       out 0x70,al
  48.       in al,0x71                         ;读RTC当前时间(时)
  49.       push ax

  50.       mov al,0x0c                        ;寄存器C的索引。且开放NMI
  51.       out 0x70,al
  52.       in al,0x71                         ;读一下RTC的寄存器C,否则只发生一次中断
  53.                                          ;此处不考虑闹钟和周期性中断的情况
  54.       mov ax,0xb800
  55.       mov es,ax

  56.       pop ax
  57.       call bcd_to_ascii
  58.       mov bx,12*160 + 36*2               ;从屏幕上的12行36列开始显示

  59.       mov [es:bx],ah
  60.       mov [es:bx+2],al                   ;显示两位小时数字

  61.       mov al,':'
  62.       mov [es:bx+4],al                   ;显示分隔符':'
  63.       not byte [es:bx+5]                 ;反转显示属性

  64.       pop ax
  65.       call bcd_to_ascii
  66.       mov [es:bx+6],ah
  67.       mov [es:bx+8],al                   ;显示两位分钟数字

  68.       mov al,':'
  69.       mov [es:bx+10],al                  ;显示分隔符':'
  70.       not byte [es:bx+11]                ;反转显示属性

  71.       pop ax
  72.       call bcd_to_ascii
  73.       mov [es:bx+12],ah
  74.       mov [es:bx+14],al                  ;显示两位小时数字

  75.       mov al,0x20                        ;中断结束命令EOI
  76.       out 0xa0,al                        ;向从片发送
  77.       out 0x20,al                        ;向主片发送

  78.       pop es
  79.       pop dx
  80.       pop cx
  81.       pop bx
  82.       pop ax

  83.       iret

  84. ;-------------------------------------------------------------------------------
  85. bcd_to_ascii:                            ;BCD码转ASCII
  86.                                          ;输入:AL=bcd码
  87.                                          ;输出:AX=ascii
  88.       mov ah,al                          ;分拆成两个数字
  89.       and al,0x0f                        ;仅保留低4位
  90.       add al,0x30                        ;转换成ASCII

  91.       shr ah,4                           ;逻辑右移4位
  92.       and ah,0x0f
  93.       add ah,0x30

  94.       ret

  95. ;-------------------------------------------------------------------------------
  96. start:
  97.       mov ax,[stack_segment]
  98.       mov ss,ax
  99.       mov sp,ss_pointer
  100.       mov ax,[data_segment]
  101.       mov ds,ax

  102.       mov bx,init_msg                    ;显示初始信息
  103.       call put_string

  104.       mov bx,inst_msg                    ;显示安装信息
  105.       call put_string

  106.       mov al,0x70
  107.       mov bl,4
  108.       mul bl                             ;计算0x70号中断在IVT中的偏移
  109.       mov bx,ax

  110.       cli                                ;防止改动期间发生新的0x70号中断

  111.       push es
  112.       mov ax,0x0000
  113.       mov es,ax
  114.       mov word [es:bx],new_int_0x70      ;偏移地址。

  115.       mov word [es:bx+2],cs              ;段地址
  116.       pop es

  117.       mov al,0x0b                        ;RTC寄存器B
  118.       or al,0x80                         ;阻断NMI
  119.       out 0x70,al
  120.       mov al,0x12                        ;设置寄存器B,禁止周期性中断,开放更
  121.       out 0x71,al                        ;新结束后中断,BCD码,24小时制

  122.       mov al,0x0c
  123.       out 0x70,al
  124.       in al,0x71                         ;读RTC寄存器C,复位未决的中断状态

  125.       in al,0xa1                         ;读8259从片的IMR寄存器
  126.       and al,0xfe                        ;清除bit 0(此位连接RTC)
  127.       out 0xa1,al                        ;写回此寄存器

  128.       sti                                ;重新开放中断

  129.       mov bx,done_msg                    ;显示安装完成信息
  130.       call put_string

  131.       mov bx,tips_msg                    ;显示提示信息
  132.       call put_string

  133.       mov cx,0xb800
  134.       mov ds,cx
  135.       mov byte [12*160 + 33*2],'@'       ;屏幕第12行,35列

  136. .idle:
  137.       hlt                                ;使CPU进入低功耗状态,直到用中断唤醒
  138.       not byte [12*160 + 33*2+1]         ;反转显示属性
  139.       jmp .idle

  140. ;-------------------------------------------------------------------------------
  141. put_string:                              ;显示串(0结尾)。
  142.                                          ;输入:DS:BX=串地址
  143.          mov cl,[bx]
  144.          or cl,cl                        ;cl=0 ?
  145.          jz .exit                        ;是的,返回主程序
  146.          call put_char
  147.          inc bx                          ;下一个字符
  148.          jmp put_string

  149.    .exit:
  150.          ret

  151. ;-------------------------------------------------------------------------------
  152. put_char:                                ;显示一个字符
  153.                                          ;输入:cl=字符ascii
  154.          push ax
  155.          push bx
  156.          push cx
  157.          push dx
  158.          push ds
  159.          push es

  160.          ;以下取当前光标位置
  161.          mov dx,0x3d4
  162.          mov al,0x0e
  163.          out dx,al
  164.          mov dx,0x3d5
  165.          in al,dx                        ;高8位
  166.          mov ah,al

  167.          mov dx,0x3d4
  168.          mov al,0x0f
  169.          out dx,al
  170.          mov dx,0x3d5
  171.          in al,dx                        ;低8位
  172.          mov bx,ax                       ;BX=代表光标位置的16位数

  173.          cmp cl,0x0d                     ;回车符?
  174.          jnz .put_0a                     ;不是。看看是不是换行等字符
  175.          mov ax,bx                       ;
  176.          mov bl,80
  177.          div bl
  178.          mul bl
  179.          mov bx,ax
  180.          jmp .set_cursor

  181. .put_0a:
  182.          cmp cl,0x0a                     ;换行符?
  183.          jnz .put_other                  ;不是,那就正常显示字符
  184.          add bx,80
  185.          jmp .roll_screen

  186. .put_other:                             ;正常显示字符
  187.          mov ax,0xb800
  188.          mov es,ax
  189.          shl bx,1
  190.          mov [es:bx],cl

  191.          ;以下将光标位置推进一个字符
  192.          shr bx,1
  193.          add bx,1

  194. .roll_screen:
  195.          cmp bx,2000                     ;光标超出屏幕?滚屏
  196.          jl .set_cursor

  197.          mov ax,0xb800
  198.          mov ds,ax
  199.          mov es,ax
  200.          cld
  201.          mov si,0xa0
  202.          mov di,0x00
  203.          mov cx,1920
  204.          rep movsw
  205.          mov bx,3840                     ;清除屏幕最底一行
  206.          mov cx,80
  207. .cls:
  208.          mov word[es:bx],0x0720
  209.          add bx,2
  210.          loop .cls

  211.          mov bx,1920

  212. .set_cursor:
  213.          mov dx,0x3d4
  214.          mov al,0x0e
  215.          out dx,al
  216.          mov dx,0x3d5
  217.          mov al,bh
  218.          out dx,al
  219.          mov dx,0x3d4
  220.          mov al,0x0f
  221.          out dx,al
  222.          mov dx,0x3d5
  223.          mov al,bl
  224.          out dx,al

  225.          pop es
  226.          pop ds
  227.          pop dx
  228.          pop cx
  229.          pop bx
  230.          pop ax

  231.          ret

  232. ;===============================================================================
  233. SECTION data align=16 vstart=0

  234.     init_msg       db 'Starting...',0x0d,0x0a,0

  235.     inst_msg       db 'Installing a new interrupt 70H...',0

  236.     done_msg       db 'Done.',0x0d,0x0a,0

  237.     tips_msg       db 'Clock is now working.',0

  238. ;===============================================================================
  239. SECTION stack align=16 vstart=0

  240.                  resb 256
  241. ss_pointer:

  242. ;===============================================================================
  243. SECTION program_trail
  244. program_end:
复制代码

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-25 19:56

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表