386保护方式编程问题

QIANYONGMING 2008-04-15 06:31:48
问题是:从实方式进不了保护方式?我用的编译器是TASM5.0,borlandc++3.1也试过!
在编译:TASM ASM1.ASM
链接:TLINK ASM1.OBJ
后执行debug工具TD ASM1.EXE,此时就会提示:program has no symbol table!
之后改用:
编译:TASM ASM1.ASM
链接:TLINK /V ASM1.OBJ
后执行debug工具TD ASM1.EXE,上述提示没了,但执行到:JUMP16 Code_Sel,<OFFSET Virtual>时系统就死在这里了,
请问各位这是什么原因?谢谢
下面是书中的源程序:
;名称:ASM1.ASM
;功能:演示实方式和保护方式切换(切换到16位代码段)
;----------------------------------------------------------------------------
INCLUDE 386SCD.INC
;----------------------------------------------------------------------------
;字符显示宏指令的定义
;----------------------------------------------------------------------------
EchoCh MACRO ascii
mov ah,2
mov dl,ascii
int 21h
ENDM
;----------------------------------------------------------------------------
DSEG SEGMENT USE16 ;16位数据段

GDT LABEL BYTE ;全局描述符表
DUMMY Desc <> ;空描述符
Code Desc <0ffffh,,,ATCE,,> ;代码段描述符
DataS Desc <0ffffh,0,11h,ATDW,,> ;源数据段描述符
DataD Desc <0ffffh,,,ATDW,,> ;目标数据段描述符

GDTLen = $-GDT ;全局描述符表长度
VGDTR PDesc <GDTLen-1,> ;伪描述符

Code_Sel = Code -GDT ;代码段选择子
DataS_Sel = Datas-GDT ;源数据段选择子
DataD_Sel = DataD-GDT ;目标数据段选择子

BufLen = 256 ;缓冲区字节长度
Buffer DB BufLen DUP(0) ;缓冲区

DSEG ENDS ;数据段定义结束
;----------------------------------------------------------------------------
CSEG SEGMENT USE16 ;16位代码段
ASSUME CS:CSEG,DS:DSEG

Start proc
mov ax,DSEG
mov ds,ax
mov bx,16 ;准备要加载到GDTR的伪描述符
mul bx
add ax,OFFSET GDT ;计算并设置基地址
adc dx,0 ;界限已在定义时设置好
mov WORD PTR VGDTR.Base,ax
mov WORD PTR VGDTR.Base+2,dx
mov ax,cs ;设置代码段描述符
mul bx
mov WORD PTR Code.BaseL,ax ;代码段开始偏移为0
mov BYTE PTR Code.BaseM,dl ;代码段界限已在定义时设置好
mov BYTE PTR Code.BaseH,dh
mov ax,ds
mul bx ;计算并设置目标数据段基址
add ax,OFFSET Buffer
adc dx,0
mov WORD PTR DataD.BaseL,ax
mov BYTE PTR DataD.BaseM,dl
mov BYTE PTR DataD.BaseH,dh
lgdt QWORD PTR VGDTR
cli ;关中断
EnableA20 ;打开地址线A20
mov eax,cr0
or eax,1
mov cr0,eax
JUMP16 Code_Sel,<OFFSET Virtual>
Virtual: ;现在开始在保护方式下运行
mov ax,DataS_Sel
mov ds,ax ;加载源数据段描述符
mov ax,DataD_Sel
mov es,ax ;加载目标数据段描述符

cld
xor si,si
xor di,di ;设置指针初值
mov cx,BufLen/4 ;设置4字节为单位的缓冲区长度
repz movsd ;传送

mov eax,cr0 ;切换回实模式
and al,11111110b
mov cr0,eax ;清指令预取队列,进入实方式
JUMP16 <SEG Real>,<OFFSET Real> ;16位的保护方式
Real: ;现在又回到实方式
DisableA20
sti

