ajee
驱动牛犊
驱动牛犊
  • 注册日期2002-06-13
  • 最后登录2004-11-05
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:1588回复:8

问问汇编问题可以吗?关于real mode下怎么访问4g内存

楼主#
更多 发布于:2002-11-11 21:18
关于real mode下访问4g内存的问题
各位大侠,我看了相关的一些资料,根据一个网站上的介绍:
http://www.powerba.com/develop/c&c++/article/20001205006.htm
做了一些修改,得到自己的汇编代码如下:(在linux as86下,16进制立即数寻址为#$XXX,其中$是十六进制的前缀,#表示立即数寻址)
!void set4G()
export _set4G
_set4G:
wait1: ;openA20 begin
in al,#$64
and al,#$02
cmp al,#$1
je wait1

mov al,#$0d1
out #$64,al

wait2:
in al,#$64
and al,#$02
cmp al,#$1
je wait2

mov al,#$0df
out #$60,al

wait3:
in al,#$64
and al,#$02
cmp al,#$1
je wait3

mov al,#$0ff
out #$64,al  ;openA20 end

; set begin
push ebx
push si
cli
mov si,#$0  
mov word ptr GDT_Addr[si],#$2*8-1
mov ax, ds
and eax,#$0000FFFF
shl eax,#$4
xor ebx, ebx
mov ebx, GDT_def
add eax,ebx
mov si,#$2
mov dword ptr GDT_Addr[si], eax

call printA  ;输出字符A,debug用

LGDT fword ptr GDT_Addr

call printB

mov eax, cr0
or eax,#$1
mov cr0,eax

call printC

jmp flush1


flush1:
mov bx,#$8  ;selector
mov fs,bx

mov gs,bx

and al,#$0fe

mov cr0,eax

jmp flush2

flush2:
mov ax,#$0
mov fs,ax
mov gs,ax
sti
pop si
pop ebx   ;set end
ret
数据段有
GDT_def: dd $0,$0,$0000FFFF,$008F9200 ;size =2*8 bytes
GDT_Addr: db $0,$0,$0,$0,$0,$0  ;size =6 bytes

在运行时,输出A和B之后死掉,不知道哪里出错了?
菜鸟一个
pjf
pjf
驱动中牛
驱动中牛
  • 注册日期2001-07-08
  • 最后登录2006-10-23
  • 粉丝0
  • 关注0
  • 积分42分
  • 威望4点
  • 贡献值0点
  • 好评度4点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2002-11-11 21:40
关于real mode下访问4g内存的问题
各位大侠,我看了相关的一些资料,根据一个网站上的介绍:
http://www.powerba.com/develop/c&c++/article/20001205006.htm
做了一些修改,得到自己的汇编代码如下:(在linux as86下,16进制立即数寻址为#$XXX,其中$是十六进制的前缀,#表示立即数寻址)
!void set4G()
export _set4G
_set4G:
wait1: ;openA20 begin
in al,#$64
and al,#$02
cmp al,#$1
je wait1

mov al,#$0d1
out #$64,al

wait2:
in al,#$64
and al,#$02
cmp al,#$1
je wait2

mov al,#$0df
out #$60,al

wait3:
in al,#$64
and al,#$02
cmp al,#$1
je wait3

mov al,#$0ff
out #$64,al  ;openA20 end

; set begin
push ebx
push si
cli
mov si,#$0  
mov word ptr GDT_Addr[si],#$2*8-1
mov ax, ds
and eax,#$0000FFFF
shl eax,#$4
xor ebx, ebx
mov ebx, GDT_def
add eax,ebx
mov si,#$2
mov dword ptr GDT_Addr[si], eax

call printA  ;输出字符A,debug用

LGDT fword ptr GDT_Addr

call printB

mov eax, cr0
or eax,#$1
mov cr0,eax

call printC

jmp flush1


flush1:
mov bx,#$8  ;selector
mov fs,bx

mov gs,bx

and al,#$0fe

mov cr0,eax

jmp flush2

flush2:
mov ax,#$0
mov fs,ax
mov gs,ax
sti
pop si
pop ebx   ;set end
ret
数据段有
GDT_def: dd $0,$0,$0000FFFF,$008F9200 ;size =2*8 bytes
GDT_Addr: db $0,$0,$0,$0,$0,$0  ;size =6 bytes

在运行时,输出A和B之后死掉,不知道哪里出错了?

删掉call printC先,放在flush2: 后。

将flush1与flush2间的机器码贴出来
ajee
驱动牛犊
驱动牛犊
  • 注册日期2002-06-13
  • 最后登录2004-11-05
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2002-11-12 09:43
你看出是什么毛病了吗?我觉得是当我mov cr0,eax 跳入pm时出错了,不知道是不是程序的问题。
还有64和60端口是不是表示可编程控制器,我没有找到它的资料
菜鸟一个
pjf
pjf
驱动中牛
驱动中牛
  • 注册日期2001-07-08
  • 最后登录2006-10-23
  • 粉丝0
  • 关注0
  • 积分42分
  • 威望4点
  • 贡献值0点
  • 好评度4点
  • 原创分0分
  • 专家分0分
地板#
发布于:2002-11-12 09:51
你看出是什么毛病了吗?我觉得是当我mov cr0,eax 跳入pm时出错了,不知道是不是程序的问题。
还有64和60端口是不是表示可编程控制器,我没有找到它的资料

你改了没,有错再说了,先看C出来没
可编程控制器?它是键盘8042CPU引出的接口,该段代码用以开启A20地址线
ajee
驱动牛犊
驱动牛犊
  • 注册日期2002-06-13
  • 最后登录2004-11-05
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2002-11-12 10:23
Thank you in advance.Now my workstation has no chinese inputs,so I say in english.
I move call printC to everywhere in the block:

flush2:
mov ax,#$0
mov fs,ax
mov gs,ax
sti

But it still fails.As I see,this code can\'t go there for it has been blocked in \"mov cr0,eax \".


菜鸟一个
pjf
pjf
驱动中牛
驱动中牛
  • 注册日期2001-07-08
  • 最后登录2006-10-23
  • 粉丝0
  • 关注0
  • 积分42分
  • 威望4点
  • 贡献值0点
  • 好评度4点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2002-11-12 10:55
Thank you in advance.Now my workstation has no chinese inputs,so I say in english.
I move call printC to everywhere in the block:

flush2:
mov ax,#$0
mov fs,ax
mov gs,ax
sti

But it still fails.As I see,this code can\'t go there for it has been blocked in \"mov cr0,eax \".


 

非也。
首先你的运行环境?
还有你的汇编器将你的代码译为16bit还是32bit?
问题必然二者之一。

手头上没有你的汇编器,用masm在DOS改写了一段,运行没问题:
.8086
.model small,c
.data
GDT_def dd 0,0,0000FFFFh,008F9200h;size =2*8 bytes
GDT_Addr db 0,0,0,0,0,0 ;size =6 bytes

.code
start:
mov ax,@data
mov ds,ax
wait1: ;openA20 begin
in al,64h
and al,02
cmp al,1
je wait1

mov al,0d1h
out 64h,al

wait2:
in al,64h
and al,02
cmp al,1
je wait2

mov al,0dfh
out 60h,al

wait3:
in al,64h
and al,02
cmp al,1
je wait3

mov al,0ffh
out 64h,al ;openA20 end

cli
db 66h
MOV BX,DS;MOV ECX,DS
MOV CL,4
db 66h
SHL BX,CL ;SHL EBX,CL
MOV word ptr GDT_Addr[0],(2*8-1)
db 66h
XOR AX,AX ;XOR EAX,EAX
MOV AX,offset GDT_def
db 66h
ADD AX,CX ;ADD EAX,ECX
MOV word ptr GDT_Addr[2], AX
db 66h
db 0c1h,0e8h,10h ;SHR EAX,16
MOV word ptr GDT_Addr[4],AX
MOV BX,offset GDT_Addr
db 0fh,01h,17h

mov DX,8
db 66h,0Fh,20h,0C0h ; MOV EAX,CR0
db 66h
MOV BX,AX ; MOV EBX,EAX
OR AX,1
db 66h,0Fh,22h,0C0h
;MOV CRO,EAX

jmp flush1

flush1:
db 66h
MOV AX,BX ;MOV EAX,EBX
db 8Eh,0E2h ;MOV FS,DX
db 66h,0Fh,22h,0C0h ;MOV CRO,EAX

jmp flush2

flush2:
sti

mov ax,4c00h
int 21h
.stack
end start
ajee
驱动牛犊
驱动牛犊
  • 注册日期2002-06-13
  • 最后登录2004-11-05
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2002-11-12 19:29
你这段代码确实可以运行了。谢谢
不过有个疑问,在这种情况下寄存器都是16位的ax等,而不是32位的,那我要访问高地址的时候怎么填入32位的地址阿?
所以我想用386下的指令改写你的例子,但是还是出现了以前那个问题。例子如下(MASM)

.model small
data segment
GDT_def dd 0,0,0000FFFFh,008F9200h
  GDT_Addr db 0,0,0,0,0,0
data ends
code segment
main proc far
assume cs:code, ds:data
.386p
start:
push ds
mov ax,data
mov ds,ax

call openA20
call set4g
pop ds
mov ax, 4c00h
int 21h
ret
main endp

openA20 proc near
wait1:
in al,64h
and al,02h
cmp al,1
je wait1

mov al,0d1h
out 64h,al

wait2:
in al,64h
and al,02h
cmp al,1
je wait2

mov al,0dfh
out 60h,al

wait3:
in al,64h
and al,02h
cmp al,1
je wait3

mov al,0ffh
out 64h,al
ret
openA20 endp

set4G proc near
cli
mov word ptr GDT_Addr[0], 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[2], eax
lgdt fword ptr GDT_Addr
mov bx, 8
mov eax, cr0
call printA
or al,1
db 66h,0Fh,22h,0C0h ; mov cr0,eax
call printB
jmp flush1


flush1:
mov fs,bx

mov gs,bx

and al,0feh

mov cr0,eax

jmp flush2

flush2:
mov ax, 0
mov fs,ax
mov gs,ax
sti
ret
set4G endp

printA proc near
mov al,\'A\'
mov ah,0eh
int 10h
ret
printA endp
printB proc near
mov al,\'B\'
mov ah,0eh
int 10h
ret
printB endp
code ends
end start

 输出了A,B没有出来,看来还是哪里环境设置有问题吧
菜鸟一个
pjf
pjf
驱动中牛
驱动中牛
  • 注册日期2001-07-08
  • 最后登录2006-10-23
  • 粉丝0
  • 关注0
  • 积分42分
  • 威望4点
  • 贡献值0点
  • 好评度4点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2002-11-12 20:55
不过有个疑问,在这种情况下寄存器都是16位的ax等,而不是32位的
---------------------------------------------------------------------
funny.注释中的“XOR EAX,EAX”这些语句你没看到吗?
db 66h
db 0c1h,0e8h,10h
就是SHR EAX,16,写成机器码而已。


那我要访问高地址的时候怎么填入32位的地址阿?
----------------------------------------------------------------------
一样。用mov ax,fs:[ebx]等等,不要说写成
db 67h
db 64h
mov ax,[bp+di]
你就不认得它是mov ax,fs:[ebx]了。


所以我想用386下的指令改写你的例子,但是还是出现了以前那个问题。
-----------------------------------------------------------------------
问题是明显的,基础不必再提,你看看改过的一段吧,正确运行:
.386p
data segment use16
GDT_def dd 0,0,0000FFFFh,008F9200h
GDT_Addr db 0,0,0,0,0,0
data ends
code segment use16
main proc far
assume cs:code, ds:data

start:

push ds
mov ax,data
mov ds,ax

call openA20
call set4g
pop ds
mov ax, 4c00h
int 21h
ret
main endp

openA20 proc near
wait1:
in al,64h
and al,02h
cmp al,1
je wait1

mov al,0d1h
out 64h,al

wait2:
in al,64h
and al,02h
cmp al,1
je wait2

mov al,0dfh
out 60h,al

wait3:
in al,64h
and al,02h
cmp al,1
je wait3

mov al,0ffh
out 64h,al
ret
openA20 endp

set4G proc near
cli
mov word ptr GDT_Addr[0], 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[2], eax
call printA
lgdt fword ptr GDT_Addr
mov bx, 8
mov eax, cr0
or al,1
mov cr0,eax
jmp flush1

flush1:
mov fs,bx
mov gs,bx
and al,0feh
mov cr0,eax

jmp flush2

flush2:
call printB
mov ax, 0
mov fs,ax
mov gs,ax
sti
ret
set4G endp

printA proc near
mov al,\'A\'
mov ah,0eh
int 10h
ret
printA endp
printB proc near
mov al,\'B\'
mov ah,0eh
int 10h
ret
printB endp
code ends

end start
你比较它们的机器编码自然明白问题。
ajee
驱动牛犊
驱动牛犊
  • 注册日期2002-06-13
  • 最后登录2004-11-05
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2002-11-12 21:20
ok谢谢这位老大,真是牛,ooo,太感激了
菜鸟一个
游客

返回顶部