DOS 4G big real Mode Demo code。
刚学习的同学,有些还不会,我这里贴点C和asm的代码。只供参考。这是C的/********************************************************************
* File: DOS4G.H *
* Compile with BC 3.1 ( Editor: Tab size = 4 ) *
* *
* ========================Title=============================== *
* 这个函数是让系统进入DOS 4G模式 *
* 程序参考了:陈家琪《DOS实方式下直接访问4GB》 *
* *
* 使用: openA20(); set4gb(); *
* *
* ===========================History========================== *
* author: bini *
* date: 2004-11-30Frist version. *
********************************************************************/
#include <conio.h>
#pragma inline
/***********************************************
* 两个GDT,第一个为系统使用,不管,默认为0 *
* 第二个为一个数据段,没有代码段。 *
***********************************************/
unsigned long GDT_def[ ]={0,0, /*系统使用*/
0x0000FFFF, /* hi16bit( 0~15 ) is base low=0,
low16bit( 0~15 ) is limit low=0xFFFF
*/
0x008F9200};/* 最低字节为 base( bit 16~23 )
最高字节为 base( bit 24~31 )
属性Attrib = 0x8F92
属性位Hibyte低四位为
Limit( 16~19 )=F
属性位Hibyte bit7 为粒度
(值1=4KB粒度)
8F & 0x80 = 1
属性位Lowbyte低四位为段类型,值=2
表示为可读/写段
属性位Hibyte高四位=9,bit3=1表示:
描述符对地址转换是有效的。
bit0=1表示为:
系统段描述符。而不是门描述符。
*/
/****************************************
* GDTR寄存器, 48bit=6bytes *
* +-------------------------------+ *
* | 32bit基地址 |16bit界限| *
* +-------------------------------+ *
****************************************/
unsigned char GDT_Addr={0};
/****************
* 打开A20门 *
****************/
void openA20(void)
{
asm{
pusha
in al, 92H
or al, 0x02
out 0x92, al
out 0xed, al
popa
}
}
/***********************************************
* 函数功能:进入DOS4G *
* ==================== *
* *
* GDT描述符界限计算方式:描述符个数*8-1 *
* 如: *
* mov word ptr GDT_Addr, (2*8-1); *
* 表示为 2个GTD *
* *
* 选择子为所在描述符内的字节偏移。 *
* *
***********************************************/
void set4gb(void)
{
asm{
cli
/****************************************
* GDTR寄存器 *
* +-------------------------------+ *
* | 32bit基地址 |16bit界限| *
* +-------------------------------+ *
*****************************************/
/*********************
* 得出段界限 *
*********************/
mov word ptr GDT_Addr, (2*8-1);
/********************************************
* 计算GDT表的32位基地址,存入GDTR *
********************************************/
mov eax, ds
shl eax, 4
xor ebx, ebx
mov bx, offset GDT_def
add eax, ebx
mov dword ptr GDT_Addr, eax
lgdt fword ptr GDT_Addr
/********************
* 选择子偏移 *
********************/
mov bx, 8
mov eax, cr0
or al, 1
/**********************
* 进入保护模式 *
**********************/
mov cr0, eax
jmp pMod
}
pMod: asm{
/************************************************************
* 让fs与gs加载选择子,使其能访问 0xFFFFF * 4K (4GB) 空间 *
************************************************************/
mov fs, bx
mov gs, bx
and al, 0x0FE
/******************
* 进入实模式 *
******************/
mov cr0, eax
jmp rMod
}
rMod: asm{
/* ******************************************************************
* 退出,fs、gs清0,访问系统内存可用: gs *
********************************************************************/
mov ax, 0
mov fs, ax
mov gs, ax
sti
}
}这是asm的;/********************************************************************
;* File: DOS4G.asm *
;* Compile with masm ( Editor: Tab size = 4 ) *
;* *
;* ========================Title=============================== *
;* 这个demo是让系统进入DOS 4G模式,进行数据访问 *
;* *
;* ===========================History========================== *
;* author: bini *
;* date: 2008-10-08Frist version. *
;********************************************************************/
.model small
.586p
DSEGSEGMENT USE16 ;16位数据段
DESC STRUC
LimitL DW 0 ;段界限(BIT0-15)
BaseL DW 0 ;段基地址(BIT0-15)
BaseM DB 0 ;段基地址(BIT16-23)
Attributes DB 0 ;段属性
LimitH DB 0 ;段界限(BIT16-19)(含段属性的高4位)
BaseH DB 0 ;段基地址(BIT24-31)
DESC ENDS
PDesc STRUC
Limit DW 0 ;16位界限
Base DD 0 ;32位基地址
PDesc ENDS
GDT_def Label Fword
Null_Desc DESC < 0h,0h, 00h, 00h, 000h, 0>
Data_Desc DESC < 0FFFFh,0h, 00h, 92h, 08Fh, 0>
GDT_Addr PDesc <$-GDT_def-1, >
DSEG ENDS ;数据段定义结束
CSEG SEGMENT USE16 ;16位代码段
ASSUMECS:CSEG,DS:DSEG
.Startup
call Set4gb
;
; fs, gs即能访问4GB空间
; write your code in here.
;
.exit
Set4gb PROC NEAR
in al, 92h
or al, 002
out 092h, al
out 0edh, al
cli
; mov word ptr GDT_Addr, (2*8-1);
mov eax, ds
shl eax, 4
xor ebx, ebx
mov bx, offset GDT_def
add eax, ebx
mov dword ptr GDT_Addr.Base, eax
lgdt fword ptr GDT_Addr
mov bx, 8
mov eax, cr0
or al, 1
mov cr0, eax
jmp pMod
pMod:
mov fs, bx
mov gs, bx
and al, 0FEh
mov cr0, eax
jmp rMod
rMod:
mov ax, 0
mov fs, ax
mov gs, ax
; 在2M的位置测试写一下数据
mov esi, 200000h
mov dword ptr fs:, 055aa55aah
; 用RU去看看200000h的位置是否是此数据....
sti
ret
Set4gbENDP
CSEG ENDS ;代码段定义结束
end 学习,学习了,楼主辛苦了 有一个问题,我用BC31为什么没法编译32位的汇编指令呢?要设置哪儿吗? option->compiler->advanced code generation中的instruction set选 80386
option->compiler->code generation中的option选中, compile via assembler
[ 本帖最后由 happybasic 于 2008-12-20 15:41 编辑 ] 太强了 学习 只是更新的比较慢哈 谢谢了 Undefined symbol: < Null_Desc DESC < 0h,0h, 00h, 00h, 000h, 0>
Data_Desc DESC < 0FFFFh,0h, 00h, 92h, 08Fh, 0>
GDT_Addr PDesc <$-GDT_def-1, >
替换如下,
Null_Desc DESC < 0h,0h, 00h, 00h, 000h, 0>
Data_Desc DESC <0FFFFh,0h, 00h, 92h, 08Fh, 0>
GDT_Addr PDesc <$-GDT_def-1, >
这样你就能编译通过并且可以运行 替换了就OK.Thanks 这个是Discuz的Bug.有空翻出来改改看。发代码<>符号被Discuz 在[ code ]里变成HTML的东西. 原帖由 happybasic 于 2008-12-18 17:11 发表 http://www.ufoit.com/bbs/images/common/back.gif
option->compiler->advanced code generation中的instruction set选 80386
option->compiler->code generation中的option选中, compile via assembler
作了上述设置之后还是不行,编译的时候提示: cannot find executable: TASM. 我换了几个版本的TASM还是没用,除非拿掉含有32位寄存器的那些code才行。这个是什么原因,请各位大侠多多指教 原帖由 A_jack 于 2010-2-26 10:47 发表 http://www.ufoit.com/bbs/images/common/back.gif
作了上述设置之后还是不行,编译的时候提示: cannot find executable: TASM. 我换了几个版本的TASM还是没用,除非拿掉含有32位寄存器的那些code才行。这个是什么原因,请各位大侠多多指教 ...
我也是相同的问题,请问哪位有解,谢了! option->compiler->Transfer 设置TASM的路径,就不会提示找不到TASM;
还要把TASMMSG.exe拷贝到源代码(工程目录),就可以编译完成了。
页:
[1]