汇编语言字符串的输入

最基本的字符串输入程序,需要具备下面的功能。
(1)在输入的同时需要显示这个字符串;
(2)一般在输入回车符后,字符串输入结束:
(3)能够删除已经输入的字符。
对于这3个功能,我们可以想象在DOS中,输入命令行时的情况。
编写一个接收字符串输入的子程序,实现上面3个基本功能。因为在输入的过程中需要显示,子程序的参数如下:
(dh)、(d1)=字符串在屏幕上显示的行、列位置:
ds: si指向字符串的存储空间,字符串以0为结尾符。
下面我们进行分析。
(1)字符的输入和删除。
每个新输入的字符都存储在前一个输入的字符之后,而删除是从最后面的字符进行的,我们看下面的过程。
空字符串:
输入“a:a
输入“b":ab
输入“c:abc
输入“d":abcd
册寸除一个字符:abc
删除一个字符:ab
删除一个字符:a
删除一个字符:
可以看出在字符串输入的过程中,字符的输入和输出是按照栈的访问规则进行的,即后进先出。这样,我们就可以用栈的方式来管理字符串的存储空间,也就是说,字符串的存储空间实际上是一个字符栈。字符栈中的所有字符,从栈底到栈顶,组成一个字符串。
(2)在输入回车符后,字符串输入结束。
输入回车符后,可以在字符串中加入0,表示字符串结束。
(3)在输入的同时需要显示这个字符串。
每次有新的字符输入和删除一个字符的时候,都应该重新显示字符串,即从字符栈的栈底到栈顶,显示所有的字符。
(4)程序的处理过程。
现在我们可以简单地确定程序的处理过程如下。
①调用int 16h读取键盘输入;
②如果是字符,进入字符栈,显示字符栈中的所有字符;继续执行①;
③如果是退格键,从字符栈中弹出一个字符,显示字符栈中的所有字符:继续执
行①;
④如果是Ente:键,向字符栈中压入0,返回。
从程序的处理过程中可以看出,字符栈的入栈、出栈和显示栈中的内容,是需要在多处使用的功能,我们应该将它们写为子程序。
子程序:字符栈的入栈、出栈和显示。
参数说明:(ah)=功能号,0表示入栈,1表示出栈,2表示显示;
dsai指向字符栈空间;
对于0号功能:(al)=入栈字符;
对于I号功能:(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
		  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
		  mov di, ax	;行
		  add dl, dl	;列
		  mov dh, 0
		  add di, dx	;屏幕字节索引
		  
		  mov bx, 0	;初始化为0用于和字符串结束标志做对比
		  
charshows: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

511遇见

另外一个要注意的问题是,显示栈中字符的时候,要注意清除屏幕上上一次显示的内容
我们现在写出完整的接收字符串输入的子程序,如下所示。

	;循环读取键盘缓冲区的字符
   getstr:push ax
   
  getstrs:mov ah, 0
		  int 16h
		  cmp al, 20h
		  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;	       ;Enter键的扫描码
		  je enter
		  jmp getstrs	
		  
backspace:mov ah, 1
		  call charstack	;字符出栈
		  mov ah, 2
		  call charstack	;显示栈中的字符
		  jmp getstrs
		  
	enter:mov al, 0
		  mov ah, 0
		  call charstack	;0入栈
		  mov ah, 2
		  call charstack	;显示栈中的字符
		  pop ax
		  ret		  
code ends
end start 

完整代码

assume cs:code, ds:data

data segment
	db 10 dup (0)
data ends

code segment
	start:mov ax, data
		  mov ds, ax
		  mov si, 0	;将ds:di设为存放字符的栈
		  mov ah, 2
		  mov dh, 0
		  mov dl, 0
		  
		  call getstr
		  mov ax, 4c00h
		  int 21h
	
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
		  mov di, ax	;行
		  add dl, dl	;列
		  mov dh, 0
		  add di, dx	;屏幕字节索引
		  
		  mov bx, 0	;初始化为0用于和字符串结束标志做对比
		  
charshows: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
	
	;循环读取键盘缓冲区的字符
   getstr:push ax
   
  getstrs:mov ah, 0
		  int 16h
		  cmp al, 20h
		  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;	       ;Enter键的扫描码
		  je enter
		  jmp getstrs	
		  
backspace:mov ah, 1
		  call charstack	;字符出栈
		  mov ah, 2
		  call charstack	;显示栈中的字符
		  jmp getstrs
		  
	enter:mov al, 0
		  mov ah, 0
		  call charstack	;0入栈
		  mov ah, 2
		  call charstack	;显示栈中的字符
		  pop ax
		  ret
		  
code ends
end start 

发布日期:

所属分类: 易语言 标签: