请选择 进入手机版 | 继续访问电脑版

4Ameta

 找回密码
 立即注册
搜索
查看: 64|回复: 0

Learn x86 protected mode assembly language-c09_1.asm

[复制链接]

26

主题

26

帖子

119

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
119
发表于 2022-9-12 20:13:10 | 显示全部楼层 |阅读模式
  1.          ;代码清单9-1
  2.          ;文件名:c09_1.asm
  3.          ;文件说明:用户程序
  4.          ;创建日期:2011-4-16 22:03
  5.          
  6. ;===============================================================================
  7. SECTION header vstart=0                     ;定义用户程序头部段
  8.     program_length  dd program_end          ;程序总长度[0x00]
  9.    
  10.     ;用户程序入口点
  11.     code_entry      dw start                ;偏移地址[0x04]
  12.                     dd section.code.start   ;段地址[0x06]
  13.    
  14.     realloc_tbl_len dw (header_end-realloc_begin)/4
  15.                                             ;段重定位表项个数[0x0a]
  16.    
  17.     realloc_begin:
  18.     ;段重定位表           
  19.     code_segment    dd section.code.start   ;[0x0c]
  20.     data_segment    dd section.data.start   ;[0x14]
  21.     stack_segment   dd section.stack.start  ;[0x1c]
  22.    
  23. header_end:               
  24.    
  25. ;===============================================================================
  26. SECTION code align=16 vstart=0           ;定义代码段(16字节对齐)
  27. new_int_0x70:
  28.       push ax
  29.       push bx
  30.       push cx
  31.       push dx
  32.       push es
  33.       
  34.   .w0:                                    
  35.       mov al,0x0a                        ;阻断NMI。当然,通常是不必要的
  36.       or al,0x80                          
  37.       out 0x70,al
  38.       in al,0x71                         ;读寄存器A
  39.       test al,0x80                       ;测试第7位UIP
  40.       jnz .w0                            ;以上代码对于更新周期结束中断来说
  41.                                          ;是不必要的
  42.       xor al,al
  43.       or al,0x80
  44.       out 0x70,al
  45.       in al,0x71                         ;读RTC当前时间(秒)
  46.       push ax

  47.       mov al,2
  48.       or al,0x80
  49.       out 0x70,al
  50.       in al,0x71                         ;读RTC当前时间(分)
  51.       push ax

  52.       mov al,4
  53.       or al,0x80
  54.       out 0x70,al
  55.       in al,0x71                         ;读RTC当前时间(时)
  56.       push ax

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

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

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

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

  71.       pop ax
  72.       call bcd_to_ascii
  73.       mov [es:bx+6],ah
  74.       mov [es:bx+8],al                   ;显示两位分钟数字

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

  78.       pop ax
  79.       call bcd_to_ascii
  80.       mov [es:bx+12],ah
  81.       mov [es:bx+14],al                  ;显示两位小时数字
  82.       
  83.       mov al,0x20                        ;中断结束命令EOI
  84.       out 0xa0,al                        ;向从片发送
  85.       out 0x20,al                        ;向主片发送

  86.       pop es
  87.       pop dx
  88.       pop cx
  89.       pop bx
  90.       pop ax

  91.       iret

  92. ;-------------------------------------------------------------------------------
  93. bcd_to_ascii:                            ;BCD码转ASCII
  94.                                          ;输入:AL=bcd码
  95.                                          ;输出:AX=ascii
  96.       mov ah,al                          ;分拆成两个数字
  97.       and al,0x0f                        ;仅保留低4位
  98.       add al,0x30                        ;转换成ASCII

  99.       shr ah,4                           ;逻辑右移4位
  100.       and ah,0x0f                        
  101.       add ah,0x30

  102.       ret

  103. ;-------------------------------------------------------------------------------
  104. start:
  105.       mov ax,[stack_segment]
  106.       mov ss,ax
  107.       mov sp,ss_pointer
  108.       mov ax,[data_segment]
  109.       mov ds,ax
  110.       
  111.       mov bx,init_msg                    ;显示初始信息
  112.       call put_string

  113.       mov bx,inst_msg                    ;显示安装信息
  114.       call put_string

  115. ;BIOS启动时,设置主片的中断号从0x80开始,从片的中断号从0x70开始,RTC是从片中第一个中断
  116.       mov al,0x70
  117.       mov bl,4
  118.       mul bl                             ;计算0x70号中断在IVT中的偏移
  119.       mov bx,ax                          

  120.          
  121. ;第一步,替换系统中的默认的0x70中断号地址
  122. ;替换掉自己的程序,即:每当0x70中断时将执行这个程序         
  123.       cli                                ;防止改动期间发生新的0x70号中断

  124.       push es
  125.       mov ax,0x0000
  126.       mov es,ax
  127.       mov word [es:bx],new_int_0x70      ;偏移地址。
  128.                                           
  129.       mov word [es:bx+2],cs              ;段地址
  130.       pop es

  131. ;第二步,0x70中断是RTC中断;RTC中断要满足一定条件
  132. ;a、关闭NMI中断
  133. ;b、设置三个中断中的某个中断
  134. ;c、读取c寄存器,清空寄存器,准备接受中断
  135. ;d、设置IMR寄存器,主片为:0x20/0x21 从片为:0xa0/0xa1
  136.          
  137.       mov al,0x0b                        ;RTC寄存器B
  138.       or al,0x80                         ;阻断NMI
  139.       out 0x70,al
  140.       mov al,0x12                        ;设置寄存器B,禁止周期性中断,开放更
  141.       out 0x71,al                        ;新结束后中断,BCD码,24小时制

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

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

  148.       sti                                ;重新开放中断

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

  151.       mov bx,tips_msg                    ;显示提示信息
  152.       call put_string
  153.       
  154.       mov cx,0xb800
  155.       mov ds,cx
  156.       mov byte [12*160 + 33*2],'@'       ;屏幕第12行,35列
  157.       
  158. .idle:
  159.       hlt                                ;使CPU进入低功耗状态,直到用中断唤醒
  160.       not byte [12*160 + 33*2+1]         ;反转显示属性
  161.       jmp .idle

  162. ;-------------------------------------------------------------------------------
  163. put_string:                              ;显示串(0结尾)。
  164.                                          ;输入:DS:BX=串地址
  165.          mov cl,[bx]
  166.          or cl,cl                        ;cl=0 ?
  167.          jz .exit                        ;是的,返回主程序
  168.          call put_char
  169.          inc bx                          ;下一个字符
  170.          jmp put_string

  171.    .exit:
  172.          ret

  173. ;-------------------------------------------------------------------------------
  174. put_char:                                ;显示一个字符
  175.                                          ;输入:cl=字符ascii
  176.          push ax
  177.          push bx
  178.          push cx
  179.          push dx
  180.          push ds
  181.          push es

  182.          ;以下取当前光标位置
  183.          mov dx,0x3d4
  184.          mov al,0x0e
  185.          out dx,al
  186.          mov dx,0x3d5
  187.          in al,dx                        ;高8位
  188.          mov ah,al

  189.          mov dx,0x3d4
  190.          mov al,0x0f
  191.          out dx,al
  192.          mov dx,0x3d5
  193.          in al,dx                        ;低8位
  194.          mov bx,ax                       ;BX=代表光标位置的16位数

  195.          cmp cl,0x0d                     ;回车符?
  196.          jnz .put_0a                     ;不是。看看是不是换行等字符
  197.          mov ax,bx                       ;
  198.          mov bl,80                       
  199.          div bl
  200.          mul bl
  201.          mov bx,ax
  202.          jmp .set_cursor

  203. .put_0a:
  204.          cmp cl,0x0a                     ;换行符?
  205.          jnz .put_other                  ;不是,那就正常显示字符
  206.          add bx,80
  207.          jmp .roll_screen

  208. .put_other:                             ;正常显示字符
  209.          mov ax,0xb800
  210.          mov es,ax
  211.          shl bx,1
  212.          mov [es:bx],cl

  213.          ;以下将光标位置推进一个字符
  214.          shr bx,1
  215.          add bx,1

  216. .roll_screen:
  217.          cmp bx,2000                     ;光标超出屏幕?滚屏
  218.          jl .set_cursor

  219.          mov ax,0xb800
  220.          mov ds,ax
  221.          mov es,ax
  222.          cld
  223.          mov si,0xa0
  224.          mov di,0x00
  225.          mov cx,1920
  226.          rep movsw
  227.          mov bx,3840                     ;清除屏幕最底一行
  228.          mov cx,80
  229. .cls:
  230.          mov word[es:bx],0x0720
  231.          add bx,2
  232.          loop .cls

  233.          mov bx,1920

  234. .set_cursor:
  235.          mov dx,0x3d4
  236.          mov al,0x0e
  237.          out dx,al
  238.          mov dx,0x3d5
  239.          mov al,bh
  240.          out dx,al
  241.          mov dx,0x3d4
  242.          mov al,0x0f
  243.          out dx,al
  244.          mov dx,0x3d5
  245.          mov al,bl
  246.          out dx,al

  247.          pop es
  248.          pop ds
  249.          pop dx
  250.          pop cx
  251.          pop bx
  252.          pop ax

  253.          ret

  254. ;===============================================================================
  255. SECTION data align=16 vstart=0

  256.     init_msg       db 'Starting...',0x0d,0x0a,0
  257.                   
  258.     inst_msg       db 'Installing a new interrupt 70H...',0
  259.    
  260.     done_msg       db 'Done.',0x0d,0x0a,0

  261.     tips_msg       db 'Clock is now working.',0
  262.                   
  263. ;===============================================================================
  264. SECTION stack align=16 vstart=0
  265.            
  266.                  resb 256
  267. ss_pointer:

  268. ;===============================================================================
  269. SECTION program_trail
  270. program_end:
复制代码



  1.      1                                           ;代码清单9-1
  2.      2                                           ;文件名:c09_1.asm
  3.      3                                           ;文件说明:用户程序
  4.      4                                           ;创建日期:2011-4-16 22:03
  5.      5                                          
  6.      6                                  ;===============================================================================
  7.      7                                  SECTION header vstart=0                     ;定义用户程序头部段
  8.      8 00000000 [00000000]                  program_length  dd program_end          ;程序总长度[0x00]
  9.      9                                      
  10.     10                                      ;用户程序入口点
  11.     11 00000004 [8D00]                      code_entry      dw start                ;偏移地址[0x04]
  12.     12 00000006 [00000000]                                  dd section.code.start   ;段地址[0x06]
  13.     13                                      
  14.     14 0000000A 0300                        realloc_tbl_len dw (header_end-realloc_begin)/4
  15.     15                                                                              ;段重定位表项个数[0x0a]
  16.     16                                      
  17.     17                                      realloc_begin:
  18.     18                                      ;段重定位表           
  19.     19 0000000C [00000000]                  code_segment    dd section.code.start   ;[0x0c]
  20.     20 00000010 [00000000]                  data_segment    dd section.data.start   ;[0x14]
  21.     21 00000014 [00000000]                  stack_segment   dd section.stack.start  ;[0x1c]
  22.     22                                      
  23.     23                                  header_end:               
  24.     24                                      
  25.     25                                  ;===============================================================================
  26.     26                                  SECTION code align=16 vstart=0           ;定义代码段(16字节对齐)
  27.     27                                  new_int_0x70:
  28.     28 00000000 50                            push ax
  29.     29 00000001 53                            push bx
  30.     30 00000002 51                            push cx
  31.     31 00000003 52                            push dx
  32.     32 00000004 06                            push es
  33.     33                                       
  34.     34                                    .w0:                                    
  35.     35 00000005 B00A                          mov al,0x0a                        ;阻断NMI。当然,通常是不必要的
  36.     36 00000007 0C80                          or al,0x80                          
  37.     37 00000009 E670                          out 0x70,al
  38.     38 0000000B E471                          in al,0x71                         ;读寄存器A
  39.     39 0000000D A880                          test al,0x80                       ;测试第7位UIP
  40.     40 0000000F 75F4                          jnz .w0                            ;以上代码对于更新周期结束中断来说
  41.     41                                                                           ;是不必要的
  42.     42 00000011 30C0                          xor al,al
  43.     43 00000013 0C80                          or al,0x80
  44.     44 00000015 E670                          out 0x70,al
  45.     45 00000017 E471                          in al,0x71                         ;读RTC当前时间(秒)
  46.     46 00000019 50                            push ax
  47.     47                                 
  48.     48 0000001A B002                          mov al,2
  49.     49 0000001C 0C80                          or al,0x80
  50.     50 0000001E E670                          out 0x70,al
  51.     51 00000020 E471                          in al,0x71                         ;读RTC当前时间(分)
  52.     52 00000022 50                            push ax
  53.     53                                 
  54.     54 00000023 B004                          mov al,4
  55.     55 00000025 0C80                          or al,0x80
  56.     56 00000027 E670                          out 0x70,al
  57.     57 00000029 E471                          in al,0x71                         ;读RTC当前时间(时)
  58.     58 0000002B 50                            push ax
  59.     59                                 
  60.     60 0000002C B00C                          mov al,0x0c                        ;寄存器C的索引。且开放NMI
  61.     61 0000002E E670                          out 0x70,al
  62.     62 00000030 E471                          in al,0x71                         ;读一下RTC的寄存器C,否则只发生一次中断
  63.     63                                                                           ;此处不考虑闹钟和周期性中断的情况
  64.     64 00000032 B800B8                        mov ax,0xb800
  65.     65 00000035 8EC0                          mov es,ax
  66.     66                                 
  67.     67 00000037 58                            pop ax
  68.     68 00000038 E84200                        call bcd_to_ascii
  69.     69 0000003B BBC807                        mov bx,12*160 + 36*2               ;从屏幕上的12行36列开始显示
  70.     70                                 
  71.     71 0000003E 268827                        mov [es:bx],ah
  72.     72 00000041 26884702                      mov [es:bx+2],al                   ;显示两位小时数字
  73.     73                                 
  74.     74 00000045 B03A                          mov al,':'
  75.     75 00000047 26884704                      mov [es:bx+4],al                   ;显示分隔符':'
  76.     76 0000004B 26F65705                      not byte [es:bx+5]                 ;反转显示属性
  77.     77                                 
  78.     78 0000004F 58                            pop ax
  79.     79 00000050 E82A00                        call bcd_to_ascii
  80.     80 00000053 26886706                      mov [es:bx+6],ah
  81.     81 00000057 26884708                      mov [es:bx+8],al                   ;显示两位分钟数字
  82.     82                                 
  83.     83 0000005B B03A                          mov al,':'
  84.     84 0000005D 2688470A                      mov [es:bx+10],al                  ;显示分隔符':'
  85.     85 00000061 26F6570B                      not byte [es:bx+11]                ;反转显示属性
  86.     86                                 
  87.     87 00000065 58                            pop ax
  88.     88 00000066 E81400                        call bcd_to_ascii
  89.     89 00000069 2688670C                      mov [es:bx+12],ah
  90.     90 0000006D 2688470E                      mov [es:bx+14],al                  ;显示两位小时数字
  91.     91                                       
  92.     92 00000071 B020                          mov al,0x20                        ;中断结束命令EOI
  93.     93 00000073 E6A0                          out 0xa0,al                        ;向从片发送
  94.     94 00000075 E620                          out 0x20,al                        ;向主片发送
  95.     95                                 
  96.     96 00000077 07                            pop es
  97.     97 00000078 5A                            pop dx
  98.     98 00000079 59                            pop cx
  99.     99 0000007A 5B                            pop bx
  100.    100 0000007B 58                            pop ax
  101.    101                                 
  102.    102 0000007C CF                            iret
  103.    103                                 
  104.    104                                  ;-------------------------------------------------------------------------------
  105.    105                                  bcd_to_ascii:                            ;BCD码转ASCII
  106.    106                                                                           ;输入:AL=bcd码
  107.    107                                                                           ;输出:AX=ascii
  108.    108 0000007D 88C4                          mov ah,al                          ;分拆成两个数字
  109.    109 0000007F 240F                          and al,0x0f                        ;仅保留低4位
  110.    110 00000081 0430                          add al,0x30                        ;转换成ASCII
  111.    111                                 
  112.    112 00000083 C0EC04                        shr ah,4                           ;逻辑右移4位
  113.    113 00000086 80E40F                        and ah,0x0f                        
  114.    114 00000089 80C430                        add ah,0x30
  115.    115                                 
  116.    116 0000008C C3                            ret
  117.    117                                 
  118.    118                                  ;-------------------------------------------------------------------------------
  119.    119                                  start:
  120.    120 0000008D A1[1400]                      mov ax,[stack_segment]
  121.    121 00000090 8ED0                          mov ss,ax
  122.    122 00000092 BC[0001]                      mov sp,ss_pointer
  123.    123 00000095 A1[1000]                      mov ax,[data_segment]
  124.    124 00000098 8ED8                          mov ds,ax
  125.    125                                       
  126.    126 0000009A BB[0000]                      mov bx,init_msg                    ;显示初始信息
  127.    127 0000009D E85400                        call put_string
  128.    128                                 
  129.    129 000000A0 BB[0E00]                      mov bx,inst_msg                    ;显示安装信息
  130.    130 000000A3 E84E00                        call put_string
  131.    131                                       
  132.    132 000000A6 B070                          mov al,0x70
  133.    133 000000A8 B304                          mov bl,4
  134.    134 000000AA F6E3                          mul bl                             ;计算0x70号中断在IVT中的偏移
  135.    135 000000AC 89C3                          mov bx,ax                          
  136.    136                                 
  137.    137 000000AE FA                            cli                                ;防止改动期间发生新的0x70号中断
  138.    138                                 
  139.    139 000000AF 06                            push es
  140.    140 000000B0 B80000                        mov ax,0x0000
  141.    141 000000B3 8EC0                          mov es,ax
  142.    142 000000B5 26C707[0000]                  mov word [es:bx],new_int_0x70      ;偏移地址。
  143.    143                                                                           
  144.    144 000000BA 268C4F02                      mov word [es:bx+2],cs              ;段地址
  145.    145 000000BE 07                            pop es
  146.    146                                 
  147.    147 000000BF B00B                          mov al,0x0b                        ;RTC寄存器B
  148.    148 000000C1 0C80                          or al,0x80                         ;阻断NMI
  149.    149 000000C3 E670                          out 0x70,al
  150.    150 000000C5 B012                          mov al,0x12                        ;设置寄存器B,禁止周期性中断,开放更
  151.    151 000000C7 E671                          out 0x71,al                        ;新结束后中断,BCD码,24小时制
  152.    152                                 
  153.    153 000000C9 B00C                          mov al,0x0c
  154.    154 000000CB E670                          out 0x70,al
  155.    155 000000CD E471                          in al,0x71                         ;读RTC寄存器C,复位未决的中断状态
  156.    156                                 
  157.    157 000000CF E4A1                          in al,0xa1                         ;读8259从片的IMR寄存器
  158.    158 000000D1 24FE                          and al,0xfe                        ;清除bit 0(此位连接RTC)
  159.    159 000000D3 E6A1                          out 0xa1,al                        ;写回此寄存器
  160.    160                                 
  161.    161 000000D5 FB                            sti                                ;重新开放中断
  162.    162                                 
  163.    163 000000D6 BB[3000]                      mov bx,done_msg                    ;显示安装完成信息
  164.    164 000000D9 E81800                        call put_string
  165.    165                                 
  166.    166 000000DC BB[3800]                      mov bx,tips_msg                    ;显示提示信息
  167.    167 000000DF E81200                        call put_string
  168.    168                                       
  169.    169 000000E2 B900B8                        mov cx,0xb800
  170.    170 000000E5 8ED9                          mov ds,cx
  171.    171 000000E7 C606C20740                    mov byte [12*160 + 33*2],'@'       ;屏幕第12行,35列
  172.    172                                         
  173.    173                                   .idle:
  174.    174 000000EC F4                            hlt                                ;使CPU进入低功耗状态,直到用中断唤醒
  175.    175 000000ED F616C307                      not byte [12*160 + 33*2+1]         ;反转显示属性
  176.    176 000000F1 E9F8FF                        jmp .idle
  177.    177                                 
  178.    178                                  ;-------------------------------------------------------------------------------
  179.    179                                  put_string:                              ;显示串(0结尾)。
  180.    180                                                                           ;输入:DS:BX=串地址
  181.    181 000000F4 8A0F                             mov cl,[bx]
  182.    182 000000F6 08C9                             or cl,cl                        ;cl=0 ?
  183.    183 000000F8 7407                             jz .exit                        ;是的,返回主程序
  184.    184 000000FA E80500                           call put_char
  185.    185 000000FD 43                               inc bx                          ;下一个字符
  186.    186 000000FE E9F3FF                           jmp put_string
  187.    187                                 
  188.    188                                     .exit:
  189.    189 00000101 C3                               ret
  190.    190                                 
  191.    191                                  ;-------------------------------------------------------------------------------
  192.    192                                  put_char:                                ;显示一个字符
  193.    193                                                                           ;输入:cl=字符ascii
  194.    194 00000102 50                               push ax
  195.    195 00000103 53                               push bx
  196.    196 00000104 51                               push cx
  197.    197 00000105 52                               push dx
  198.    198 00000106 1E                               push ds
  199.    199 00000107 06                               push es
  200.    200                                 
  201.    201                                           ;以下取当前光标位置
  202.    202 00000108 BAD403                           mov dx,0x3d4
  203.    203 0000010B B00E                             mov al,0x0e
  204.    204 0000010D EE                               out dx,al
  205.    205 0000010E BAD503                           mov dx,0x3d5
  206.    206 00000111 EC                               in al,dx                        ;高8位
  207.    207 00000112 88C4                             mov ah,al
  208.    208                                 
  209.    209 00000114 BAD403                           mov dx,0x3d4
  210.    210 00000117 B00F                             mov al,0x0f
  211.    211 00000119 EE                               out dx,al
  212.    212 0000011A BAD503                           mov dx,0x3d5
  213.    213 0000011D EC                               in al,dx                        ;低8位
  214.    214 0000011E 89C3                             mov bx,ax                       ;BX=代表光标位置的16位数
  215.    215                                 
  216.    216 00000120 80F90D                           cmp cl,0x0d                     ;回车符?
  217.    217 00000123 750D                             jnz .put_0a                     ;不是。看看是不是换行等字符
  218.    218 00000125 89D8                             mov ax,bx                       ;
  219.    219 00000127 B350                             mov bl,80                       
  220.    220 00000129 F6F3                             div bl
  221.    221 0000012B F6E3                             mul bl
  222.    222 0000012D 89C3                             mov bx,ax
  223.    223 0000012F E94900                           jmp .set_cursor
  224.    224                                 
  225.    225                                   .put_0a:
  226.    226 00000132 80F90A                           cmp cl,0x0a                     ;换行符?
  227.    227 00000135 7507                             jnz .put_other                  ;不是,那就正常显示字符
  228.    228 00000137 81C35000                         add bx,80
  229.    229 0000013B E91000                           jmp .roll_screen
  230.    230                                 
  231.    231                                   .put_other:                             ;正常显示字符
  232.    232 0000013E B800B8                           mov ax,0xb800
  233.    233 00000141 8EC0                             mov es,ax
  234.    234 00000143 D1E3                             shl bx,1
  235.    235 00000145 26880F                           mov [es:bx],cl
  236.    236                                 
  237.    237                                           ;以下将光标位置推进一个字符
  238.    238 00000148 D1EB                             shr bx,1
  239.    239 0000014A 81C30100                         add bx,1
  240.    240                                 
  241.    241                                   .roll_screen:
  242.    242 0000014E 81FBD007                         cmp bx,2000                     ;光标超出屏幕?滚屏
  243.    243 00000152 7C27                             jl .set_cursor
  244.    244                                 
  245.    245 00000154 B800B8                           mov ax,0xb800
  246.    246 00000157 8ED8                             mov ds,ax
  247.    247 00000159 8EC0                             mov es,ax
  248.    248 0000015B FC                               cld
  249.    249 0000015C BEA000                           mov si,0xa0
  250.    250 0000015F BF0000                           mov di,0x00
  251.    251 00000162 B98007                           mov cx,1920
  252.    252 00000165 F3A5                             rep movsw
  253.    253 00000167 BB000F                           mov bx,3840                     ;清除屏幕最底一行
  254.    254 0000016A B95000                           mov cx,80
  255.    255                                   .cls:
  256.    256 0000016D 26C7072007                       mov word[es:bx],0x0720
  257.    257 00000172 81C30200                         add bx,2
  258.    258 00000176 E2F5                             loop .cls
  259.    259                                 
  260.    260 00000178 BB8007                           mov bx,1920
  261.    261                                 
  262.    262                                   .set_cursor:
  263.    263 0000017B BAD403                           mov dx,0x3d4
  264.    264 0000017E B00E                             mov al,0x0e
  265.    265 00000180 EE                               out dx,al
  266.    266 00000181 BAD503                           mov dx,0x3d5
  267.    267 00000184 88F8                             mov al,bh
  268.    268 00000186 EE                               out dx,al
  269.    269 00000187 BAD403                           mov dx,0x3d4
  270.    270 0000018A B00F                             mov al,0x0f
  271.    271 0000018C EE                               out dx,al
  272.    272 0000018D BAD503                           mov dx,0x3d5
  273.    273 00000190 88D8                             mov al,bl
  274.    274 00000192 EE                               out dx,al
  275.    275                                 
  276.    276 00000193 07                               pop es
  277.    277 00000194 1F                               pop ds
  278.    278 00000195 5A                               pop dx
  279.    279 00000196 59                               pop cx
  280.    280 00000197 5B                               pop bx
  281.    281 00000198 58                               pop ax
  282.    282                                 
  283.    283 00000199 C3                               ret
  284.    284                                 
  285.    285                                  ;===============================================================================
  286.    286                                  SECTION data align=16 vstart=0
  287.    287                                 
  288.    288 00000000 5374617274696E672E-         init_msg       db 'Starting...',0x0d,0x0a,0
  289.    289 00000009 2E2E0D0A00         
  290.    290                                                     
  291.    291 0000000E 496E7374616C6C696E-         inst_msg       db 'Installing a new interrupt 70H...',0
  292.    292 00000017 672061206E65772069-
  293.    293 00000020 6E7465727275707420-
  294.    294 00000029 3730482E2E2E00     
  295.    295                                      
  296.    296 00000030 446F6E652E0D0A00            done_msg       db 'Done.',0x0d,0x0a,0
  297.    297                                 
  298.    298 00000038 436C6F636B20697320-         tips_msg       db 'Clock is now working.',0
  299.    299 00000041 6E6F7720776F726B69-
  300.    300 0000004A 6E672E00           
  301.    301                                                     
  302.    302                                  ;===============================================================================
  303.    303                                  SECTION stack align=16 vstart=0
  304.    304                                             
  305.    305 00000000 <res 00000100>                           resb 256
  306.    306          ******************       warning: uninitialized space declared in stack section: zeroing
  307.    307                                  ss_pointer:
  308.    308                                   
  309.    309                                  ;===============================================================================
  310.    310                                  SECTION program_trail
  311.    311                                  program_end:

