zoukankan      html  css  js  c++  java
  • 《汇编语言》(王爽)补充笔记,第 14 ~ 17 章

    第十四章 CALL 和 RET 指令

    ● 与总线相连的各设备芯片中均有一组可供 CPU 访问的寄存器,总线除了连接存储器芯片外还有:① 各种接口卡(网卡、显卡、声卡)的芯片;② 主板接口芯片,用于访问部分外设;③ 其他芯片,用于存储相关系统信息及处理输入输出

    ● CPU 定位设备地址范围为 0 ~ 65535,共 64 KB。端口读写指令只有两条,in 和 out,分别用于读取和写入,用 ax 或 al 来存放转移数据。

    ● 地址 0 ~ 255 设备读写时可以使用立即数作地址,地址 256 ~ 65536 设备读写时端口号放在 dx 中

    1     in  al, 20h     ; 20h 端口读取 1 Byte 数据,放入 al
    2     out 20h, al     ; 20h 端口写入 1 Byte 数据,来自 al,注意操作数顺序
    3 
    4     mov dx, 0100h   ; 大地址读写
    5     in  al, dx
    6     out dx, al

    ● CMOS RAM 芯片,特性:

      ① 包含一个实时钟

      ② 靠纽扣电池供电

      ③ 包含128 Byte 的 RAM 存储器,00h ~ 0dh 单元存储时间信息,其他部分存储系统配置信息供启动时 BIOS 读取,BIOS 中有相关例程可以编辑 CMOS 信息。

      ④ 端口地址 70h 和 71h,前者存放目标 RAM 地址,后者存放读写数据。CPU 读写分两步,先向 70h 写入地址,再对 71h 进行读写操作。

    ● shl 和 shr 命令,当位移数大于 1 时 要将位移数放入 cl 中

    ● BCD 码:用四位二进制数表示两位十进制数码的方法,每两位十进制数(如36)分别写成二进制后拼成 1 Byte(00110110)

    ● CMOS 中,年月日时分秒 6 个信息长度均为 1 Byte,存放地址:秒(0)分(2)时(4)日(7)月(8)年(9),

    ● 代码,从 CMOS 中读取时间,在屏幕上动态输出(之前一直不能用的输出方式,现在能用了)

     1 assume cs:code
     2 code segment
     3     s1: db 9, 8, 7, 4, 2, 0             ; 各数据的位置
     4     s2: dw 0, 0, 0, 0, 0, 0            
     5     s3: db '/', '/', ' ', ':', ':', ' ' ; 用于输出的字符串
     6 
     7 start:
     8     mov ax, cs
     9     mov ds, ax
    10     mov bx, offset s1
    11     mov si, offset s2
    12 
    13     mov cx, 6           ; 一个时间要读 6 次得到
    14 reads: 
    15     push cx
    16     mov al, [bx]        ; 取所需数据的地址
    17     out 70h, al         ; 读取数据
    18     in al, 71h
    19     mov ah, al          ; ah 存十位数,al 存个位数
    20     mov cl, 4
    21     shr ah, cl
    22     and al, 00001111b
    23 
    24     add ah, 30h         ; 十六进制数转 ASCII 码
    25     add al, 30h
    26     mov [si], ah        ; 保存读取的数据
    27     mov [si+1], al
    28     inc bx              ; 指向下一个数据
    29     add si, 2
    30     pop cx
    31     loop reads
    32 
    33     mov ax, 0b800h      ; 数据移动到特定内存用于显示,es : bx 表示终端第 12 行 10 列
    34     mov es, ax
    35     mov bx, 160 * 12 + 10 * 2
    36     mov si, offset s2
    37     mov di, offset s3
    38 
    39     mov ah, 2           ; 指定颜色
    40     mov cx, 6
    41 show:   
    42     mov al, [si]        ; 每读两位 s2(用 si ),读一位 S3(用 di)
    43     mov es:[bx], al 
    44     mov es:[bx+1], ah
    45     add bx, 2
    46     mov al, [si+1]
    47     mov es:[bx], al 
    48     mov es:[bx+1], ah
    49     add bx, 2
    50     mov al, [di]
    51     mov es:[bx], al 
    52     mov es:[bx+1], ah
    53 
    54     add bx, 2           ; 移动指针 
    55     add si, 2
    56     inc di
    57     loop show
    58 
    59     in al, 60h          ; 键盘输入
    60     cmp al, 10h         ; 检查输入是否为 'q'
    61     jne start           ; 循环
    62 
    63     mov ax, 4c00h
    64     int 21h
    65 code ends
    66 
    67 end start

    第十五章 外中断

    ● CPU 在执行完一条指令后可以检测外中断信息,引发中断过程,处理外设输入

    ● 标志寄存器 IF =1 时 CPU 响应外中断,IF = 0 时 CPU 屏蔽外中断不响应

    ● 指令 sti 置标志寄存器 IF 为 1;cti 置标志寄存器 IF 为 0

    ● 8086 CPU 中,几乎所有外设引发的终端都是可屏蔽中断,不可屏蔽中断的终端类型码固定为 2

    ● 键盘中断特性:

      ① 按下或放开一个键,键盘产生相应的扫描码;

      ② 按下产生通码,松开产生断码,同一按键,断码 = 通码 + 20h;

      ③ 按下或放开一个键,键盘芯片向 60h 端口寄存器写入扫描码;

      ④ 相关芯片向 CPU 引发 9 号中断码;

      ⑤ BIOS 键盘缓冲区可以存储 15 个键盘输入等待 CPU 响应,每个键盘输入为 1 个字,高字节存放扫描码,低字节存放字符码;

      ⑥ 0400 : 0017 存放键盘状态字节,该字节的各位记录辅助按键的状态:Insert(7),CapsLock(6),NumLock(5),ScrollLock(4),Alt(3),Ctrl(2),左 Shift(1),右 Shift(0)

    ● 代码,在屏幕上逐个显示 a ~ z,期间按下 Esc 改变字体颜色

     1 assume cs:code
     2 
     3 stack segment
     4     db 128 dup (0)
     5 stack ends
     6 
     7 data segment
     8     dw 0, 0
     9 data ends
    10 
    11 code segment
    12 start:
    13     mov ax, stack
    14     mov ss, ax
    15     mov sp, 128
    16     mov ax, data
    17     mov ds, ax
    18     mov ax, 0
    19     mov es, ax
    20 
    21     push es:[9*4]                       ; 原 int 9 中断例程的入口地址保存到 0000 : 0200
    22     pop ds:[0]                          ; 使用栈中转,把 es : [] 指向的内存放入 ds : []
    23     push es:[9*4+2]
    24     pop ds:[2]                          
    25 
    26     cli                                 ; 不需要等待键盘输入时,及时置屏蔽中断标志位 IF = 0
    27 
    28     mov word ptr es:[9*4], offset int9  ; 设置新的 int 9 程序的入口地址
    29     mov es:[9*4+2], cs
    30 
    31     sti                                 ; 需要键盘输入时,置屏蔽中断标志位 IF = 1
    32 
    33     mov ax, 0b800h                      ; 最初显示
    34     mov es, ax
    35     mov ah, 'a'
    36 s:
    37     mov  es:[160*12+40*2], ah           ; 循环显示
    38     call delay
    39     inc ah
    40     cmp ah, 'z'
    41     jna s
    42     mov ax, 0
    43     mov es, ax
    44 
    45     cli                 
    46 
    47     push ds:[0]         ; 将中断向量表中 int 9 中断例程的入口恢复为原来的地址
    48     pop es:[9*4]
    49     push ds             ; [2]
    50     pop es              ; [9*4+2]
    51 
    52     sti                 
    53 
    54     mov ax, 4c00h
    55     int 21h
    56 
    57 delay:    
    58     push ax             ; 延时
    59     push dx
    60     mov dx, 1h         ; 使用 dx : ax = 1000000000 向下递减,减到零时退出
    61     mov ax, 0
    62 s1:
    63     sub ax, 1
    64     sbb dx, 0
    65     cmp ax, 0
    66     jne s1
    67     cmp dx, 0
    68     jne s1
    69     pop dx
    70     pop ax
    71     ret
    72 
    73 int9:    
    74     push ax
    75     push bx
    76     push es
    77 
    78     in al, 60h                      ; 读取键盘
    79 
    80     pushf
    81 
    82     call dword ptr ds:[0]           ; 调用原 int 9 中断例程
    83 
    84     cmp al, 1
    85     jne int9ret
    86 
    87     mov ax, 0b800h
    88     mov es, ax
    89     inc byte ptr es:[160*12+40*2+1] ; 属性值增加 1,从前景色开始改变颜色
    90 
    91 int9ret:
    92     pop es
    93     pop bx
    94     pop ax
    95     iret
    96 
    97 code ends
    98 
    99 end start

    第十六章 直接址表(即表驱动查找)

    ● 地址标号与数据标号

     1 code segment
     2     a: db 1, 2, 3, 4, 5, 6, 7, 8    ; 地址标号,仅表地址,只能在代码段中使用    
     3 
     4     mov si, OFFSET a                ; 要用 OFFSET 来计算
     5     mov al, cs:[si]
     6 
     7     ...
     8 ;----------------------------------------------------------------
     9 code segment
    10     a db 1, 2, 3, 4, 5, 6, 7, 8     ; 数据标号,表地址和内存单元长    
    11     
    12     mov si, 0                       ; 直接使用数组名和偏移地址来取            
    13     mov al, a[si]
    14 
    15     ...
    16 ;----------------------------------------------------------------
    17 code segment
    18     a db 1, 2, 3, 4, 5, 6, 7, 8
    19     b dw 0, 0, 0, 0
    20     c dw a, b                       ; c 中存储 a 和 b 的偏移地址
    21                                     ; 等价于 c dw OFFSET a, OFFSET b
    22     d dd a, b                       ; d 中存储 a 和 b 的短地址和偏移地址            
    23                                     ; 等价于 d dd OFFSET a, SEG a, OFFSET b, SEG b 

    第十七章 使用 BIOS 进行键盘输入和磁盘读写

    ● BIOS int 16h 中断例程 0 号子程序,从键盘缓冲区读取一个输入,并将其从缓冲区中删除,若缓冲区为空,则循环等待直到有数据。调用时 mov ah,0  int 16h ,返回 ah 为扫描码,al 为 ASCII 码

    ● 代码,简单的字符串输入程序,能够输入、删除

      1 assume cs:code
      2 
      3 code segment
      4 start:    
      5     call getstr    
      6 
      7 return:    
      8     mov ax, 4c00h
      9     int 21h
     10 
     11 getstr:                 ; 接收字符串    
     12     push ax 
     13 
     14 getstrs:
     15     mov ah, 0
     16     int 16h
     17     
     18     cmp al, 20h
     19     jb nochar           ; ASCII < 0,不是字符
     20     mov ah, 0
     21     call charstack      ; 字符入栈
     22     mov ah, 2
     23     call charstack      ; 显示栈中的字符
     24     jmp getstrs
     25 
     26 nochar:                 ; 输入非字符键
     27     cmp ah, 0eh         ; 退格键
     28     je backspace
     29     cmp ah, 1ch         ; 回车键
     30     je enter
     31     jmp getstrs
     32         
     33 backspace:              ; 输入退格键
     34     mov ah, 1    
     35     call charstack      ; 字符出栈
     36     mov ah, 2
     37     call charstack      ; 打印栈中字符串
     38     jmp getstrs
     39 
     40 enter:                  ; 输入回车键
     41     mov al, 0
     42     mov ah, 0
     43     call charstack      ; 0 入栈
     44     mov ah, 2
     45     call charstack      ;显示栈中的字符
     46 
     47     pop ax
     48     ret
     49 
     50 charstack:                                  ; 实现与栈相关功能的程序
     51     jmp short charstart
     52     table dw charpush, charpop, charshow    ; 驱动表,0 入栈,1 出栈,2 打印栈
     53     top dw 0                                ; 栈顶
     54 charstart:
     55     push bx
     56     push dx
     57     push di
     58     push es
     59 
     60     cmp ah, 2
     61     ja sret                     ; >2 的非法输入,直接结束
     62     mov bl, ah                  ; [0, 1, 2] -> [0, 2, 4]
     63     mov bh, 0
     64     add bx, bx
     65     jmp word ptr table[bx]      ; 每个表项占 4 字节
     66 
     67 charpush:                       ; al 入栈
     68     mov bx, top
     69     mov [si][bx], al
     70     inc top
     71     jmp sret
     72 
     73 charpop:                        ; 出栈到 al
     74     cmp top, 0
     75     je sret
     76     dec top
     77     mov bx, top
     78     mov al, [si][bx]    
     79     jmp sret
     80 
     81 charshow:                       ; 显示栈中的内容
     82     mov bx, 0b800h
     83     mov es, bx
     84     mov al, 160
     85     mov ah, 0    
     86     mul dh
     87     mov di, ax
     88     add dl, dl
     89     mov dh, 0
     90     add di, dx
     91 
     92     mov bx, 0
     93 
     94 charshows:
     95     cmp bx, top
     96     jne noempty
     97     mov byte ptr es:[di], ' '    
     98     jmp sret
     99 
    100 noempty:
    101     mov al, [si][bx]
    102     mov es:[di], al
    103     mov byte ptr es:[di+2], ' '
    104     inc bx
    105     add di, 2
    106     jmp charshows
    107 
    108 sret:    
    109     pop es
    110     pop di
    111     pop dx
    112     pop bx
    113     ret
    114 
    115 code ends
    116 end start

    ● 代码,从硬盘读取数据

     1 assume cs:code
     2 
     3 code segment
     4 start:    
     5     mov ax, 0
     6     mov es, ax
     7     mov bx, 200h    ; es : bx 指向接收数据的内存区
     8 
     9     mov al, 1       ; 要读取的扇区数,3.5 英寸盘一个扇区 512 Byte
    10     mov ch, 0       ; 磁道号,从0开始
    11     mov cl, 1       ; 扇区号,从1开始
    12     mov dl, 1       ; 驱动器号,0:软驱A,1:软驱B,硬盘从 80h 开始,80h:硬盘C,81h:硬盘D
    13     mov dh, 0       ; 磁头号,对于软盘即面号
    14     mov ah, 2       ; int 13h 的 2 号子程序,读取数据
    15     int 13h         ; 读取硬盘,操作成功:ah 为 0,al 为 读取的扇区数;操作失败:ah 为 出错代码
    16                         
    17 return:    
    18     mov ax, 4c00h
    19     int 21h
    20 
    21 code ends
    22 end start

    ● 代码,内存数据写入硬盘

     1 assume cs:code
     2 
     3 code segment
     4 start:    
     5     mov ax, 0
     6     mov es, ax
     7     mov bx, 200h    ; es : bx 指向写入磁盘的数据的内存区
     8 
     9     mov al, 1
    10     mov ch, 0
    11     mov cl, 1
    12     mov dl, 1
    13     mov dh, 0
    14     mov ah, 3       ; int 13h 的 3 号子程序,写入数据
    15     int 13h         ; 写入硬盘
    16     
    17 return:
    18     mov ax, 4c00h
    19     int 21h
    20 
    21 code ends
    22 end start
  • 相关阅读:
    创业日志N,一听到别人说创业我就怕
    《创业维艰分享之五》所有得,有所乐,日事日清,循序渐进。
    创业维艰--分享技术人做产品与做市场的一些经验
    创业维艰--最艰难的时候
    angular js 在ie11 下的get请求缓存问题的解决办法
    《创业维艰-分享创业中遇到的困难之二》----破局
    xwalk_core_library-15.44.384 .13.aar 百度云分享
    linux常用命令
    Merge into 用法
    多线程的并发控制
  • 原文地址:https://www.cnblogs.com/cuancuancuanhao/p/9688290.html
Copyright © 2011-2022 走看看