使用直接定址表遇到的问题

直接定址表是否要先定义后使用?看起来是的。否则出现错误:

使用直接定址表遇到的问题_第1张图片


此错误为遍历出错,masm在两次扫描代码时得到的某个标记的地址值不同。


因为在定义直接定址表前就使用了它。修改后没问题。


附代码:

assume cs:code
code segment
   start:mov ax,0
         mov es,ax
         mov di,200h


         mov ax,cs
         mov ds,ax
         mov si,offset int7ch


         mov ax,offset sub1 - offset int7ch
         add ax,200h
         mov [si+2],ax
         mov ax,offset sub2 - offset int7ch
         add ax,200h
         mov [si+4],ax
         mov ax,offset sub3 - offset int7ch
         add ax,200h
         mov [si+6],ax
         mov ax,offset sub4 - offset int7ch
         add ax,200h
         mov [si+8],ax


         mov cx,offset int7ch_e - offset int7ch


         cld
         rep movsb


         mov ax,200h
         mov es:[7ch*4],ax
         mov ax,0
         mov es:[7ch*4+2],ax


         mov ax,4c00h
         int 21h




  int7ch:jmp short begin
         dw 0,0,0,0
   begin:push bx
         push ds
         mov bx,cs
         mov ds,bx
         mov bl,ah
         mov bh,0
         add bx,bx
         call word ptr [bx].202h
         pop ds
         pop bx
         iret


    sub1:push bx
         push cx
         push es


         mov bx,0b800h
         mov es,bx
         mov bx,0
         mov cx,2000
      s1:mov byte ptr es:[bx],' '
         add bx,2
         loop s1


         pop es
         pop cx
         pop bx
         ret


    sub2:push bx
         push cx
         push es


         mov bx,0b800h
         mov es,bx
         mov bx,1
         mov cx,2000
      s2:and byte ptr es:[bx],11111000b
         or byte ptr es:[bx],al
         add bx,2
         loop s2


         pop es
         pop cx
         pop bx
         ret


    sub3:push bx
         push cx
         push es


         mov cl,4
         shl al,cl


         mov bx,0b800h
         mov es,bx
         mov bx,1
         mov cx,2000
      s3:and byte ptr es:[bx],10001111b
         or byte ptr es:[bx],al
         add bx,2
         loop s3


         pop es
         pop cx
         pop bx
         ret




    sub4:push bx
         push cx
         push es
         push si


         mov bx,0b800h
         mov es,bx


         mov cx,24
         mov bx,0
     s44:push cx
         mov cx,80
         mov si,0
      s4:push es:[bx].160[si]
         pop es:[bx][si]
         add si,2
         loop s4
         pop cx
         add bx,160
         loop s44


         pop si
         pop es
         pop cx
         pop bx
         ret


int7ch_e:nop


code ends
end start


其中修改部分为:

         mov ax,offset sub1 - offset int7ch
         add ax,200h
         mov [si+2],ax
         mov ax,offset sub2 - offset int7ch
         add ax,200h
         mov [si+4],ax
         mov ax,offset sub3 - offset int7ch
         add ax,200h
         mov [si+6],ax
         mov ax,offset sub4 - offset int7ch
         add ax,200h
         mov [si+8],ax


原先想通过直接引用直接定址表对其中的数据进行访问。

       
         mov ax,offset sub1 - offset int7ch
         add ax,200h
         mov table[0],ax
         mov ax,offset sub2 - offset int7ch
         add ax,200h
         mov table[1],ax
         mov ax,offset sub3 - offset int7ch
         add ax,200h
         mov table[2],ax
         mov ax,offset sub4 - offset int7ch
         add ax,200h
         mov table[3],ax




还有一个比较严重的问题:此程序为中断处理程序的安装程序,在用MASM进行编译链接的时候,table标记被解释为table在此安装程序内的偏移,为004E

因此,中断处理程序中对table的引用都是004E 。比如

call byte ptr table[bx]

比如要使用7ch中断中的0号程序,则bx=0 .而table[bx]得到的内存单元是(bx)+004e 并不是我们想要的在中断处理程序中的table值加上偏移量bx定位到的存储子程序IP的内存区。因为table值翻译成二进制代码在编译和链接后就完成了,安装程序只是把代码复制到目的区域。安装完成后0:200处代码如下

使用直接定址表遇到的问题_第2张图片


红色部分,可以看到call指令使用的寻址call table[bx]代码为call [BX+004E] 。而再看看原安装程序内的情况:

使用直接定址表遇到的问题_第3张图片


紧接着jmp指令的一条指令,其实不是指令,而是我们定义的四个word型数据。刚好它的偏移地址是004e 也是table标记的地址值。


修改方法是使用数据段的寻址

int7ch:jmp short begin
         dw 0,0,0,0
   begin:push bx
         push ds
         mov bx,cs
         mov ds,bx
         mov bl,ah
         mov bh,0
         add bx,bx
         call word ptr [bx].202h
         pop ds
         pop bx
         iret


不使用table了,但是仍然是直接定址表的思想,程序的地址放在一个连续的空间存放。

使用直接定址表主要的问题:call指令目标地址的定位问题。

1.首先是转移目的地址的存储。本来是用一个 table dw 0,0,0,0存储,但是table在编译连接后获得的是在安装程序中的地址,在中断处理程序中是无效的。

2.后来根据传送来的子程序号用call指令定位子程序IP。搞清楚子程序IP到底存储在什么位置










   

你可能感兴趣的:(c,table,存储,byte)