学到这里,已经感觉有点跟不上王爽老师的步伐了,因为有些程序需要在dos的实模式下才可以运行出来
自己又懒得去整,最多是在虚拟机下的xp,有些东西还是无法运行出来
这道题是书上的例题,我进行了整理
功能是最基本的字符串输入程序,需要具备下面的功能
1、在输入的同时需要显示这个字符串
2、一般在输入回车符后,字符串输入结束
3、可以删除已经输入的字符串
程序如下:
;字符栈的入栈,出栈和显示
;ah=功能号,0代表入栈,1表示出栈,2表示显示
;ds:si指向字符栈空间
;0==》al入栈字符
;1==》al返回的字符
;2==》dh,dl==字符串在屏幕上显示的行列位置
assume cs:code
code segment
start:
mov dh,0
mov dl,0
call getstr
mov ax,4c00h
int 21h
getstr:
push ax
getstrs:
mov ah,0
int 16h ;16号的0号中断可以读取键盘输入
;int 9 键盘写入
cmp al,20h ;ah中扫描码,al中ASCII码
jb nochar ;ASCII码小于20h,说明不是字符
mov ah,0
call charstack ;字符入栈
mov ah,2
call charstack ;显示字符
jmp getstrs
nochar:
cmp ah,0eh ;退格键
je backspace
cmp ah,1ch
je enters ;enter键的扫描码
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 ;显示栈中的字符
;jmp short ok
pop ax
ret
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
mov bl,ah
mov bh,0
add bx,bx
jmp word ptr table[bx]
charpush:
mov bx,top
mov [si+bx],al
inc top
jmp sret
charpop:
cmp top,0
je sret ;栈空结束
dec top
mov bx,top
mov al,[si][bx]
jmp sret
charshow:
mov bx,0b800h
mov es,bx
mov al,160
mov ah,0
mul dh ;行数*160+列数*2
mov di,ax
add dl,dl
mov dh,0
add di,dx
mov bx,0
charshows:
cmp bx,top ;与栈底比较
jne noempty
mov byte ptr es:[di],' ' ;top虽然是0但是由于top指向的是第0个
;所以top还没有清空
jmp sret
noempty:
mov al,[bx+si]
mov es:[di],al
mov byte ptr es:[di+1],2
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
108行的作用:
因为判断栈空的条件是top=0,所以当栈空的时候top还指向第一个元素,第一个元素没有被删除
所以要再将top指向的清零
116行的作用:
我试着将+2,换成+4、+6、+8,发现程序是将显示的代码往后偏移的第几个置为空格
比如如果是+6,屏幕上现在显示的是‘abcde’,你现在输入2,屏幕上就是‘2bc e’,将第四个置为空格
这只是我认为的,但是实际上却是‘2 c e’,原因还没搞懂
按理上说,将这条代码如果注释,那输入的字符相邻的字符就不会置为空格,
但是结果和不注释是一样的
我想是不是在dos实模式下运行就会好,这个问题还有待于验证