- [mywiil] 我没用书上的入栈出栈写,就是先看看不用书上的方法能做出来否? ============== 不错 09/19 09:24
- [njutyangxiao] 谢谢你的指导 09/18 17:00
- [younggay] 嗯,应该说理解的没问题。 09/18 15:41
- [njutyangxiao] 检测点16.1的题目是中是这样定义的: a dw 1,2,3,4,5,6,7,8 b dd 09/16 11:23
- [njutyangxiao] 嗯,谢谢指导 09/16 11:22
- [wsrf] assume伪指令指定了段中标号与相应段寄存器的联系。 09/16 09:46
- [wsrf] 没有问题,不过源代码中 a db 1,2,3,4,5,6,7,8 b dw 0 怎么 09/16 09:43
- [njutyangxiao] 谢谢,keep moving! 09/16 09:06
- [njutyangxiao] 谢谢你的指导 09/16 09:05
- [njutyangxiao] 谢谢你的指导 09/16 09:05
[2009-09-18 17:04] 17.3字符串的接收、显示以及删除(1)
题目:编程,编写一个接受字符串输入的程序,应该有如下功能:
(1)在输入的同时需要显示这个字符串
(2)一般在输入回车符后,字符串输入结束
(3)能够删除已经输入的字符
分析:我没用书上的入栈出栈写,就是先看看不用书上的方法能做出来否?实现过程在源代码中有详细的分析。
源代码:
assume cs:codesg
datasg segment
db 1024 dup(0)
datasg ends
codesg segment
start:
mov ax,datasg
mov ds,ax
mov si,0;设置ds:[si]指向存储字符串的地址空间
mov dh,12
mov dl,0;在第12行0列开始显示字符串
get_char:
mov ax,0
int 16h;调用int 16h的0号功能子程序读取键盘的输入
cmp al,20h
jb no_char;如果读取到的ASCII码值小于20h,就不是字符了,跳转到no_char处。
mov ds:[si],al;否则,就把字符的ASCII码是送入ds:[si]中保存起来
inc si
mov byte ptr ds:[si],0 ;每输入一个字符,就马上再起后一地址单元填充0.比如输入a后,其后单元填
;充0,再输入b,就会把刚刚的存储0的单元用来填充b,接着又会在b后的存储单元中填充0.依次类推
;输出字符串
print_char:
call clear_screen;输出字符串之前先要把之前显示的字符串给清空
call show_str;显示字符串
jmp short get_char;又跳转到get_char处,继续读取键盘的输入
;判断是否是enter键或backspace键的按下,是就转去执行相应的程序代码。如果是其他键,就退出程序
no_char:
cmp al,0dh
je get_charover;是enter键的话就退出程序
cmp al,8h
je delete_char;是backspace键就转到删除字符的子程序delete_char处
;其他键和enter键就退出程序
get_charover:
mov ax,4c00h
int 21h
;显示字符串
show_str:
push ax
push di
push si
push cx
push es
push dx
mov ax,0b800h
mov es,ax
mov ah,0
mov al,160
mul dh
mov di,ax
add dl,dl
mov dh,0
add di,dx;根据dh(行号)和dl(列号)中的值来计算开始显示字符的地址
mov si,0
mov cx,0
;开始循环输出
lp_show:
mov al,ds:[si];获取要输出字符
mov cl,al
jcxz ok_show;判断是否是0,是的话就结束输出字符串
mov byte ptr es:[di],al
mov byte ptr es:[di+1],2h;显示的字体是绿色
inc si
add di,2
loop lp_show
ok_show:
pop dx
pop es
pop cx
pop si
pop di
pop ax
ret
;删除字符
delete_char:
mov cx,si
cmp cx,0;先把si的值给cx,用于判断是否把字符串给删除完
jne delete_over;没有删除完字符串就跳转到delete_over处
;如果删除完结,就结束程序
jmp short get_charover
delete_over:
dec si
mov byte ptr ds:[si],0 ;删除字符就是把最后一个字符的位置用0来填充
jmp short print_char;处理删除结束就跳转到print_char处
;清除之前显示的字符串
clear_screen:
push ax
push di
push cx
push es
push dx
mov ax,0b800h
mov es,ax
mov ah,0
mov al,160
mul dh
mov di,ax
add dl,dl
mov dh,0
add di,dx;根据dh(行号)和dl(列号)中的值来计算开始清除字符的起始地址,其实和输出字符时起始
;地 址一样
mov cx,si;把si的值给cx,因为si的值就是之前字符串的长度
inc cx;问什么要加一,这时因为有删除字符发生时si的值被减去了1,所以要加1使其符合字符串的长度
;那没有删除字符发生时循环次数就会被加一,我想这应该没有问题吧,我们的目的是为了清除之前字
;符串,多清除应该没问题。但是很明显的这是一隐患
jcxz clrscrok
lp_clrscr:
mov byte ptr es:[di],20h
add di,2
loop lp_clrscr
clrscrok:
pop dx
pop es
pop cx
pop di
pop ax
ret
codesg ends
end start
(1)在输入的同时需要显示这个字符串
(2)一般在输入回车符后,字符串输入结束
(3)能够删除已经输入的字符
分析:我没用书上的入栈出栈写,就是先看看不用书上的方法能做出来否?实现过程在源代码中有详细的分析。
源代码:
assume cs:codesg
datasg segment
db 1024 dup(0)
datasg ends
codesg segment
start:
mov ax,datasg
mov ds,ax
mov si,0;设置ds:[si]指向存储字符串的地址空间
mov dh,12
mov dl,0;在第12行0列开始显示字符串
get_char:
mov ax,0
int 16h;调用int 16h的0号功能子程序读取键盘的输入
cmp al,20h
jb no_char;如果读取到的ASCII码值小于20h,就不是字符了,跳转到no_char处。
mov ds:[si],al;否则,就把字符的ASCII码是送入ds:[si]中保存起来
inc si
mov byte ptr ds:[si],0 ;每输入一个字符,就马上再起后一地址单元填充0.比如输入a后,其后单元填
;充0,再输入b,就会把刚刚的存储0的单元用来填充b,接着又会在b后的存储单元中填充0.依次类推
;输出字符串
print_char:
call clear_screen;输出字符串之前先要把之前显示的字符串给清空
call show_str;显示字符串
jmp short get_char;又跳转到get_char处,继续读取键盘的输入
;判断是否是enter键或backspace键的按下,是就转去执行相应的程序代码。如果是其他键,就退出程序
no_char:
cmp al,0dh
je get_charover;是enter键的话就退出程序
cmp al,8h
je delete_char;是backspace键就转到删除字符的子程序delete_char处
;其他键和enter键就退出程序
get_charover:
mov ax,4c00h
int 21h
;显示字符串
show_str:
push ax
push di
push si
push cx
push es
push dx
mov ax,0b800h
mov es,ax
mov ah,0
mov al,160
mul dh
mov di,ax
add dl,dl
mov dh,0
add di,dx;根据dh(行号)和dl(列号)中的值来计算开始显示字符的地址
mov si,0
mov cx,0
;开始循环输出
lp_show:
mov al,ds:[si];获取要输出字符
mov cl,al
jcxz ok_show;判断是否是0,是的话就结束输出字符串
mov byte ptr es:[di],al
mov byte ptr es:[di+1],2h;显示的字体是绿色
inc si
add di,2
loop lp_show
ok_show:
pop dx
pop es
pop cx
pop si
pop di
pop ax
ret
;删除字符
delete_char:
mov cx,si
cmp cx,0;先把si的值给cx,用于判断是否把字符串给删除完
jne delete_over;没有删除完字符串就跳转到delete_over处
;如果删除完结,就结束程序
jmp short get_charover
delete_over:
dec si
mov byte ptr ds:[si],0 ;删除字符就是把最后一个字符的位置用0来填充
jmp short print_char;处理删除结束就跳转到print_char处
;清除之前显示的字符串
clear_screen:
push ax
push di
push cx
push es
push dx
mov ax,0b800h
mov es,ax
mov ah,0
mov al,160
mul dh
mov di,ax
add dl,dl
mov dh,0
add di,dx;根据dh(行号)和dl(列号)中的值来计算开始清除字符的起始地址,其实和输出字符时起始
;地 址一样
mov cx,si;把si的值给cx,因为si的值就是之前字符串的长度
inc cx;问什么要加一,这时因为有删除字符发生时si的值被减去了1,所以要加1使其符合字符串的长度
;那没有删除字符发生时循环次数就会被加一,我想这应该没有问题吧,我们的目的是为了清除之前字
;符串,多清除应该没问题。但是很明显的这是一隐患
jcxz clrscrok
lp_clrscr:
mov byte ptr es:[di],20h
add di,2
loop lp_clrscr
clrscrok:
pop dx
pop es
pop cx
pop di
pop ax
ret
codesg ends
end start
评论次数(1) |
浏览次数(990) |
类型(Assembly's Road) |
收藏此文 |