复制代码


  1.          ;代码清单9-1
  2.          ;文件名:c09_1.asm
  3.          ;文件说明:用户程序
  4.          ;创建日期:2011-4-16 22:03
  5.          
  6. ;===============================================================================
  7. SECTION header vstart=0                     ;定义用户程序头部段
  8.     program_length  dd program_end          ;程序总长度[0x00]
  9.    
  10.     ;用户程序入口点
  11.     code_entry      dw start                ;偏移地址[0x04]
  12.                     dd section.code.start   ;段地址[0x06]
  13.    
  14.     realloc_tbl_len dw (header_end-realloc_begin)/4
  15.                                             ;段重定位表项个数[0x0a]
  16.    
  17.     realloc_begin:
  18.     ;段重定位表           
  19.     code_segment    dd section.code.start   ;[0x0c]
  20.     data_segment    dd section.data.start   ;[0x14]
  21.     stack_segment   dd section.stack.start  ;[0x1c]
  22.    
  23. header_end:               
  24.    
  25. ;===============================================================================
  26. SECTION code align=16 vstart=0           ;定义代码段(16字节对齐)
  27. new_int_0x70:
  28.       push ax
  29.       push bx
  30.       push cx
  31.       push dx
  32.       push es
  33.       
  34.   .w0:                                    
  35.       mov al,0x0a                        ;阻断NMI。当然,通常是不必要的
  36.       or al,0x80                          
  37.       out 0x70,al
  38.       in al,0x71                         ;读寄存器A
  39.       test al,0x80                       ;测试第7位UIP
  40.       jnz .w0                            ;以上代码对于更新周期结束中断来说
  41.                                          ;是不必要的
  42.       xor al,al
  43.       or al,0x80
  44.       out 0x70,al
  45.       in al,0x71                         ;读RTC当前时间(秒)
  46.       push ax

  47.       mov al,2
  48.       or al,0x80
  49.       out 0x70,al
  50.       in al,0x71                         ;读RTC当前时间(分)
  51.       push ax

  52.       mov al,4
  53.       or al,0x80
  54.       out 0x70,al
  55.       in al,0x71                         ;读RTC当前时间(时)
  56.       push ax

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

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

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

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

  71.       pop ax
  72.       call bcd_to_ascii
  73.       mov [es:bx+6],ah
  74.       mov [es:bx+8],al                   ;显示两位分钟数字

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

  78.       pop ax
  79.       call bcd_to_ascii
  80.       mov [es:bx+12],ah
  81.       mov [es:bx+14],al                  ;显示两位小时数字
  82.       
  83.       mov al,0x20                        ;中断结束命令EOI
  84.       out 0xa0,al                        ;向从片发送
  85.       out 0x20,al                        ;向主片发送

  86.       pop es
  87.       pop dx
  88.       pop cx
  89.       pop bx
  90.       pop ax

  91.       iret

  92. ;-------------------------------------------------------------------------------
  93. bcd_to_ascii:                            ;BCD码转ASCII
  94.                                          ;输入:AL=bcd码
  95.                                          ;输出:AX=ascii
  96.       mov ah,al                          ;分拆成两个数字
  97.       and al,0x0f                        ;仅保留低4位
  98.       add al,0x30                        ;转换成ASCII

  99.       shr ah,4                           ;逻辑右移4位
  100.       and ah,0x0f                        
  101.       add ah,0x30

  102.       ret

  103. ;-------------------------------------------------------------------------------
  104. start:
  105.       mov ax,[stack_segment]
  106.       mov ss,ax
  107.       mov sp,ss_pointer
  108.       mov ax,[data_segment]
  109.       mov ds,ax
  110.       
  111.       mov bx,init_msg                    ;显示初始信息
  112.       call put_string

  113.       mov bx,inst_msg                    ;显示安装信息
  114.       call put_string
  115.       
  116.       mov al,0x70
  117.       mov bl,4
  118.       mul bl                             ;计算0x70号中断在IVT中的偏移
  119.       mov bx,ax                          

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

  121.       push es
  122.       mov ax,0x0000
  123.       mov es,ax
  124.       mov word [es:bx],new_int_0x70      ;偏移地址。
  125.                                           
  126.       mov word [es:bx+2],cs              ;段地址
  127.       pop es

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

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

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

  139.       sti                                ;重新开放中断

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

  142.       mov bx,tips_msg                    ;显示提示信息
  143.       call put_string
  144.       
  145.       mov cx,0xb800
  146.       mov ds,cx
  147.       mov byte [12*160 + 33*2],'@'       ;屏幕第12行,35列
  148.       
  149. .idle:
  150.       hlt                                ;使CPU进入低功耗状态,直到用中断唤醒
  151.       not byte [12*160 + 33*2+1]         ;反转显示属性
  152.       jmp .idle

  153. ;-------------------------------------------------------------------------------
  154. put_string:                              ;显示串(0结尾)。
  155.                                          ;输入:DS:BX=串地址
  156.          mov cl,[bx]
  157.          or cl,cl                        ;cl=0 ?
  158.          jz .exit                        ;是的,返回主程序
  159.          call put_char
  160.          inc bx                          ;下一个字符
  161.          jmp put_string

  162.    .exit:
  163.          ret

  164. ;-------------------------------------------------------------------------------
  165. put_char:                                ;显示一个字符
  166.                                          ;输入:cl=字符ascii
  167.          push ax
  168.          push bx
  169.          push cx
  170.          push dx
  171.          push ds
  172.          push es

  173.          ;以下取当前光标位置
  174.          mov dx,0x3d4
  175.          mov al,0x0e
  176.          out dx,al
  177.          mov dx,0x3d5
  178.          in al,dx                        ;高8位
  179.          mov ah,al

  180.          mov dx,0x3d4
  181.          mov al,0x0f
  182.          out dx,al
  183.          mov dx,0x3d5
  184.          in al,dx                        ;低8位
  185.          mov bx,ax                       ;BX=代表光标位置的16位数

  186.          cmp cl,0x0d                     ;回车符?
  187.          jnz .put_0a                     ;不是。看看是不是换行等字符
  188.          mov ax,bx                       ;
  189.          mov bl,80                       
  190.          div bl
  191.          mul bl
  192.          mov bx,ax
  193.          jmp .set_cursor

  194. .put_0a:
  195.          cmp cl,0x0a                     ;换行符?
  196.          jnz .put_other                  ;不是,那就正常显示字符
  197.          add bx,80
  198.          jmp .roll_screen

  199. .put_other:                             ;正常显示字符
  200.          mov ax,0xb800
  201.          mov es,ax
  202.          shl bx,1
  203.          mov [es:bx],cl

  204.          ;以下将光标位置推进一个字符
  205.          shr bx,1
  206.          add bx,1

  207. .roll_screen:
  208.          cmp bx,2000                     ;光标超出屏幕?滚屏
  209.          jl .set_cursor

  210.          mov ax,0xb800
  211.          mov ds,ax
  212.          mov es,ax
  213.          cld
  214.          mov si,0xa0
  215.          mov di,0x00
  216.          mov cx,1920
  217.          rep movsw
  218.          mov bx,3840                     ;清除屏幕最底一行
  219.          mov cx,80
  220. .cls:
  221.          mov word[es:bx],0x0720
  222.          add bx,2
  223.          loop .cls

  224.          mov bx,1920

  225. .set_cursor:
  226.          mov dx,0x3d4
  227.          mov al,0x0e
  228.          out dx,al
  229.          mov dx,0x3d5
  230.          mov al,bh
  231.          out dx,al
  232.          mov dx,0x3d4
  233.          mov al,0x0f
  234.          out dx,al
  235.          mov dx,0x3d5
  236.          mov al,bl
  237.          out dx,al

  238.          pop es
  239.          pop ds
  240.          pop dx
  241.          pop cx
  242.          pop bx
  243.          pop ax

  244.          ret

  245. ;===============================================================================
  246. SECTION data align=16 vstart=0

  247.     init_msg       db 'Starting...',0x0d,0x0a,0
  248.                   
  249.     inst_msg       db 'Installing a new interrupt 70H...',0
  250.    
  251.     done_msg       db 'Done.',0x0d,0x0a,0

  252.     tips_msg       db 'Clock is now working.',0
  253.                   
  254. ;===============================================================================
  255. SECTION stack align=16 vstart=0
  256.            
  257.                  resb 256
  258. ss_pointer:

  259. ;===============================================================================
  260. SECTION program_trail
  261. program_end:
