王爽《汇编语言》 实验十六 二次调用地址不一致

做完了实验十六,由于后面的练习涉及按键选择功能,而这题恰好又是用参数选择子程序,就试图让程序根据键盘输入来选择子程序

 

程序如下,接受键盘输入的主要是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