mov ax,DSEG ;实地址方式下显示
mov ds,ax
mov si,OFFSET Buffer
cld
mov bp,BufLen/16
NextLine:
mov cx,16
NextCh: lodsb ;
push ax
shr al,1
call ToASCII
EchoCh al
pop ax
call ToASCII
EchoCh al
EchoCh ' '
loop NextCh
EchoCh 0dh
EchoCh 0ah
dec bp
jnz NextLine
mov ax,4c00h
int 21h
Start ENDP
;----------------------------------------------------------------------------
ToASCII PROC
and al,0fh
add al,90h
daa
adc al,40h
daa
ret
ToASCII ENDP
;----------------------------------------------------------------------------
CSEG ENDS ;代码段定义结束
;----------------------------------------------------------------------------
END Start
...全文
277 18 打赏 收藏 举报
写回复
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
xym5366 2011-03-30
  • 打赏
  • 举报
回复
全都是说的纯理论东西,楼主还是自己看看基础书吧,或再百度一下,这些人我看很难给你讲明白,你最好的选择还是自己看基础书,从书里学。
cnzdgs 2008-04-19
  • 打赏
  • 举报
回复
使用HIMEM是通过调用INT 2FH的43H功能,你可以在网上搜索一下“XMS”、“INT 2F 43”等关键字。
mov cr0,eax这条指令不会引起死机,而且无法通过常规的方法来确定是不是在这条指令上死机,一般的调试工具到这里就没法继续调试了(bochs我没用过),另外如果在Windows的DOS窗口中是不能执行这样的代码的。
如果要一直保持在保护模式下运行,还需要考虑中断的处理问题,这样就更复杂了。
cnzdgs 2008-04-18
  • 打赏
  • 举报
回复
在config.sys中把device=himem.sys这行去掉就不加载了,切入保护模式前自己用代码打开A20。
你完全可以利用himem来使用1MB以上的内存,不需要自己写保护模式程序。
QIANYONGMING 2008-04-18
  • 打赏
  • 举报
回复
还有一个问题:我做的这个程序编程方法是从16位实方式进入16位保护方式,在保护方式下通过调用门访问32位程序段,这32位程序段做成类似实方式下的子程

序,因为这个程序要经常调用这个32位程序段。而且,该程序进入保护模式后就不再返回实模式,除非关机,否则一直在16位保护模式下循环执行!

这个方法行得通吗
QIANYONGMING 2008-04-18
  • 打赏
  • 举报
回复
你说的这些我也知道了解

但我还是搞不清楚问题出在哪点了:我编的测试程序和应用程序都是这个问题!所有的程序我都是采用这种方式进保护模式的!

还有一个问题HIMEM 怎样用阿?

如下注释部分的原因:
Start proc
mov ax,DSEG
mov ds,ax
......
lgdt QWORD PTR VGDTR
cli ;关中断
EnableA20 ;打开地址线A20
mov eax,cr0
or eax,1
mov cr0,eax ;执行到此处死机,根本进不了保护模式,更不要说从保护模式返回实模式了,是什么原因?之前全局描述符表等装载的也没问题阿,不明白问题出哪儿了
JUMP16 Code_Sel, <OFFSET Virtual>
Virtual: ;进入保护模式
......
......
mov eax,cr0 ;切换回实模式
and al,11111110b
mov cr0,eax
JUMP16 <SEG Real>, <OFFSET Real>
Real: ;回到实方式
DisableA20
sti
.......

[Quote=引用 14 楼 cnzdgs 的回复:]
你现在还没有遇到与HIMEM冲突的问题。

切回实模式需要把cr0的第0位清0,并执行一条跳转隔断指令流。
要在实模式下使用32位地址空间,需要需要在保护模式下给DS、ES装入描述符,并且切回实模式后不能关闭A20。

既然在DOS下运行应该首先考虑使用HIMEM。
[/Quote]
QIANYONGMING 2008-04-18
  • 打赏
  • 举报