复制代码


  1.          ;代码清单9-2
  2.          ;文件名:c09_2.asm
  3.          ;文件说明:用于演示BIOS中断的用户程序
  4.          ;创建日期:2012-3-28 20:35
  5.          
  6. ;===============================================================================
  7. SECTION header vstart=0                     ;定义用户程序头部段
  8.     program_length  dd program_end          ;程序总长度[0x00]
  9.    
  10.     ;用户程序入口点
  11.     code_entry      dw start                ;偏移地址[0x04]
  12.                     dd section.code.start   ;段地址[0x06]
  13.    
  14.     realloc_tbl_len dw (header_end-realloc_begin)/4
  15.                                             ;段重定位表项个数[0x0a]
  16.    
  17.     realloc_begin:
  18.     ;段重定位表           
  19.     code_segment    dd section.code.start   ;[0x0c]
  20.     data_segment    dd section.data.start   ;[0x14]
  21.     stack_segment   dd section.stack.start  ;[0x1c]
  22.    
  23. header_end:               
  24.    
  25. ;===============================================================================
  26. SECTION code align=16 vstart=0           ;定义代码段(16字节对齐)
  27. start:
  28.       mov ax,[stack_segment]
  29.       mov ss,ax
  30.       mov sp,ss_pointer
  31.       mov ax,[data_segment]
  32.       mov ds,ax
  33.       
  34.       mov cx,msg_end-message
  35.       mov bx,message
  36.       
  37. .putc:
  38.       mov ah,0x0e
  39.       mov al,[bx]
  40.       int 0x10
  41.       inc bx
  42.       loop .putc

  43. .reps:
  44.       mov ah,0x00
  45.       int 0x16
  46.       
  47.       mov ah,0x0e
  48.       mov bl,0x07
  49.       int 0x10

  50.       jmp .reps

  51. ;===============================================================================
  52. SECTION data align=16 vstart=0

  53.     message       db 'Hello, friend!',0x0d,0x0a
  54.                   db 'This simple procedure used to demonstrate '
  55.                   db 'the BIOS interrupt.',0x0d,0x0a
  56.                   db 'Please press the keys on the keyboard ->'
  57.     msg_end:
  58.                   
  59. ;===============================================================================
  60. SECTION stack align=16 vstart=0
  61.            
  62.                  resb 256
  63. ss_pointer:

  64. ;===============================================================================
  65. SECTION program_trail
  66. program_end:
