阅读:1588回复:8
问问汇编问题可以吗?关于real mode下怎么访问4g内存
关于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之后死掉,不知道哪里出错了? |
|
|
沙发#
发布于:2002-11-11 21:40
关于real mode下访问4g内存的问题 删掉call printC先,放在flush2: 后。 将flush1与flush2间的机器码贴出来 |
|
板凳#
发布于:2002-11-12 09:43
你看出是什么毛病了吗?我觉得是当我mov cr0,eax 跳入pm时出错了,不知道是不是程序的问题。
还有64和60端口是不是表示可编程控制器,我没有找到它的资料 |
|
|
地板#
发布于:2002-11-12 09:51
你看出是什么毛病了吗?我觉得是当我mov cr0,eax 跳入pm时出错了,不知道是不是程序的问题。 你改了没,有错再说了,先看C出来没 可编程控制器?它是键盘8042CPU引出的接口,该段代码用以开启A20地址线 |
|
地下室#
发布于: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 \". |
|
|
5楼#
发布于:2002-11-12 10:55
Thank you in advance.Now my workstation has no chinese inputs,so I say in english. 非也。 首先你的运行环境? 还有你的汇编器将你的代码译为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 |
|
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没有出来,看来还是哪里环境设置有问题吧 |
|
|
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 你比较它们的机器编码自然明白问题。 |
|
8楼#
发布于:2002-11-12 21:20
ok谢谢这位老大,真是牛,ooo,太感激了
|
|
|