首页 > 其他 > 详细

汇编学习--第十八天

时间:2019-07-28 09:06:24      阅读:99      评论:0      收藏:0      [点我收藏+]

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

技术分享图片

 

汇编学习--第十八天

原文:https://www.cnblogs.com/Mayfly-nymph/p/11257397.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!