做完了实验十六,由于后面的练习涉及按键选择功能,而这题恰好又是用参数选择子程序,就试图让程序根据键盘输入来选择子程序
程序如下,接受键盘输入的主要是getchar子程序,运行后发现不出end,检查其他子程序的栈平衡没发现问题。但发现getchar第一次调用和第二次调用时call 的地址不一样,第一次能正常使用getchar 但第二次call就从主线程跳转到了一个没有指令的地方,第一次遇到这种状况,不知道自己哪里搞错了。
assume cs:code,ds:menu
menu segment
db '__________________________________\n'
db '|choose the function your need: |\n'
db '|0.clear the screen |\n'
db '|1.set the front color |\n'
db '|2.set the background color |\n'
db '|3.roll back screen by 1 line |\n'
db '|_________________________________|\0'
setcolor: db 'choose color:\0'
menu ends
stack segment
db 128 dup(0)
stack ends
error segment
db 'illegal input,press r back:\0'
error ends
oringalEntry segment
dd 0
oringalEntry ends
code segment
start:
main:
mov ax,stack
mov ss,ax
mov sp,128
call install7ch
mov ax,menu
mov ds,ax
mov ax,2 ;颜色
push ax
mov ax,40 ;列数 of 80
push ax
mov ax,13 ;行数 of 25
push ax
call show_str
call getchar ;choose fun ;dosbox第一次调用为:call 015e
mov dh,al
mov ah,al
int 7ch
mov ax,0 ;return int7ch oringal entry
mov es,ax
mov ax,oringalEntry
mov ds,ax
mov ax,ds:[0]
mov es:[7ch*4],ax
mov ax,ds:[2]
mov es:[7ch*4+2],ax
mov ax,4c00h
int 21h
int7ch:
cmp ah,0
je do0
cmp ah,1
je do1
cmp ah,2
je do2
cmp ah,3
je do3
jmp short sret
do0:
call cls
jmp short sret
do1:
call getchar ;set color ;dosbox第一次调用为:call 0319
mov ah,dh
call setFront
jmp short sret
do2:
call getchar ;set color ;dosbox第一次调用为:call 0319
mov ah,dh
call setBack
jmp short sret
do3:
call rollBack
jmp short sret
sret:iret
cls:
push bx
push cx
push es
mov bx,0b800h
mov es,bx
mov bx,0
mov cx,2000
clss:
mov byte ptr es:[bx],' '
add bx,2
loop clss
pop es
pop cx
pop bx
jmp subret
setFront:
push bx
push cx
push es
mov bx,0b800h
mov es,bx
mov bx,1
mov cx,2000
setFronts:
and byte ptr es:[bx],11111000b
or es:[bx],al
add bx,2
loop setFronts
pop es
pop cx
pop bx
jmp subret
setBack:
push bx
push cx
push es
mov cl,4
shl al,cl
mov bx,0b800h
mov es,bx
mov bx,1
mov cx,2000
setBacks:
and byte ptr es:[bx],10001111b
or es:[bx],al
add bx,2
loop setBacks
pop es
pop cx
pop bx
jmp subret
rollBack:
push cx
push si
push di
push es
push ds
mov si,0b800h
mov es,si
mov ds,si
mov si,160
mov di,0
cld
mov cx,24
rollBacks:
push cx
mov cx,160
rep movsb
pop cx
loop rollBacks
rollBacks1:
mov byte ptr [160*24+si],' '
add si,2
loop rollBacks1
pop ds
pop es
pop di
pop si
pop cx
jmp subret
subret:
ret
int7ch_end:nop
show_str: ;函数介绍:将从ds:si到'\0'结尾的字符串显示在屏幕上,ds:si指向字符串,其他参数在栈中,为:行号,列号,颜色(由栈顶向栈底)
push bp
mov bp,sp ;bp指向栈顶
push ax
push bx
push ds
push es
push si
push di
mov bx,0b800h ;用es:bx+di指向显存
mov es,bx
mov ax,160 ;根据行和列计算在显存中相应的偏移地址,存入bx中
mul word ptr [bp+4]
mov bx,[bp+6]
add bx,bx
add bx,ax
putchar:
mov ax,ds:[si]
mov es:[bx+di],ax
mov ax,[bp+8]
mov es:[bx+di+1],ax
add di,2
inc si
cmp ds:[si],6E5CH ;ascii for '\n'
je nextline
cmp ds:[si],305CH ;ascii for '\0'
je show_str_end
jmp short putchar
show_str_end: ;还原子程序中用到的参数
pop di
pop si
pop es
pop ds
pop bx
pop ax
pop bp
ret 6
nextline:
add bx,160
add si,2
mov di,0
jmp short putchar
getchar:
int 16h
cmp al,00h
ja gret
jmp short getchar
gret:
sub al,30H
ret
install7ch:
push ax
push ds
push es
push si
push di
push cx
mov ax,0
mov es,ax
mov di,200h
mov ax,cs
mov ds,ax
mov si,offset int7ch ;install program to 0:200
mov cx,offset int7ch_end - offset int7ch
cld
rep movsb
mov ax,oringalEntry
mov ds,ax
mov ax,es:[7ch*4]
mov ds:[0],ax
mov ax,es:[7ch*4+2]
mov ds:[2],ax
mov es:[7ch*4],200h
mov es:[7ch*4+2],0
pop cx
pop di
pop si
pop es
pop ds
pop ax
ret
delay: ;delay for 0000 ffffh
push dx
push ax
mov dx,0h
mov ax,0ffffh
s1:
sub ax,1
sbb dx,0
cmp ax,0
jnz s1
cmp dx,0
jnz s1
pop ax
pop dx
ret
code ends
end start