直接定址表
描述了单元长度的标号
以前我们多采用后面不带冒号的形式进行编程
assume:code
code segment
a: db 1,2,3,4,5,6,7,8
b: dw 0
start:
mov si,offset a
mov bx,offset b
mov cx,8
s:
mov al,cs:[si]
mov ah,0
add cs:[bx],ax
inc si
loop s
mov ax,4c00h
int 21h
code ends
end start
But the mark only represent the address of the memory. We still have another form of the mark that does not have the colon. For example.
assume:code
code segment
a db 1,2,3,4,5,6,7,8
b dw 0
start:
mov si,offset a
mov bx,offset b
mov cx,8
s:
mov al,a:[si]
mov ah,0
add bs,ax
inc si
loop s
mov ax,4c00h
int 21h
code ends
end start
mov al,a[si]
equal to mov al,cs:0[si]
So, we could find the way helps us access the address of memory in a neat form. We call it data-mark.他标记了存储数据的单元的地址和长度,它不同于仅仅表示地址的标号。
在其他段使用数据标号
一般来说,我们不在代码段中定义数据,而是将数据定义到其他段中,在其他段中,我们也可以使用数据标号来描述数据单元的地址和长度。
注意:在后面加有‘:’的地址只能在代码段中使用,不能在其他段使用。
实验
安装一个新的int 7ch中断例程
功能: 1.clear the screen
2.set the foreground
3.set the background
4.move up one row
思路
- 编写新的int 7ch 中断例程
- 安装新的int 7ch 中断例程
这个实验过程的代码出了很多问题,到最后终于改好了。
初期的改错思路
the major problem 是中断例程中table dw sub1,sub2,sub3,sub4
无法正常运作。
给人的感觉好像,不能在程序中用一样.按照这种形式写的话,后面的set标号无法被正确的编译。不知道为什么都变成了table标号下面的??
改成这种形式之后,才能在debug中的cpu看到正确的汇编代码,虽然代码段中把它们这些地址解析成了汇编指令
通过后续的观察发现,其实代码是被正确解析了的,只是在cpu版块的显示上table段中的存放的数据被当作了指令。但是为什么程序不执行呢?
这也是为什么要把jmp命令放在前面的原因,就是为了不让table段存放的数据被当作指令执行,这样的话,肯定有问题的
后期的改错思路
先整理一下初期思路中出错的原因,再分析一下是哪些基础的知识没有掌握好,导致我们这么长时间一直在纠错
初期思路:
1.jmp命令放在前面的原因,就是为了防止我们存储的数据被当作指令执行,这也是为什么你在debug模块中的cpu看汇编代码的时候,看起来好像很奇怪。但是它们都是正常的指令。
2.
tabledata dw sub1,sub2,sub3,sub4;
无论是tabledata 还是 sub1,sub2 这些地址都是相对于最开始运行的CS段而言的,而我们想要的是中断例程,也就是执行中断例程的时候的CS段。这样去调用的话,肯定会出错。说成白话的话就是,本来一棵树距离图书馆35米,但是现在要问你,这棵树举例教学楼多少米,你要是还说35米。那是不是有点刻舟求剑的意思了。所以,真正要采用的是相对地址,还得加上0200h才行! 这样才行tabledata dw offset sub1 - offset interupt + 0200h,offset sub2 - offset interupt+0200h,offset sub3 - offset interupt+0200h,offset sub4 - offset interupt+0200h
call word ptr [bx]
这样默认的访问地址是ds+bx
,而你想要的是cs:[bx]
所以要把寄存器显式的标注出来啊
- 虽然中断例程处,确实没有办法通过
F7
进入,但是可以通过看0000:0200h
内存中代码,就可以发现到底是不是你想要的了。
- 虽然中断例程处,确实没有办法通过
- int指令和iret指令的作用,如果真的能很好的掌握这两个指令,也犯不着这么长时间才找到问题的源头。
代码
assume cs:code
code segment
start:
mov ax,cs
mov ds,ax
mov si,offset interupt; set the ds:si point to the source address
mov ax,0
mov es,ax
mov di,0200h; set the es:di point to the destination address
mov cx,offset interuptend-offset interupt; cx the length of transmisson
cld ; the sequence of the transmit
rep movsb
mov ax,0
mov es,ax
cli
mov word ptr es:[7ch*4],0200h
mov word ptr es:[7ch*4+2],0
sti
;调用之前的设置你需要再看一下要求是怎么设置的
mov ah,2
mov al,3
int 7ch; 这里怎么跳到了4002h
; call interupt
mov ax,4c00h
int 21h
;所以程序大体上是没有问题的
;但是加上table sub1,sub2,sub3,sub4之后就显的怪怪的
;通过调试程序来看的话,只有mov bl,ah之后的程序是正常的
;前面的程序好像都是错的一样,--通过CPU反汇编的指令来看的话,前面的几句都不对
;我如果去掉table直接调用函数的话,就不会出现上述问题
;对前面的简单程序进行操作后发现,这个table dw sub1,sub2,sub3,sub4不能在标号里面
;也不是因为jmp short set语句和tabledata dw......两个语句的顺序问题
;书上说
interupt:
jmp short set
;并不是写法是错的,而是你用错了
;按道理来说,程序的执行CS IP 本来在code段
;现在你引发了中断以后就跑到 中断例程中的CS IP了,但是此时 tabledata中保存的仍然是最开始的CS IP 这样一跳转的话,z
; tabledata dw sub1,sub2,sub3,sub4;这种写法是错误的
;写成下面这种形式的话,set标号就会重新显示出来
tabledata dw offset sub1 - offset interupt + 0200h,offset sub2 - offset interupt+0200h,offset sub3 - offset interupt+0200h,offset sub4 - offset interupt+0200h
; tabledata dw offset sub1 - offset interupt + 0200h,offset sub2 - offset interupt + 0200h,offset sub3 - offset interupt + 0200h,offset sub4 - offset interupt + 0200h
set:
push bx
push es
push cx
cmp ah,3;判读功能号是否大于3
ja sret
mov bl,ah
mov bh,0
add bx,bx;根据ah中的功能号计算对应子程序在table表中的偏移
add bx,offset tabledata-offset interupt + 0200h
; call word ptr (offset tabledata-offset interupt)[bx+0200h];调用对应的功能子程序这句话有问题
; 上面这条指令错就错在 这样隐含的寄存器是ds 也就是 访问的是ds:[...]但是我们想要的是cs:[bx]
call word ptr cs:[bx]
; add bx,7e02h
; jmp cs:[bx]
sret:
pop cx
pop es
pop bx
; ret
iret
;make the screen empty
sub1:
push bx
push cx
push es
mov bx,0b800h
mov es,bx
mov bx,0
mov cx,2000
sub1s:
mov byte ptr es:[bx],' '
add bx,2
loop sub1s
pop es
pop cx
pop bx
ret
; jmp sret
; set the foreground
sub2:
push bx
push cx
push es
mov bx,0b800h
mov es,bx
mov bx,1
mov cx,2000
sub2s:
and byte ptr es:[bx],11111000B
or es:[bx],al
add bx,2
loop sub2s
pop es
pop cx
pop bx
ret
;set the background color
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
sub3s:
and byte ptr es:[bx],10001111B
or es:[bx],al
add bx,2
loop sub3s
pop es
pop cx
pop bx
ret
;scroll up one line
sub4:
push cx
push si
push di
push es
push ds
mov si,0b800h
mov es,si
mov ds,si
mov si,160;ds:si指向第n+1行
mov di,0;es:di指向第n行
cld
mov cx,24;共复制24行
sub4s:
push cx
mov cx,160
rep movsb
pop cx
loop sub4s
mov cx,80
mov si,0
sub4s1:
mov byte ptr [160*24+si],' ';最后一行清空
add si,2
loop sub4s1
pop ds
pop es
pop di
pop si
pop cx
ret
interuptend:
nop
code ends
end start