100分啦!!! 请教各位高手,帮帮忙啦!!!

Systemgoblin 2007-12-27 10:40:24
请各位高手,帮我把把脉,看看我的程序哪里出问题了。谢谢。


我想写一个程序,把中断向量表的内容取出来,写到一个文件里。大家都知道中断向量表放在第一个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
...全文
109 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
czlyc006 2007-12-31
  • 打赏
  • 举报
回复
根据其特性,V86模式下使用特权指令通常不可靠,会被简单地忽略掉。
asmst 2007-12-29
  • 打赏
  • 举报
回复
1.楼主 你搞的太麻烦了
在copy那些数据的时候用段前缀就可以了
比如mov ecx,dword ptr 0:[si]
2.楼主认识错误,在实模式下你肯定可以干这样的事情,但你是在虚拟实模式下,不是真的实模式
3.windows 可能不会让你访问那些数据的,你在虚拟dos下应该可以访问那些数据的一份copy,
现在访问不了,我也搞不懂windows怎么搞的,我认为完全可以让一个程序在这个虚拟的1M空间内瞎搞,第1个dos程序启动时会给它创建一个全新的1M空间,以后启动的dos程序都共享这部分内存。
把虚拟dos模式下的0~10k都dump出来看看是什么东东,就用debug做。
还可以查些资料看看windows把这部分内存搬到什么地方去了(我觉得肯定会有一份copy)
4.实在是不行,你就转到真正的实模式下搞吧。

bilit2008 2007-12-29
  • 打赏
  • 举报
回复
帮顶
zhangjjhua 2007-12-29
  • 打赏
  • 举报
回复
不会.顶一下,
大熊猫侯佩 2007-12-29
  • 打赏
  • 举报
回复
还是没搞懂楼主的意思...-_-b
awperpvip 2007-12-29
  • 打赏
  • 举报
回复
mark
realbenz 2007-12-28
  • 打赏
  • 举报
回复
ding !
zara 2007-12-27
  • 打赏
  • 举报
回复
楼主的这个程序, 以前的个帖子我看过了, 也说了主要是段寄存器的分配和使用上的问题. 你的 DS=0000, ES=9000, 哪个寄存器来指向 data 段以使用其中的变量? 其实, 段的组织可以简单些的. ES=9000 段可以不要, 直接在 data 段中定义个空间来存放转换后的字符串. 甚至简单地, data 段的内容可以合并放在 code 段中的.
另外, 程序开始处有 .586 语句, 对于 dos16 类的程序, 还需要在其前面加上 .model small 这样的语句, 以使编译程序将段置为 16 位模式. 这两个语句及它们间顺序关系对缺省段模式的影响, 是编译器的个约定.
evileagle 2007-12-27
  • 打赏
  • 举报
回复
windows是不会让你随便动系统内存的,除非你写的是驱动,如果系统内存谁都可以访问修改很容易系统就崩溃了,楼主应该先了解windows的进程是什么
jmulxg 2007-12-27
  • 打赏
  • 举报
回复
比较少用的,现在也很少看汇编了。。。

21,458

社区成员

发帖
与我相关
我的任务
社区描述
汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区管理员
  • 汇编语言
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