zoukankan      html  css  js  c++  java
  • 汇编学习--第十八天

    16.4 程序入口地址的直接定址表

    实验 16编写包含多个功能子程序的中断例程。

    在这道题中,因为table...最终会被范围为cs:N[si]这种形式存储,当我们转移程序到0:200h处时,CS和IP改变,但是程序中table处没有改变,所以会引发定址错误。

    测试程序

    assume cs:code
    code segment
    start:
        mov ah,2
        mov al,2
        int 7ch
        
        mov ax,4c00h
        int 21h
    code ends
    end start

    中断例程

    assume cs:code
    code segment
    start:
        ;储存程序到0:200h
        mov ax,0
        mov es,ax
        mov ax,cs
        mov ds,ax
        mov cx,offset setscreenend-offset setscreen
        mov di,200h
        mov si,offset setscreen
        cld
        rep movsb
        
        ;程序入口写入向量表
        mov word ptr es:[7ch*4],200h
        mov word ptr es:[7ch*4+2],0
        
        mov ax,4c00h
        int 21h
        
        org 200h
    setscreen:
        jmp short set
        table dw sub1,sub2,sub3,sub4
    set:
        push bx
        ;判断选择的功能是否越界
        cmp ah,4
        ja sret
        mov bl,ah
        mov bh,0
        add bx,bx
        
        call word ptr table[bx]
        
    sret:
        pop bx
        iret
    
    sub1:
        push es
        push bx
        push cx
        
        mov bx,0b800h
        mov es,bx
        mov bx,0
        mov cx,2000
    sub1s:
        mov byte ptr es:[bx],' '
        add bx,2
        loop sub1s
        
        pop cx
        pop bx
        pop es
        iret
        
    sub2:
        push bx
        push es
        push cx
        
        mov bx,0b800h
        mov es,bx
        mov bx,1
        mov cx,2000    
    sub2s:
        ;设置指定颜色
        and byte ptr es:[bx],11111000b
        or es:[bx],al
        add bx,2
        loop sub2s
        
        pop cx
        pop es
        pop bx
        iret
        
    sub3:
        push bx
        push cx
        push es
        
        ;因为al的范围在0~7,所以设置背景色时,需要右移4位
        mov cl,4
        shr al,cl
        mov bx,0b800h
        mov es,bx
        mov cx,2000
        mov bx,1
    sub3s:
        and byte ptr es:[bx],10001111b
        or es:[bx],al
        add bx,2
        loop sub3s
        
        pop es
        pop cx
        pop bx
        iret
        
    sub4:
        push bx
        push es
        push di
        push si
        push cx
        
        mov bx,0b800h
        mov es,bx
        mov ds,bx
        mov si,160
        mov di,0
        mov cx,24
    sub4s:
        push cx
        mov cx,160
        cld
        rep movsb
        pop cx
        loop sub4s
        
        pop cx
        pop si
        pop di
        pop es
        pop bx
        iret
        
    setscreenend:nop
    code ends
    end start

    转自百度:http://t.cn/AijCULrC

    伪指令org用来规定目标程序存放单元的偏移量。比如,如果在源程序的第一条指令前用了如下指令:

    org 200h

    那么,汇编程序会把指令指针的ip的值设成200h,即目标程序的第一个字节放在200h处,后面的 内容则顺序存放,除非遇上另一个org 语句

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

    17.1 int 9中断例程对键盘输入的处理

    键盘缓冲区有16个字节单元,可以存储15个按键的扫描码和对应的ASCII码

    17.2 使用int 16h中断例程读取键盘缓冲区

    int 16的一个功能:从键盘缓冲区读取一个键盘输入,并将其从键盘缓冲区删除

    mov ah,0

    int 16h

    (ah)=扫描码   (al)=ASCII嘛

    编程,接受用户的键盘输入,输入'r',屏幕字变红,输入'g',屏幕字变绿,输入'b',屏幕字变蓝。

    assume cs:code
    code segment
    start:
        mov ah,0
        int 16h
        
        mov ah,1
        cmp al,'r'
        je red
        cmp al,'g'
        je green
        cmp al,'b'
        je blue
        jmp short sret
        
    red:
        shl ah,1
    
    green:
        shl ah,1
    
    blue:
        mov bx,0b800h
        mov es,bx
        mov bx,1
        mov cx,2000
    s:
        and byte ptr es:[bx],11111000b
        or es:[bx],ah
        add bx,2
        loop s
    
    sret:
        mov ax,4c00h
        int 21h
    code ends
    end start

    检测点 17.1

    错误,如果int 16是不可屏蔽中断,那IF=0,如果int 16是可屏蔽中断,且要一直检查键盘缓冲区是否存在数据,所以IF=1一直存在。

    17.3 字符串的输入

    assume cs:code,ds:data
    data segment
        dw 128 dup (0)
    data ends
    code segment
    start:
        mov ax,data
        mov ds,ax
        mov si,0
        call getstr
        
        mov ax,4c00h
        int 21h
        
    getstr:
        push ax
        
    getstrs:
        mov ah, 0
        int 16h
        cmp al, 20h
        jb nochar                        ; ASCII码小于20h, 说明不是字符
    
        ; 字符的处理分为两步,1:入栈,   2:显示栈中的字符
        mov ah, 0                        ; 1: 字符入栈
        call charstack
        mov ah, 2                        ; 2: 显示栈中的字符
        call charstack
        jmp getstrs
                        
    nochar:    
        cmp ah, 0eh                    ; 退格键的扫描码
        je backspace
        cmp ah, 1ch                    ; Enter键的扫描码
        je enters
        jmp getstrs                    ; 其他控制键忽略
        
    backspace:
        mov ah, 1
        call charstack                    ; 字符出栈
        mov ah, 2
        call charstack                    ; 字符显示
        jmp getstrs
        
    enters:
        mov al, 0
        mov ah, 0
        call charstack                    ; 0入栈
        mov ah, 2
        call charstack                    ; 显示栈中的字符串
                
        pop ax
        ret
    
    ; 子程序: 字符栈的入栈、出栈和显示
    ; 参数说明:(ah)=功能号,0表示入栈,1表示出栈,2表示显示
    ; ds:si指向字符栈的空间
    ; 对于0号功能:(al)=入栈字符;
    ; 对于1号功能: (al)=返回的字符;
    ; 对于2号功能:(dh)、(dl)=字符串在屏幕上显示的行、列位置。
        
    charstack:    jmp short charstart
        table     dw charpush, charpop, charshow
        top       dw 0;栈空间
            
    charstart:
        push bx
        push dx
        push di
        push es
        
        ;判断选择是否越界
        cmp ah, 2
        ja sret
        ;选择序号对应到table中的地址
        mov bl, ah
        mov bh, 0
        add bx, bx
        jmp word ptr table[bx]
    
    charpush:
        ;将入栈字符放入栈中,top是栈顶指针
        ;下面的[si][bx],应该是ds:[si][bx],
        ;在我们主程序应该定义了一个data段,用于模拟栈空间,存储读取数据。
        ;top地址存储的数据是栈顶的位置
        mov bx, top
        mov [si][bx], al
        inc top
        jmp sret
    
    charpop:
        ;栈顶位置为0,说明键盘缓冲区没有数据
        cmp top, 0
        je sret
        ;不为0,top减1,模拟出栈
        dec top
        ;将我们主程序定义的data段中的栈顶数据取出,赋值给al
        mov bx, top
        mov al, [si][bx]
        jmp sret
                    
    charshow:;(dh)、(dl)=字符串在屏幕上显示的行、列位置。    
        mov bx, 0b800h
        mov es, bx
        mov al, 160
        mov ah, 0
        mul dh
        mov di, ax
        add dl, dl
        mov dh, 0
        add di, dx
    
        mov bx, 0
        
    charshows:
        ;使用bx在栈空间移动取值
        ;判断栈顶位置是否和bx相等,相等表示键盘缓冲区为空
        cmp bx, top
        jne noempty
        ;为空,在字符串后面加‘ ’
        mov byte ptr es:[di], ' '
        jmp sret
    
    noempty:
        ;取出数据显示,以‘ ’间隔
        mov al, [si][bx]
        mov es:[di], al
        mov byte ptr es:[di+2], ' '
        inc bx
        add di, 2
        jmp charshows
    
    sret:        
        pop es
        pop di
        pop dx
        pop bx
        ret
        
    code ends
    end start

  • 相关阅读:
    hibernate 高并发下遇到的大坑
    Spring Cloud微服务架构企业中的应用
    spring cloud学习-hystrix
    点评CAT接入手册
    centOS6.5 修改catalina.sh使用crontab自动切割日志tomcat8
    mariaDB安装报错
    linux安装rap需要的软件
    mariaDB的innodb恢复报错解决
    NFinal学习笔记 02—NFinalBuild
    NFinal 视图—用户控件
  • 原文地址:https://www.cnblogs.com/Mayfly-nymph/p/11257397.html
Copyright © 2011-2022 走看看