i download this program @ internet...
;
; bigreal.asm
;
; Programmer: David Lindauer
; Date: August 16,1995
; email address: gclind01@ulkyvx.louisville.edu
;
;
; Enable big real mode on FS,GS
;
;
.MODEL SMALL
.386P
MEMSIZE = 400000h ; Set this to MB you want to test
MEMBASE = 100000h
;---------------------------------------------------------------------
; Various symbols used to make things more readable.
;
;---------------------------------------------------------------------
NUMGDT = 2 ; Number of entries in GDT.
GDTSIZE = NUMGDT*8
;
; Selectors, RPL = 0, in GDT
;
DS386 EQU 8h ; 386 data segment selector
;---------------------------------------------------------------------
; Define ordering of segments.
;
;---------------------------------------------------------------------
DGROUP GROUP seg8086
SEG8086 SEGMENT dword USE16 public 'CODE'
SEG8086 ends
;---------------------------------------------------------------------
; Define a 1K entry stack.
;
;---------------------------------------------------------------------
.STACK 256
;---------------------------------------------------------------------
; IDT and GDT are first so they will be DWORD aligned
;
;---------------------------------------------------------------------
SEG8086 SEGMENT
;
; The constructed GDT
;
tgdt dw 0,0,0,0
db 0ffh,0ffh,0,0,0,92h,0cfh,0
;
; The value to load with the lgdt reg
;
pGDT dw GDTSIZE-1 ; Protected mode GDT register
gdtadr dd offset tGDT ; Move this out of ROM!!!!!
;
msg db "Failure attempting to init a20 line",10,13,'$'
goodmsg db "Test ok",10,13,'$'
badmsg db "Test failed",10,13,'$'
SEG8086 ends
seg8086 SEGMENT
assume cs:dgroup
bigreal proc
cld
cli ; Interrupts clear throughout
sub ebx,ebx
mov bx,cs ; Set ES=DS=CS=DGROUP
mov ds,bx
mov es,bx
;
; Fixup the GDT with our current location in memory.
;
shl ebx,4
add [gdtadr],ebx ; GDT and IDT regs must have a physical value
; Load the GDT descriptor
lgdt [fword ptr pGDT]
;
; Switch to protected mode.
;
mov ebx,CR0 ; Set protected mode
inc bx
mov CR0,ebx
;
; Load fs & gs with big segs
;
push DS386
pop fs
push DS386
pop gs
;
; Switch back to real mode
;
dec bx
mov CR0,ebx
ret
bigreal endp
;
; Routine to wait till KB controller not busy
;
kb_busy proc
xor cx,cx ; Loop 65536 times
kb_bs2:
in al,64h ; Get status
jmp $+2
jmp $+2
test al,2 ; See if busy
jz kb_busy_done ; Not busy any more
loop kb_bs2
stc
ret
kb_busy_done:
clc
ret
kb_busy endp
;
; Routine to wait till KB data buffer empty
;
kb_writewait proc
xor cx,cx ; Loop 65536 times
kb_rd2:
in al,64h ; Get port status
test al,2 ;
jz short kb_writewait_done ; Quit if buffer empty
loop kb_rd2 ; Wait a while
stc ; Error
ret
kb_writewait_done:
clc
ret
kb_writewait endp
;
; Routine to wait till KB data buffer fll
;
kb_readwait proc
xor cx,cx ; Loop 65536 times
kb_rdrd2:
in al,64h ; Get port status
test al,1 ;
jnz short kb_readwait_done ; Quit if buffer empty
loop kb_rdrd2 ; Wait a while
stc ; Error
ret
kb_readwait_done:
mov cx,32 ; Wait for controller to set data
delay:
jmp $+2
jmp $+2
loop delay ;
clc
ret
kb_readwait endp
;
; Routine to turn on A20 line
;
seta20 proc
cli ; Don't want a keypress now!
call kb_busy ; Wait while busy
jc short error ;
mov al,0d0h ; Command to get port status
out 64h,al ;
call kb_busy ; Wait while busy
jc short error
call kb_readwait ; Wait for it to put the char there
jc short error
in al,60h ; Get the data
or al,2 ; Set the A20 bit
xchg al,ah ; Data to ah
call kb_busy ; Wait while busy
jc short error
mov al,0d1h ; Command to put port status
out 64h,al ;
call kb_busy ; Wait while busy
jc short error
call kb_writewait ; Wait for buffer to empty
jc short error
mov al,ah ; Write the data
out 60h,al ;
clc ; No erros
error:
sti ; Keys allowed now
ret
seta20 endp
;
; Fill extended memory with a pattern
;
fillmegs proc
mov edi,MEMBASE
mov ecx,MEMSIZE / 4
mov eax,0ffff0000h
fmlp:
mov fs:[edi],eax
add edi,4
inc eax
loop fmlp
; mov dword ptr fs:[edi-16],0 ; put this line in to observe a failure
ret
fillmegs endp
;
; See if pattern overwrote itself
;
testmegs proc
mov edi,MEMBASE
mov ecx,MEMSIZE/4
mov eax,0ffff0000h
cmlp:
cmp fs:[edi],eax
jnz short badcmp
add edi,4
inc eax
loop cmlp
mov dx,offset goodmsg
jmp short pmsg
badcmp:
mov dx,offset badmsg
pmsg:
mov ah,9
int 21h
ret
testmegs endp
;
start:
call seta20
jc short bada20
call bigreal ; Switch FS & GS to large seg sizes
call fillmegs
call testmegs
done:
mov ah,04ch ; Back to DOS; big limits on everything.
int 21h
bada20:
mov dx,offset msg
mov ah,9
int 21h
jmp done
SEG8086 ends
end start
;***********
masm 6.11;why i always restart??please tell me ,tks......
i try to trace this program ,use debug32 it's trace to "mov cr0,ebx" then reboot......
I think the problem has something to do with the condition of the system when you execute the program. When I tried to execute it from Windows 98 MS-DOS Mode, it hung. When I tried to execute it from a Windows 98 boot disk, it also hung. In both cases, the processor was in real mode, but himem.sys had been loaded, so it had already taken over control of the A20 address line. When I created a bare Windows 98 boot disk (without a config.sys or autoexec.bat), booted from the disk, and executed the program, it returned "Test ok".
Thinking about this more, I realized that in addition to himem.sys being loaded, some OS components had been moved into the high memory area (HMA). From config.sys for the Windows 98 boot disk:
device=himem.sys /testmem:off
...
dos=high,umb
And because MEMBASE is set to the start of the HMA, the test is overwriting everything there, and the problem occurs at some point after the return to DOS.
thank you for your detail explain !!and i have another question..................
for example: i write membase:100000h (1MB)~c800000(200MB) ...if it retuend "test ok" and my question....how verify it really write 1MB~200MB??
use debug32??but it just can see ffff:ffff "value"....can you tell me??in this program ...it's write to fs:edi....can i verify "value" that 1MB~200MB??and how?
thank you .......!!maybe you don't understand my mean.....because my english very poor!!sorry........but i hope you can help me!
I'm not familiar with debug32. The code looks correct to me, so I don't see how it could fail. But if you feel a need to verify, one easy method would be to change the code so the value written to each dword is the address of the dword:
Change:
mov fs:[edi],eax
To:
mov fs:[edi],edi
And:
cmp fs:[edi],eax
To:
mov fs:[edi],edi
Then for some number of addresses spread out through the range, compare the stored value to the address and display a message based on the result. Because DOS does not use FS or GS, the segment limit should stick until the system is rebooted.
Hi,
Have you tried it from 'Safe mode Command Prompt'? You select that one from the boot menu you get by pressing F8 while windows loads. I think this one doesn't load himem.sys .
Thomas Antony
thank you Michael and Thomas..
i have a lot of question ...i am a beginner of assembly..and ask stupid question! i have some question :P
1.DS386 EQU 8h ; 386 data segment selector
; Load fs & gs with big segs
;
push DS386
pop fs
push DS386
pop gs
;
i trace this....GS=FS=0008 ,why this is 8? may i change DS386= 0???
2.what different big real mode and protected mode ??
3.mov fs:[edi],eax ..if edi=00100000h ! it's mean 1MB liner address @ memory??
and if i want written 256MB, this address @ memory...
mov edi,10000000h
mov fs:[edi],eax
fs:10000000h =256MB @ liner address??
thank your answer!!!
The first descriptor in the GTD must be a "null descriptor". Each descriptor is 8 bytes in length, so the second descriptor starts at offset 8.
; The constructed GDT
;
tgdt dw 0,0,0,0 ; null decriptor
db 0ffh,0ffh,0,0,0,92h,0cfh,0
The purpose of the null descriptor is to guarantee that a reference to an unused segment register will generate an exception.
SEGMENT_DESCRIPTOR struc
seg_limit_low dw 0ffffh
seg_base_low dw 0
seg_base_mid db 0
seg_access_rights db 92h
seg_extra_byte db 0cfh
seg_base_high db 0
SEGMENT_DESCRIPTOR ends
The definitons of some of the bits will be different for
a system or application code segment.
Access rights byte:
92h = 10010010b
||||||||
|||||||+-- 0 = not accessed
||||||+--- 1 = write enable
|||||+---- 0 = not expand down
||||+----- 0 = data segment
|||+------ 1 = application segment (not system segment)
|++------- 00 = privilege level 0
+--------- 1 = segment present in memory
Extra byte:
0cfh = 11001111b
||||||||
||||++++-- 1111 = limit high (bits 19-16)
|||+------ 0 = not availabe for use by system
||+------- must be zero
|+-------- 1 = default operand size is 32 bits
+--------- 1 = page granularity (limit scaled by 4096)
The primary differences between big real mode and protected are the differences between real and protected mode. The primary difference between normal real mode and big real mode is that for big real mode the segment limit has been forced to a larger value that the default 0ffffh.
The linear address is the segment base address plus the offset address. For a segment base of zero, the linear address equals the offset address.
HI. I have try the big real mode. With big real mode you will not confuse with the interupt. You can still use interupt.
Some function is cannot be done from protected mode(difficult to code), like set video function and disk access function, thats why I think big real mode is usefull.
thank you very much Michael and Farabi...i try to develop ram test tool (like Ram Stress Test;memtest+86)..but i'm beginner ! so i want to know "Value" @ memory address.i think it's very long that develop software.it will have many question....if i have difficult problem, may i earnestly request your help??
this forum,and you help me to very much .....and you can understand my english, i'm so surprised!!TKS.
Quote from: guesehsaio on April 04, 2005, 05:06:56 PM
thank you very much Michael and Farabi...i try to develop ram test tool (like Ram Stress Test;memtest+86)..but i'm beginner ! so i want to know "Value" @ memory address.i think it's very long that develop software.it will have many question....if i have difficult problem, may i earnestly request your help??
this forum,and you help me to very much .....and you can understand my english, i'm so surprised!!TKS.
Hi. If you dont know, asking about protected mode is an advance question. If you want the software development fast, I suggest you to use the function available. www.google.com is agreat aid.
;
; Load fs & gs with big segs
;
push DS386
pop fs
push DS386
pop gs
push ds386
pop es
;**************************
MEMSIZE EQU 08000000h ; Set this to MB you want to test
MEMBASE EQU 0100000h
fillmegs proc near
CALL CACHE_OFF
push ecx
mov edi,MEMBASE
mov eax,0AAAAAAAAh
mov ecx,MEMSIZE /4
loop3: mov es:[edi],eax
cmp es:[edi],eax
jnz badcmp
add edi,4
loop loop3
;******************************
i use "ES" to displace "FS" ! But i really filled 1MB~256MB??
i try to use "debug32" trace this program ! discover
0000:00100000~00100FF00 => i filled "value" ,but 0000:00100FF00 above isn't my "value"
0001:00100000~00100FF00=> i filled "Value" ,but 0000:00100FF00 above isn't my "value"
why?? i filled just about "63K Byte"???
In your original post the test code was in a 16-bit segment, and AFAIK in a 16-bit segment the loop instruction uses CX for the loop counter. You could try substituting LOOPD for LOOP to force the use of ECX for the loop counter.
[ You could try substituting LOOPD for LOOP to force the use of ECX for the loop counter.
thanks....that's ok....!!
loopd solved my question!thanks.......