j450n 发表于 2021-1-10 16:49:41

汇编语言(王爽)实验16_功能子程序跳转问题

本帖最后由 j450n 于 2021-1-10 16:57 编辑

问题描述:

在原实验基础上结合实验15和16,把该程序写入int9键盘中断,运行后可以输入0~3来检验4个子程序功能。

参考过网上的答案,直接定址表已避开因程序copy而造成偏移地址改变的坑,采用offset sub1 - offset setscreen + 204h的方式。

实际运行后,只有功能1、2能实现,功能0、3无法实现。通过改变(call word ptr cs:)(即204h改为202,206,208)检验子程序本身并无问题,但不能同时实现4个功能正常运行。

debuge 对int9中断无法单步跟踪,一直找不出问题所在,向论坛大神求助!

代码如下:
assume cs:code

code segment
start:

    mov ax,0
    mov es,ax

    push es:
    pop es:
    push es:
    pop es:
    ;save BIOS origin int9 to 0:200h~202h

    cli ;IF = 0
    mov word ptr es:,204h
    mov word ptr es:,0
    sti ;IF = 1
    ;set new int9 entry address as 0:204h

    mov ax,cs
    mov ds,ax
    mov si,offset int9
    mov di,204h
    mov cx,offset int9end-offset int9
    cld ;DF = 0 forward
    rep movsb

    mov ax,4c00h
    int 21h

int9:
    setscreen:        jmp short set
   
        table                dw offset sub1 - offset setscreen + 204h
                                dw offset sub2 - offset setscreen + 204h
                                dw offset sub3 - offset setscreen + 204h
                                dw offset sub4 - offset setscreen + 204h
                       
set:       
    push bx
    push ax
    push es
    push cx
    push di

    mov ax,0
    mov es,ax
    pushf         
    call dword ptr es:
    ;call original int9

    in al,60h
    mov ah,al
    mov al,4
        cmp ah,3
        ja sret
        mov bl,ah
        mov bh,0
        add bx,bx
        call word ptr cs:

sret:
    pop di
    pop cx
    pop es
    pop ax
    pop bx
    ;CAN NOT add popf here, it's done in call original int9
    iret

sub1:                                        ;1号子程序
        push bx
        push cx
        push es
        mov bx,0b800h
        mov es,bx
        mov bx,0
        mov cx,2000
sub1s:
        mov byte ptr es:,' '
        add bx,2
        loop sub1s
        pop es
        pop cx
        pop bx
        ret

sub2:                                        ;2号子程序
        push bx
        push cx
        push es
        mov bx,0b800h
        mov es,bx
        mov bx,1
        mov cx,2000
sub2s:
        and byte ptr es:,11111000b
        or es:,al
        add bx,2
        loop sub2s
        pop es
        pop cx
        pop bx
        ret

sub3:                                        ;3号子程序
        push bx
        push cx
        push es
        mov cl,4
        shl al,cl
        mov bx,0b800h
        mov es,bx
        mov bx,1
        mov cx,2000
sub3s:
        and byte ptr es:,10001111b
;        shl al,1
;        shl al,1
;        shl al,1
;        shl al,1
        or es:,al
        add bx,2
        loop sub3s
        pop es
        pop cx
        pop bx
        ret

sub4:                                        ;4号子程序
        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
sub4s:
        push cx
        mov cx,160
        rep movsb
        pop cx
        loop sub4s

        mov cx,80
        mov si,0
sub4s1:
        mov byte ptr ,' '
        add si,2
        loop sub4s1
       
        pop ds
        pop es
        pop di
        pop si
        pop cx
        ret

int9end: nop

code ends
end start

wtchou 发表于 2021-1-11 01:55:47

in al,60h 获取的是键盘扫描码
输入 0, 1, 2, 3 得到的扫描码为 B, 2, 3, 4

j450n 发表于 2021-1-11 11:25:12

本帖最后由 j450n 于 2021-1-11 11:27 编辑

wtchou 发表于 2021-1-11 01:55
in al,60h 获取的是键盘扫描码
输入 0, 1, 2, 3 得到的扫描码为 B, 2, 3, 4

多谢大神提醒!问题解决了!
结果最头疼的bug其实是最低级的错误{:10_277:}


终于运行正常了{:10_266:}
(功能号改为1-4)

j450n 发表于 2021-2-19 09:45:17

wtchou 发表于 2021-1-11 01:55
in al,60h 获取的是键盘扫描码
输入 0, 1, 2, 3 得到的扫描码为 B, 2, 3, 4

int9:
    setscreen:      jmp short set
   
      table                dw offset sub1 - offset setscreen + 204h
                              dw offset sub2 - offset setscreen + 204h
                              dw offset sub3 - offset setscreen + 204h
                              dw offset sub4 - offset setscreen + 204h
                     

接原帖里的代码,想再请教一下
直接定址表如果被安装到内存中另外一个位置,是不是就无法再用了,必须按上述引用的计算地址的方式来写吗?有没有其他的解决方法?

wtchou 发表于 2021-2-20 20:18:25

定址表里的内容都是原程序的地址, 所以我自己也是用类似的方法去处理

j450n 发表于 2021-2-22 10:17:21

wtchou 发表于 2021-2-20 20:18
定址表里的内容都是原程序的地址, 所以我自己也是用类似的方法去处理

好的,tks
页: [1]
查看完整版本: 汇编语言(王爽)实验16_功能子程序跳转问题