汇编学习--第十八天
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