100分啦!!! 请教各位高手,帮帮忙啦!!!
请各位高手,帮我把把脉,看看我的程序哪里出问题了。谢谢。
我想写一个程序,把中断向量表的内容取出来,写到一个文件里。大家都知道中断向量表放在第一个1MB的第一个1KB里。我想,把代码段设为0,偏移地址也设为0,即
mov ax,0
mov ds,ax
mov si,0
把附加段的段地地址设为9000H,偏移地址设为0,即
mov ax,9000h
mov es,ax
mov di,0
考虑到很可能段的使用会有冲突,所以就把附加段ES设置为9000h。
一次读出四个字节,并把它们转换成十六进制表示(具体由下面的ECX_TO_16子程序实现)。一共循环256次,就完成了1024字节的二进制数到十六制数的转换。
以下的程序经过了十多次的修改,仍然不能在WINDOWS里运行(运行就会出现需要“调试”的窗口)。因为本人还尚未掌握保护模式下的DOS编程,所以只能写实模式的程序。一般来说,WINDOWS也支持虚拟86,按道理,应该可以运行的。但还是出了问题。
另外,我还发现了自身的一个矛盾。 首先,我设想把1MB的第一个64K内存当作数据段,即数据段段地址为0,偏移为0,这样就可以进行数据处理。但是接着的矛盾就来了:程序里要定义数据段。很明显,这会与设想的数据段地址有冲突。1024字节的中断向量表很可能就会被修改。
再有,运行本程序是虚拟的,WINDOWS会不会这样处理:并不把DS:SI并不指向实模式的0号地址,而是指向别的什么地址? 对此,我很是苦恼。
难道,在实模式下不能写一个程序把中断向量表取出来?
敬请各位高手帮帮忙了......
把一些程序段写成子程序,是为了程序的阅读清晰。
.586
;-------------------------------------------------------------------------------------------------------
data segment
save_data dw ?
PATHNAME db 'E:\abc\abcde.txt',00h
HANDLE_ dw ?
e1 db 'Set file is fail.$'
e2 db 'Send message fail.$'
e3 db 'Message sizes error.$'
data ends
;-------------------------------------------------------------------------------------------------------
data2 segment
data2 ends
stack segment stack
dw 200 dup(?)
stack ends
;-------------------------------------------------------------------------------------------------------
code segment
assume cs:code,ds:data,es:data2
_start:
push ds
sub ax,ax
push ax
mov ds,ax
mov ax,9000h
mov es,ax
mov si,0
mov di,0
call ppoo
call aatt
mov ax,4c00h
int 21h
;-------------------------------------------------------------------------------------------------------
;建立文件
;-------------------------------------------------------------------------------------------------------
ppoo proc near
push ax
push cx
push dx
mov ah,3ch
mov cx,00
lea dx,PATHNAME
int 21h
jc er1 ;如果建立文件失败则跳到er1处,并输出建立文件失败信息
mov HANDLE_,ax
jmp uiui
er1:
push dx
lea dx,e1
mov ah,9h
int 21h
pop dx
mov ax,4c00h
int 21h
uiui:
pop dx
pop cx
pop ax
ret
ppoo endp
;-------------------------------------------------------------------------------------------------------
;-------------------------------------------------------------------------------------------------------
;程序的主要内容
;把第一个1024字节取出,经ECX_TO_16子程序转换后送往附加段,然后再把附加段的2048字节(即已经转换后的内容)送
;往数据段。因为,在最后要把程序里的数据写入文件时,把将要输出内容的偏移地址送DX。我经过查看DOS中断
;int 21h 的功能40h时,发现此功能并没有说明输出内容的段地址可以使用ES,我怀疑它是用DS作段地址。所以要把转;换后的内容再传回数据段中
aatt proc near
push eax
push ecx
push edx
mov eax,255 ;设置EAX为255。由于以下指令使用了mov ecx,ds:dword ptr [si]
;一次把四个字节送到EAX中进行二进制到十六进制数的转换。中断向量只有1024
;字节,所以把EAX设置为255,以便作循环结束的控制条件
loop1:
mov ecx,ds:dword ptr [si]
mov dword ptr save_data,ecx ;把四个字节送入
call ECX_TO_16 ;
add si,4
cmp eax,0 ;此即循环结束的控制条件。当256次的四个字节都传送完毕就结束程序。
;0号地址的一次加上255次即一共256次。256*4=1024
jz leave_
dec eax
jmp loop1
leave_:
xor si,si
xor di,di
mov ax,5000h
mov ds,ax
again2:
mov dl,es:BYTE ptr [di] ;现在的附加段里存放的是转换后的数据,一共2048个字节
mov ds:BYTE ptr [si],dl ;这里的作用是把附加段的数据再回传到数据段,回传的数据肯定会把原
inc di ;来的数据段里的数据破坏掉。我也顾不得那么多了,我只想把中断向量
inc si ;表取出来保存到文件里,以方便研究用
cmp di,800h
jz passmessage
jmp again2
passmessage:
mov ah,40h ;当所有数据就绪之后,40h功能进行写文件操作
mov bx,HANDLE_
mov cx,7FFH
mov dx,0
int 21h
jc er2
cmp ax,7FFH
jne er3
jmp tt
er2:
push dx
lea dx,e2
mov ah,9h
int 21h
pop dx
mov ax,4c00h
int 21h
er3:
lea dx,e3
mov ah,9h
int 21h
mov ax,4c00h
int 21h
tt:
mov ah,3eh ;关闭文件,把数据保存到磁盘文件
mov bx,HANDLE_
int 21h
mov ax,4c00h
int 21h
pop edx
pop ecx
pop eax
ret
aatt endp
;-------------------------------------------------------------------------------------------------------
;-------------------------------------------------------------------------------------------------------
;把寄存器里的二进制数转换为十六进制数
ECX_TO_16 proc far
push eax
push ebx
push ecx
push edx
mov eax,dword ptr save_data
mov ch,8
rotate:
mov cl,4
rol eax,cl
mov bl,al
and bl,0fh
add bl,30h
cmp bl,3ah
jl save
add bl,7h
save:
mov es:BYTE ptr [di],bl
inc di
dec ch
jnc rotate
pop edx
pop ecx
pop ebx
pop eax
ret
ECX_TO_16 endp
;-------------------------------------------------------------------------------------------------------
code ends
end _start