复制代码


  1.      1                                           ;代码清单9-2
  2.      2                                           ;文件名:c09_2.asm
  3.      3                                           ;文件说明:用于演示BIOS中断的用户程序
  4.      4                                           ;创建日期:2012-3-28 20:35
  5.      5                                          
  6.      6                                  ;===============================================================================
  7.      7                                  SECTION header vstart=0                     ;定义用户程序头部段
  8.      8 00000000 [00000000]                  program_length  dd program_end          ;程序总长度[0x00]
  9.      9                                      
  10.     10                                      ;用户程序入口点
  11.     11 00000004 [0000]                      code_entry      dw start                ;偏移地址[0x04]
  12.     12 00000006 [00000000]                                  dd section.code.start   ;段地址[0x06]
  13.     13                                      
  14.     14 0000000A 0300                        realloc_tbl_len dw (header_end-realloc_begin)/4
  15.     15                                                                              ;段重定位表项个数[0x0a]
  16.     16                                      
  17.     17                                      realloc_begin:
  18.     18                                      ;段重定位表           
  19.     19 0000000C [00000000]                  code_segment    dd section.code.start   ;[0x0c]
  20.     20 00000010 [00000000]                  data_segment    dd section.data.start   ;[0x14]
  21.     21 00000014 [00000000]                  stack_segment   dd section.stack.start  ;[0x1c]
  22.     22                                      
  23.     23                                  header_end:               
  24.     24                                      
  25.     25                                  ;===============================================================================
  26.     26                                  SECTION code align=16 vstart=0           ;定义代码段(16字节对齐)
  27.     27                                  start:
  28.     28 00000000 A1[1400]                      mov ax,[stack_segment]
  29.     29 00000003 8ED0                          mov ss,ax
  30.     30 00000005 BC[0001]                      mov sp,ss_pointer
  31.     31 00000008 A1[1000]                      mov ax,[data_segment]
  32.     32 0000000B 8ED8                          mov ds,ax
  33.     33                                       
  34.     34 0000000D B97700                        mov cx,msg_end-message
  35.     35 00000010 BB[0000]                      mov bx,message
  36.     36                                       
  37.     37                                   .putc:
  38.     38 00000013 B40E                          mov ah,0x0e
  39.     39 00000015 8A07                          mov al,[bx]
  40.     40 00000017 CD10                          int 0x10
  41.     41 00000019 43                            inc bx
  42.     42 0000001A E2F7                          loop .putc
  43.     43                                 
  44.     44                                   .reps:
  45.     45 0000001C B400                          mov ah,0x00
  46.     46 0000001E CD16                          int 0x16
  47.     47                                       
  48.     48 00000020 B40E                          mov ah,0x0e
  49.     49 00000022 B307                          mov bl,0x07
  50.     50 00000024 CD10                          int 0x10
  51.     51                                 
  52.     52 00000026 E9F3FF                        jmp .reps
  53.     53                                 
  54.     54                                  ;===============================================================================
  55.     55                                  SECTION data align=16 vstart=0
  56.     56                                 
  57.     57 00000000 48656C6C6F2C206672-         message       db 'Hello, friend!',0x0d,0x0a
  58.     58 00000009 69656E64210D0A     
  59.     59 00000010 546869732073696D70-                       db 'This simple procedure used to demonstrate '
  60.     60 00000019 6C652070726F636564-
  61.     61 00000022 757265207573656420-
  62.     62 0000002B 746F2064656D6F6E73-
  63.     63 00000034 747261746520      
  64.     64 0000003A 7468652042494F5320-                       db 'the BIOS interrupt.',0x0d,0x0a
  65.     65 00000043 696E74657272757074-
  66.     66 0000004C 2E0D0A            
  67.     67 0000004F 506C65617365207072-                       db 'Please press the keys on the keyboard ->'
  68.     68 00000058 65737320746865206B-
  69.     69 00000061 657973206F6E207468-
  70.     70 0000006A 65206B6579626F6172-
  71.     71 00000073 64202D3E           
  72.     72                                      msg_end:
  73.     73                                                     
  74.     74                                  ;===============================================================================
  75.     75                                  SECTION stack align=16 vstart=0
  76.     76                                             
  77.     77 00000000 <res 00000100>                           resb 256
  78.     78          ******************       warning: uninitialized space declared in stack section: zeroing
  79.     79                                  ss_pointer:
  80.     80                                   
  81.     81                                  ;===============================================================================
  82.     82                                  SECTION program_trail
  83.     83                                  program_end:

复制代码


  1.          ;代码清单9-2
  2.          ;文件名:c09_2.asm
  3.          ;文件说明:用于演示BIOS中断的用户程序
  4.          ;创建日期:2012-3-28 20:35
  5.          
  6. ;===============================================================================
  7. SECTION header vstart=0                     ;定义用户程序头部段
  8.     program_length  dd program_end          ;程序总长度[0x00]
  9.    
  10.     ;用户程序入口点
  11.     code_entry      dw start                ;偏移地址[0x04]
  12.                     dd section.code.start   ;段地址[0x06]
  13.    
  14.     realloc_tbl_len dw (header_end-realloc_begin)/4
  15.                                             ;段重定位表项个数[0x0a]
  16.    
  17.     realloc_begin:
  18.     ;段重定位表           
  19.     code_segment    dd section.code.start   ;[0x0c]
  20.     data_segment    dd section.data.start   ;[0x14]
  21.     stack_segment   dd section.stack.start  ;[0x1c]
  22.    
  23. header_end:               
  24.    
  25. ;===============================================================================
  26. SECTION code align=16 vstart=0           ;定义代码段(16字节对齐)
  27. start:
  28.       mov ax,[stack_segment]
  29.       mov ss,ax
  30.       mov sp,ss_pointer
  31.       mov ax,[data_segment]
  32.       mov ds,ax
  33.       
  34.       mov cx,msg_end-message
  35.       mov bx,message
  36.       
  37. .putc:
  38.       mov ah,0x0e
  39.       mov al,[bx]
  40.       int 0x10
  41.       inc bx
  42.       loop .putc

  43. .reps:
  44.       mov ah,0x00
  45.       int 0x16
  46.       
  47.       mov ah,0x0e
  48.       mov bl,0x07
  49.       int 0x10

  50.       jmp .reps

  51. ;===============================================================================
  52. SECTION data align=16 vstart=0

  53.     message       db 'Hello, friend!',0x0d,0x0a
  54.                   db 'This simple procedure used to demonstrate '
  55.                   db 'the BIOS interrupt.',0x0d,0x0a
  56.                   db 'Please press the keys on the keyboard ->'
  57.     msg_end:
  58.                   
  59. ;===============================================================================
  60. SECTION stack align=16 vstart=0
  61.            
  62.                  resb 256
  63. ss_pointer:

  64. ;===============================================================================
  65. SECTION program_trail
  66. program_end:
复制代码
回复

使用道具 举报

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

本版积分规则

Archiver|手机版|小黑屋|4ameta

GMT+8, 2022-10-2 23:16 , Processed in 0.036022 second(s), 17 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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