回复
应怎样避免发生使用扩展内存而发生冲突的情况,如果关闭HIMEM扩展内存管理程序,系统就不内打开A20,也就进不了保护模式了。用了扩展内存后,应该怎样避免冲突?
QIANYONGMING 2008-04-18
  • 打赏
  • 举报
回复
HIMEM只是扩充内存管理程序,怎样不加载这个扩展内存的驱动程序?
cnzdgs 2008-04-18
  • 打赏
  • 举报
回复
你现在还没有遇到与HIMEM冲突的问题。

切回实模式需要把cr0的第0位清0,并执行一条跳转隔断指令流。
要在实模式下使用32位地址空间,需要需要在保护模式下给DS、ES装入描述符,并且切回实模式后不能关闭A20。

既然在DOS下运行应该首先考虑使用HIMEM。
QIANYONGMING 2008-04-18
  • 打赏
  • 举报
回复
楼上各位朋友的方法,我也试试了,但还是没解决问题!可能自己水平低,表达的不清楚!

可以这么说吧:纯ms-dos平台加载了himem.sys,bios里显示low memeory:639k extended memory:3072K;cpu是386EX嵌入式处理器,内存是4M,编译环境是

Borlandc++3.1中自带的TASM编译器和tlink连接器;测试程序如1楼程序,由实模式进入保护模式:打开A20,读写CR0寄存器,问题就出在写cr0处,死机!

请各位帮我想个办法解决此问题,前提是还是在这个平台上!谢谢

急用!

cnzdgs 2008-04-17
  • 打赏
  • 举报
回复
只有保护模式才能访问1MB以上的内存,所以HIMEM当然也要切入到保护模式,也要有GDT。
QIANYONGMING 2008-04-17
  • 打赏
  • 举报
回复
MS-DOS启动时提示:HIMEM is testing extended memory......DONE!

我想这是检测并加载了高位内存的意思吧!

如果加载了高位内存的话,怎样发生了冲突?

不太明白这个高位内存冲突的原因?

qinxinfo 2008-04-17
  • 打赏
  • 举报
回复
你在純DOS環境下執行應該不會有問題啊, 不加加載高位內存.不然會有衝突.
QIANYONGMING 2008-04-17
  • 打赏
  • 举报
回复
谢谢各位解答!我现在做的是一款工控机,该工控机以intel 80386EX cpu为核心,以ms-dos622为平台,内存4M,数据主要放在1M以上的存储空间,因此必须用保护模式编程,但

本人对这方面不甚了解,还需请各位多多指教!

楼上的朋友说的bochs,以及Window下编程本人更是不太了解!还有待于继续学习!

本人一直在dos平台上移植程序,关键的问题是:测试参考书上的最近本的原程序,只要求从实模式进入保护模式,运行程序就会死在跳转处!郁闷中!
ttlyfast 2008-04-16
  • 打赏
  • 举报
回复
bochs
QIANYONGMING 2008-04-16
  • 打赏
  • 举报
回复
不用debug调试器,请推荐一款使用的方法?谢谢!
大熊猫侯佩 2008-04-16
  • 打赏
  • 举报
回复
不能用debug之类的调试器调试这类程序,否则必挂。
独孤过儿 2008-04-16
  • 打赏
  • 举报
回复
保护模式下的应用程序都是ring3级别的,你这个都涉及到GDT,显然需要ring0级别才行,而在windows下,除非你自己写驱动,要不然没

法获得到ring0的权限。上面兄弟告诉你用bochs,实际上是想让你用虚拟机来玩,跑一个虚拟机,就相当与一个裸机了,你可以直接写一个

kernel在上面跑,这样ring0自然也可以用了...
cnzdgs 2008-04-16
  • 打赏
  • 举报
回复
网上搜索一下“调试保护模式”,会找到很多网页都是带有bochs字样的,看起来应该可以。另外建议你还是要先苦练基本功才行,保护模式程序的难度是很高的。
相关推荐
发帖
汇编语言

2.1w+

社区成员

汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区管理员
  • 汇编语言
加入社区
帖子事件
创建了帖子
2008-04-15 06:31
社区公告
暂无公告