home *** CD-ROM | disk | FTP | other *** search
- page 82,120
- title MemTest - Test Main & Extended Memory
- .MODEL SMALL
- .386p
-
- ; Gene Czarcinski, 4 Sep 89
- ;
- ; This program is designed to test main and extended (not expanded)
- ; (ram) memory on a 386 or 386SX. It was developed on a Wave Mate
- ; Bullet-386SX and some of the ports or hardware values may differ on
- ; different systems. Because it was developed on a 386, some of the
- ; specific characteristics of a 386 are used (however, it should be
- ; possible to convert this program to a 286 with some effort).
- ;
- ; NOTE that this program operates in REAL mode to test main memory
- ; and in 386 PROTECTED mode to test extended memory.
- ;
- ; This program owes some of its features and code to some other
- ; programs and some books (with programs):
- ; - RAMHAM by Clifford A. McCullough
- ; - 80386 A Programming and Design Handbook, 2nd Ed.
- ; by Penn Brumm and Don Brumm
- ; - Dr. Dobb's Toolbook of 80286/80386 Programming
- ; Edited by Phillip Robinson
- ; Finding enough CORRECT information to write this program was a bit
- ; of a problem - much of it was trial and error (plus the usual set
- ; of coding/typing errors -- interesting results when a segment reg
- ; is incorrect in protected mode).
- ;
- ; Writing this program was motivated by some memory errors on my
- ; Wave Mate system board. The bad memory caused a Parity Error
- ; but not until after the system was up (it did not fail the BIOS
- ; memory test). The error turned out to be a bad 1meg chip which
- ; had a bad section of memory (1 chip, 1 bit, 256k bits). This program
- ; found the error and when I replaced the chip, I had no more problems.
- ; I hope this may be of use to others.
- ;
- ; Note that error handling is VERY PRIMATIVE - the objective was to
- ; find the memory errors in the extended memory, not to create a full
- ; environment for the 386 (although some interrupt handling, etc. is
- ; necessary). This is NOT a turn-key program and some "fiddling" will
- ; be necessary to get it to work on other systems.
- ;
- ; The NMI Parity Error Disable/Enable value may differ. The port
- ; and values (bit) which indicate a Parity Error may (will) differ -
- ; these were quessed at since they were added AFTER the problem was
- ; fixed.
- ;
- ; Some simple run-time options:
- ;
- ; -f .. fast mode, very short display pause if error
- ; -x .. skip check for parity error
- ; -a .. 20 cycles of main memory checking
- ; -b .. 100 cycles of main memory checking
- ; -c .. 20 cycles of extended memory checking
- ; -d .. 100 cycles of extended memory checking
- ; default is 10 cycles each
- ;
- ; Note that errors or program completion cause the program to
- ; hang in a spin-loop which will require a RESET or the Big-Red-
- ; Switch power cycle to "terminate" (this was simple) so that messages
- ; are left on the video screen.
-
- ; Equates
-
- Line00 equ 0 ; Video Ram Displacements
- Line01 equ 160
- Line02 equ 160*2
- Line03 equ 160*3
- Line04 equ 160*4
- Line05 equ 160*5
- Line06 equ 160*6
- Line07 equ 160*7
- Line08 equ 160*8
- Line09 equ 160*9
- Line10 equ 160*10
- Line11 equ 160*11
- Line12 equ 160*12
- Line13 equ 160*13
- Line14 equ 160*14
- Line15 equ 160*15
- Line16 equ 160*16
- Line17 equ 160*17
- Line18 equ 160*18
- Line19 equ 160*19
- Line20 equ 160*20
- Line21 equ 160*21
- Line22 equ 160*22
- Line23 equ 160*23
- Line24 equ 160*24
- INTa01 equ 021h ; 8259 Controller #1
- INTa02 equ 0A1h ; 8259 Controller #2
-
- Port_a equ 060h ; 8042 Port A
- Port_b equ 061h ; 8042 Port B
- Port_c equ 062h ; 8042 Port C
- Port_Status equ 064h ; 8042 Status Port
-
- Port_Par equ 061h ; on WaveMate, others use 062h
- Bits_Par equ 080h ; on WaveMate 062h, other use 0C0h on 62h
-
- NMIPort equ 070h ; to disable/enable parity checking
- Port_cmos equ 070h ;
-
- bit20_disable equ 11011101b ; 8042 function code to degate A20
- bit20_enable equ 11011111b ; 8042 function code to GATE A20
- ; to run protected on AT, need to enable bit20 so 386 controls the
- ; address line.
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Macros and Structures ;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- ; Convert 8086 segment register value to a linear address
-
- segadr macro segr
- sub eax,eax ; clear reg
- mov AX,&segr ; get the segment reg
- shl EAX,4 ; convert to a linear addr
- endm
-
- ; Convert an 8086 segment to linear addr in a segment descriptor
-
- segcvt macro segr,segm
- segadr segr
- mov segm&.base_l,AX ; get base of data
- shr EAX,8 ; to AH
- mov segm&.base_m,AH ; and set mid-range byte
- endm
-
- ; Display Message
-
- Vtype macro msg,len,line
- mov si,offset msg ; addr of msg
- mov cx,len ; length of message
- mov di,line ; offset into screen
- call Video_Output
- endm
-
- ; Define Descriptor Structure
-
- desc struc
- limit dw 0 ; offset to last byte
- base_l dw 0 ; low 16 bits of base addr
- base_m db 0 ; bits 16-23 of base addr
- access db 0 ; access privledges
- gran db 0 ; Granularity and limit
- base_h db 0 ; bits 24-31 of base addr
- desc ends
-
- ; Similar to a descriptor, describe the GATE control block
-
- gate struc
- addr_l dw 0 ; Destinations's offset 0...15
- select dw 0 ; Destinations's Segment Selector
- db 0
- gate_t db 8Eh ; type, DPL
- addr_h dw 0 ; offset 16...31
- gate ends
-
- ; Describe the stack of the level 0 interrrupt handler.
-
- stkdef struc
- oldip dw 0 ; 0..15 of EIP
- dw 0
- oldcs dw 0 ; CS
- dw 0
- oldfl dw 0 ; 0..15 of EFLAGS
- dw 0
- oldsp dw 0 ; 0..15 of SP
- dw 0
- oldss dw 0 ; SP
- dw 0
- oldes dw 0 ; ES
- dw 0
- oldds dw 0 ; DS
- dw 0
- oldfs dw 0 ; FS
- dw 0
- oldgs dw 0 ; GS
- dw 0
- stkdef ends
-
-
- .CODE
- assume cs:_text, ds:_text, es:_text, ss:_text
-
- org 80h
- command label byte ; tail of DOS command line
-
- org 100h ; this is a COM file
- Start: jmp Main
-
- ALIGN 4
- stack dw 800h dup(0)
- stacke dw 0,0
-
- dtsize dw 0
- dtload dd 0
- dsaddr dd 0
-
- Vram dw 0b800h ; real seg of video ram
-
- work dw 0,0,0,0
-
- Cycle dw 0 ; Memory Test Cycles
- CycleMm dw 10 ; Max Cycles for a pass Main
- CycleEm dw 10 ; Max Cycles for a pass Extended
- Errors dw 0 ; number of errors which occured
- LoopCnt dw 0
- Pause_Cnt dw 20 ; Error Pause Loop Count
- Flag_CheckParity db 1 ;
-
-
- ALIGN 4
- MemExtnd label DWORD
- MemOff dw 0 ; Current Offset
- MemSeg dw 0 ; Current Segment
-
- lastPat dw 0
-
- Mem_Val db 0
- Mem_Pat db 0
- Mem_Par db 0,0
-
- Msize dw 0 ; Main memory size
- Esize dw 0 ; Extended memory size
-
- Main_S dw 0 ; Start for main memory
- Main_L dw 0 ; Limit for main memory
-
- Extnd_Sw label WORD
- Extnd_S dd 100000h ; Extended Memory Start (normal 1M or 100000h)
- Extnd_Lw label WORD
- Extnd_L dd 0 ; Extended Memory Limit
-
- savecs dw 0
- savess dw 0
- savesp dw 0
- i8259_1 db 0 ; save int status
- i8259_2 db 0 ; save int status
-
-
- ; Memory Test Patterns
- pattern db 10110010b ;par = e, B2
- db 11011001b ;par = o, D9
- db 01101100b ;par = e, 6C
- db 10110110b ;par = o, B6
- db 01011011b ;par = o, 5B
- db 00101101b ;par = e, 2D
- db 10010110b ;par = e, 96
- db 11001011b ;par = o, CB
- db 01100101b ;par = e, 65
- pattern_len equ $-pattern-1
-
- msgd1 db 'Main Memory Test Done'
- msgd1L equ $-msgd1
- msgd2 db 'Extended Memory Test Done'
- msgd2L equ $-msgd2
- msgd2o equ 80
- msgd3 db 'All Testing Complete'
- msgd3L equ $-msgd3
-
- Msg1 db 'MemTest (09/04/89) Main='
- Msg1a db 'xxxxxK/'
- Msg1ax db 'xxxx, Extended='
- Msg1b db 'xxxxxK/'
- Msg1bx db 'xxxx -f='
- Msg1c db ' -x='
- Msg1d db ' '
- Msg1Len equ $-Msg1
- Msg2 db ' *** To Terminate: Reset or BRS -- Re-Boot the System ***'
- Msg2Len equ $-Msg2
- MsgTst db ' Test'
- MsgTstL equ $-MsgTst
- Msg3 db 'Write Main Segment='
- Msg3ao equ ($-Msg3)*2
- Msg3a db 'xxxx:0000'
- Msg3Len equ $-Msg3
- Msg3Leno equ ($-Msg3+4)*2
- Msg4 db 'Write Extended Segment='
- Msg4ao equ ($-Msg4)*2
- Msg4a db 'xxxx:'
- Msg4b db 'xxxx'
- Msg4Len equ $-Msg4
- Msg4Leno equ ($-Msg4+4)*2
- Msg5 db '** Error: Address='
- Msg5a db 'xxxx:'
- Msg5b db 'xxxx Pattern:'
- Msg5c db 'xx, Memory:'
- Msg5d db 'xx, Parity:'
- Msg5e db 'xx'
- msg5Len equ $-Msg5
- Msg7 db ' Main Memory Test Segment Start='
- Msg7a db 'xxxx Limit='
- Msg7b db 'xxxx Max Cycles='
- Msg7d db 'xxxxx'
- Msg7Len equ $-Msg7
- Msg8 db 'Extended Memory Test Segment Start='
- Msg8a db '0010:'
- Msg8a2 db '0000 Limit='
- Msg8b db 'xxxx:'
- Msg8c db 'xxxx Max Cycles='
- Msg8d db 'xxxxx'
- Msg8Len equ $-Msg8
- Msg9 db 'Cycle='
- Msg9ao equ ($-Msg9)*2
- Msg9a db 'xxxxx, Errors='
- Msg9bo equ ($-Msg9)*2
- Msg9b db 'xxxxx'
- Msg9Len equ $-Msg9
-
- Emsg3 db 'Address Line A20 failed to gate open'
- Emsg3L equ $-Emsg3
-
-
-
-
- ; 386 Protected Mode Tables, etc.
-
- ; Define the Global Descriptor Table (GDT)
-
- ALIGN 8
- gdt_def LABEL word
- d_gdt desc <> ; first one is a dummy
- d_cs desc <0ffffh,0,0,10011010b,00001111b,0> ; Code
- s_cs equ d_cs-gdt_def
- d_ds desc <0ffffh,0,0,10010010b,00001111b,0> ; Data
- s_ds equ d_ds-gdt_def
- d_ss desc <0,0,0,10010110b,00000000b,0> ; Stack
- s_ss equ d_ss-gdt_def
- d_crt desc <0fffh,0,0,10010010b,00001111b,0> ; CRT
- s_crt equ d_crt-gdt_def
- d_mem desc <0fffh,0,0,10010010b,10000000b,0> ; To ref hi memory
- s_mem equ d_mem-gdt_def
- gdt_size equ $-gdt_def
-
- ; Define the Interrupt Descriptor Table (IDT)
-
- ALIGN 8
- idt_def LABEL WORD
- gate <int00,s_cs,0,8Eh,0> ; Divide
- .SALL
- gate <int01,s_cs,0,8Eh,0> ; Debug
- gate <int02,s_cs,0,8Eh,0> ; NMI
- gate <int03,s_cs,0,8Eh,0> ; BrkPt
- gate <int04,s_cs,0,8Eh,0> ; Overflow
- gate <int05,s_cs,0,8Eh,0> ; Bounds
- gate <int06,s_cs,0,8Eh,0> ; Invalid Opcode
- gate <int07,s_cs,0,8Eh,0> ; CoProcessor Error
- gate <int08,s_cs,0,8Eh,0> ; Double Fault
- gate <int09,s_cs,0,8Eh,0> ; Coproc Segment Overrun
- gate <int10,s_cs,0,8Eh,0> ; Invalid TSS
- gate <int11,s_cs,0,8Eh,0> ; Segment Not Present
- gate <int12,s_cs,0,8Eh,0> ; Stack Exception
- gate <int13,s_cs,0,8Eh,0> ; General Protection
- gate <int14,s_cs,0,8Eh,0> ; Page Fault
- gate <intxx,s_cs,0,8Eh,0> ;
- gate <int16,s_cs,0,8Eh,0> ; Coproc Error
- gate <intxx,s_cs,0,8Eh,0> ; 17
- gate <intxx,s_cs,0,8Eh,0> ; 18
- gate <intxx,s_cs,0,8Eh,0> ; 19
- gate <intxx,s_cs,0,8Eh,0> ; 20
- gate <intxx,s_cs,0,8Eh,0> ; 21
- gate <intxx,s_cs,0,8Eh,0> ; 22
- gate <intxx,s_cs,0,8Eh,0> ; 23
- gate <intxx,s_cs,0,8Eh,0> ; 24
- gate <intxx,s_cs,0,8Eh,0> ; 25
- gate <intxx,s_cs,0,8Eh,0> ; 26
- gate <intxx,s_cs,0,8Eh,0> ; 27
- gate <intxx,s_cs,0,8Eh,0> ; 28
- gate <intxx,s_cs,0,8Eh,0> ; 29
- gate <intxx,s_cs,0,8Eh,0> ; 30
- gate <intxx,s_cs,0,8Eh,0> ; 31
- REPT 224
- gate <intxx,s_cs,0,8Eh,0> ; PE Interrupt Gates
- ENDM
- idt_size equ $-idt_def
- .XALL
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; Entry ;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- Main proc near
- mov ax,cs ; init real-mode seg addr
- mov ss,ax
- mov ds,ax
- mov es,ax
- mov sp,stacke-_text ; set our stack
-
- mov ah,00h ; initialize display
- mov al,3 ; video mode 3
- int 10h
-
- mov si,offset command+1 ; process any run-time options
- cld
- opt1: lodsb
- cmp al,0dh ; C/R is end
- je optend
- cmp al,'-' ; option marker
- jne opt1
- lodsb ; option found, get next char
- or al,20h ; fold to lower case
- cmp al,'f' ; fast mode?
- jne short opt2
- mov pause_cnt,1
- jmp opt1
- opt2: cmp al,'x' ; skip parity check
- jne short opt3
- mov flag_CheckParity,0
- jmp opt1
- opt3: cmp al,'a' ; CycleMm=20 Main
- jne short opt4
- mov CycleMm,20
- jmp opt1
- opt4: cmp al,'b' ; CycleMm=100 Main
- jne short opt5
- mov CycleMm,100
- jmp opt1
- opt5: cmp al,'c' ; CycleEm=10 Extended
- jne short opt6
- mov CycleEm,20
- jmp opt1
- opt6: cmp al,'d' ; CycleEm=100 Extended
- jne short opt7
- mov CycleEm,100
- jmp opt1
- opt7:
- jmp opt1
- optend: cmp Pause_cnt,1
- jne short optend1
- mov Msg1c,'f'
- optend1:cmp flag_checkparity,0
- jne short optend2
- mov Msg1d,'x'
- optend2:mov ax,cycleMm
- mov bx,offset Msg7d
- call Convert_Decimal
- mov ax,cycleEm
- mov bx,offset Msg8d
- call Convert_Decimal
-
- int 12h ; get size of convensional memory
- mov Msize,ax
- mov bx,offset Msg1a
- call Convert_Decimal
- mov ax,Msize
- mov bx,offset Msg1ax
- call Convert_Hex
-
- mov ah,88h ; get size of extended memory
- int 15h
- mov Esize,ax
- mov bx,offset Msg1b
- call Convert_Decimal
- mov ax,Esize
- mov bx,offset Msg1bx
- call Convert_Hex
-
- vtype Msg1,Msg1Len,Line03
-
- mov Main_S,cs ; calc start of testing.
- mov ax,Progend-_text
- add ax,4020h
- shr ax,4
- add ax,Main_S
- and ax,0fc00h
- mov Main_S,ax
- mov bx,offset Msg7a
- call Convert_Hex
- mov ax,Msize
- shl ax,6
- mov Main_L,ax
- mov bx,offset Msg7b
- call Convert_hex
-
- Vtype Msg7,Msg7Len,Line04 ; Intro Msg
-
- sub eax,eax
- mov ax,Esize ; setup extended memory
- or ax,ax
- jz Main5 ; NO Extended Memory
- add ax,0400h
- shl eax,10 ; in K, mpy by 1024 to get megs
- dec eax ; limit is minus 1
- mov Extnd_L,EAX
- mov ax,Extnd_Lw+2
- mov bx,offset Msg8b
- call Convert_Hex
- mov ax,Extnd_Lw
- mov bx,offset Msg8c
- call Convert_Hex
- mov ax,Extnd_Sw+2
- mov bx,offset Msg8a
- call Convert_Hex
- mov ax,Extnd_Sw
- mov bx,offset Msg8a2
- call Convert_Hex
- Vtype Msg8,Msg8Len,Line05
- Vtype Msg2,Msg2Len,Line23
-
- Main5:
- mov al,80h ; disable the NMI interrupt
- out NMIport,al
-
- call Check_Main
- mov ax,Esize
- or ax,ax
- jz Done ; NO Extended Memory
- call Exec_Prot ; Yes, enter PE and Check it.
-
- Done:
- int 20h ; for now
- Main endp
-
- ; Output a message directly to the screen - bypass any use of the BIOS
- ; SI=offset to msg, CX-msglength, DI=offset into screen
- Video_Output proc near
- push ES
- mov ah,7 ; video attribute
- mov ES,Vram ; video ram segment (addr or selector)
- cld ; incrementing
- Vout1: lodsb
- stosw
- dec cx
- jnz Vout1
- pop ES
- ret
- Video_Output endp
-
- ; Convert number in AX to 5 digit decimal/ASCII equivalent into
- ; the area (offset) pointed to by BX.
- Convert_Decimal proc near
- push cx
- push dx
- push si
- mov cx,5
- Conv1: mov byte ptr [BX],' ' ; clear buffer
- inc bx
- loop Conv1
- mov si,10 ; to get digits
- or ax,ax ; positive numbers only
- jns Conv5
- neg ax
- Conv5: sub dx,dx
- div si
- add dx,'0'
- dec bx
- mov [bx],dl
- or ax,ax ; done if zero
- jnz Conv5
- pop si
- pop dx
- pop cx
- ret
- Convert_Decimal endp
-
- ; Convert number in AL to 2 digit hex/ASCII equivalent into
- ; the area (offset) pointed to by BX.
- Hexit proc near
- push ax
- and al,0fh
- or al,30h
- cmp al,3ah
- jl Hex_al
- add al,7
- Hex_al: mov 1[bx],al
- pop ax
- shr ax,4
- and al,0fh
- or al,30h
- cmp al,3ah
- jl Hex_ah
- add al,7
- Hex_ah: mov [bx],al
- ret
- Hexit endp
-
- ; Convert number in AX to 4 digit hex/ASCII equivalent into
- ; the area (offset) pointed to by BX.
- Convert_Hex proc near
- push bx
- push ax
- mov al,ah
- call Hexit
- pop ax
- add bx,2
- call Hexit
- pop bx
- ret
- Convert_Hex endp
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; Memory bad, report error ;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- Bad_Mem proc near
- push cx
- push si
- push di
- push bx
- mov ax,Errors
- mov bx,offset Msg9b
- call Convert_Decimal
- Vtype Msg9b,5,Line10+Msg9bo
-
- mov ax,MemSeg
- mov bx,offset Msg5a
- call Convert_Hex
- mov ax,MemOff
- mov bx,offset Msg5b
- call Convert_Hex
- mov al,Mem_Pat
- mov bx,offset Msg5c
- call Hexit
- mov al,Mem_Val
- mov bx,offset Msg5d
- call Hexit
- mov al,Mem_Par
- mov bx,offset Msg5e
- call Hexit
- Vtype Msg5,Msg5Len,Line14
- mov bx,pause_cnt ; pause to display msg
- pause1: sub cx,cx
- pause2: dec cx
- jnz pause2
- dec bx
- jnz pause1
- pop bx
- pop di
- pop si
- pop cx
- ret
- Bad_Mem endp
-
- ;;;;;;;;;;;;;;;;;;;;;
- ; Check Main Memory ;
- ;;;;;;;;;;;;;;;;;;;;;
-
- Check_Main proc near
- mov ax,Main_S ; setup
- mov MemSeg,ax
- mov Cycle,1
- mov Errors,0
- mov ax,Errors
- mov bx,offset Msg9b
- call Convert_Decimal
-
- Vtype Msg3,Msg3Len,Line07
- Vtype Msg9,Msg9Len,Line10
-
- Main_Loop:
- mov ax,Cycle
- mov bx,offset Msg9a
- call Convert_Decimal
- Vtype Msg9a,5,Line10+Msg9ao
-
- mov ax,LastPat
- dec ax ; start at different place each time
- jge short ml1
- mov ax,pattern_len
- ml1: mov LastPat,ax
-
- Vtype Msg3,MsgTstL,Line07
-
- mov ax,Main_S ; re-init for writing
- mov MemSeg,ax
- ; now write data to main memory
- cld
- mov ax,LastPat
- add ax,offset pattern
- mov si,ax
-
- wm1: push si
- mov ax,MemSeg
- mov bx,offset Msg3a
- call Convert_Hex
- Vtype Msg3a,4,Line07+Msg3ao
- pop si
- mov es,MemSeg ; point to segment to be written
- mov cx,1000h ; 4K block
- sub di,di ; start at zero offset
- wm5: lodsb ; put pattern byte into memory
- mov es:[di],al
- inc di
- cmp si,offset pattern+pattern_len
- jle short wm6
- mov si,offset pattern
- wm6: loop wm5
- mov ax,MemSeg ; bump up 4k
- add ax,0100h
- mov MemSeg,ax
- add ax,0ffh
- cmp ax,Main_L
- jb wm1
-
- mov bx,pause_cnt ; pause to display msg
- wm_x1: sub cx,cx
- wm_x2: dec cx
- jnz wm_x2
- dec bx
- jnz wm_x1
- Vtype MsgTst,MsgTstL,Line07
-
- mov ax,Main_S ; re-init for testing
- mov MemSeg,ax
- ; now test the data in main memory
- cld
- mov ax,LastPat
- add ax,offset pattern
- mov si,ax
-
- tm1: push si
- mov ax,MemSeg
- mov bx,offset Msg3a
- call Convert_Hex
- Vtype Msg3a,4,Line07+Msg3ao
-
- pop si
- mov es,MemSeg ; point to segment to be tested
- mov cx,1000h ; 4K block
- sub di,di ; start at zero offset
- tm3: mov al,es:[di] ; check pattern byte against memory
- cmp al,[si]
- jne tm7 ; bad byte
- mov Mem_Val,al ; save if bad parity
- in al,Port_Par ; check parity
- test al,Bits_Par ; shows parity error
- jnz tm8
- tm4: inc si
- inc di
- cmp si,offset pattern+pattern_len
- jle tm6
- mov si,offset pattern
- tm6: loop tm3
- jmp tm9
- tm7: inc Errors
- mov MemOff,di
- mov Mem_Val,al
- in al,Port_Par
- mov Mem_Par,al
- mov al,[si]
- mov Mem_Pat,al
- call Bad_Mem ; display
- jmp tm4
- tm8: inc Errors
- mov MemOff,di
- mov MemSeg,ES
- mov Mem_Par,al
- mov al,[si]
- mov Mem_Pat,al
- call Bad_Mem ; display
- jmp tm4
- tm9: mov ax,MemSeg ; bump up 4k
- add ax,0100h
- mov MemSeg,ax
- add ax,0ffh
- cmp ax,Main_L
- jb tm1
-
- mov bx,pause_cnt ; pause to display msg
- tm_x1: sub cx,cx
- tm_x2: dec cx
- jnz tm_x2
- dec bx
- jnz tm_x1
-
- mov ax,Main_S ; re-init
- mov MemSeg,ax
- mov ax,Cycle
- inc ax
- mov Cycle,ax
- cmp ax,CycleMm
- jle Main_loop
- Vtype msgd1,msgd1L,line21
- Vtype Msg9,Msg9Len,Line07+Msg3Leno
- ret
- Check_Main endp
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Initialize and Enter Protected Mode ;;
- ;; ... Then call Check_Extended ;;
- ;; ... Finally, return to real mode ;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-
- Check_Extended proc near
- mov ax,s_mem ; init segment
- mov GS,ax
- mov Cycle,1
- mov errors,0
- mov ax,Errors
- mov bx,offset Msg9b
- call Convert_Decimal
-
- Vtype Msg4,Msg4Len,Line08
- Vtype Msg9,Msg9Len,Line10
-
- ce1: mov ax,Cycle
- mov bx,offset Msg9a
- call Convert_Decimal
- Vtype Msg9a,5,Line10+Msg9ao
-
- mov ax,LastPat
- dec ax ; start at different place each time
- jge short ce2
- mov ax,pattern_len
- ce2: mov LastPat,ax
-
- Vtype Msg4,MsgTstL,Line08
-
- mov eax,Extnd_S ; re-init for writing
- mov MemExtnd,eax
- mov LoopCnt,0
- ; now write the data to memory
- cld
- mov ax,LastPat
- add ax,offset pattern
- mov si,ax
- we1: push si
- mov ax,MemSeg
- mov bx,offset Msg4a
- call Convert_Hex
- mov ax,MemOff
- mov bx,offset Msg4b
- call Convert_Hex
- Vtype MSg4a,9,Line08+Msg4ao
- pop si
- mov cx,LoopCnt
- mov edi,MemExtnd ; start
- we5: lodsb ; put pattern byte into memory
- mov gs:[edi],al
- inc edi
- cmp si,offset pattern+pattern_len
- jle short we6
- mov si,offset pattern
- we6: loop we5
- mov MemExtnd,EDI
- cmp edi,Extnd_L ; at end?
- jnb short we_x
- add edi,10000h
- cmp edi,Extnd_L ; at end?
- jb we1
- mov edi,Extnd_L
- sub edi,MemExtnd
- mov LoopCnt,DI
- jmp we1
-
- we_x: mov bx,pause_cnt ; pause to display msg
- we_x1: sub cx,cx
- we_x2: dec cx
- jnz we_x2
- dec bx
- jnz we_x1
- Vtype MsgTst,MsgTstL,Line08
-
- mov eax,Extnd_S ; re-init for testing
- mov MemExtnd,eax
- mov LoopCnt,0
- ; now test the memory
- cld
- mov ax,LastPat
- add ax,offset pattern
- mov si,ax
- te1: push si
- mov ax,MemSeg
- mov bx,offset Msg4a
- call Convert_Hex
- mov ax,MemOff
- mov bx,offset Msg4b
- call Convert_Hex
- Vtype Msg4a,9,Line08+Msg4ao
- pop si
- mov cx,LoopCnt
- mov edi,MemExtnd ; start
- te3: mov al,GS:[EDI] ; check pattern byte against memory
- cmp al,[si]
- jne te7 ; bad byte
- cmp flag_CheckParity,0
- je short te4
- mov Mem_Val,al ; save if bad parity
- in al,Port_Par ; check parity
- test al,Bits_Par ; shows parity error
- jnz te8
- te4: inc si
- inc edi
- cmp si,offset pattern+pattern_len
- jle short te6
- mov si,offset pattern
- te6: loop te3
- jmp te9
- te7: inc Errors ; memory did not compare
- mov Mem_Val,al
- mov MemExtnd,EDI
- mov MemExtnd,EDI
- in al,Port_Par
- mov Mem_Par,al
- mov al,[si]
- mov Mem_Pat,al
- call Bad_Mem ; display info
- call Empty_8042
- jmp te4
- te8: inc Errors ; memory compared but parity error
- mov MemExtnd,EDI
- mov MemExtnd,EDI
- mov Mem_Par,al
- mov al,[si]
- mov Mem_Pat,al
- call Bad_Mem ; display info
- call Empty_8042
- jmp te4
- te9: mov MemExtnd,edi ; at end?
- cmp edi,Extnd_L
- jnb short te_x
- add edi,10000h
- cmp edi,Extnd_L
- jb te1
- mov edi,Extnd_L
- sub edi,MemExtnd
- mov LoopCnt,DI
- jmp te1
-
- te_x: push si
- mov ax,MemSeg
- mov bx,offset Msg4a
- call Convert_Hex
- mov ax,MemOff
- mov bx,offset Msg4b
- call Convert_Hex
- Vtype Msg4a,9,Line08+Msg4ao
- pop si
- mov bx,pause_cnt ; pause to display msg
- te_x1: sub cx,cx
- te_x2: dec cx
- jnz te_x2
- dec bx
- jnz te_x1
-
- mov eax,Extnd_S ; re-init
- mov MemExtnd,eax
- mov ax,Cycle
- inc ax
- mov Cycle,ax
- cmp ax,CycleEm
- jle ce1
- Vtype msgd2,msgd2L,line21+msgd2o
- Vtype Msg9,Msg9Len,Line08+Msg3Leno
- ret
- Check_Extended endp
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; Interrupt Handlers
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-
- intspv equ 1800h ; base value of interrupt handler stack
- intspv1 equ 17e0h ; if no code on stack
- intspv2 equ intspv1-4 ; if code IS stored
- int_rdisp dw 0 ; to check SP
- intcod1 dw 0 ; interrupt code word 1
- intcod2 dw 0 ; interrupt code word 2
-
- xmsg08 db 'Double Fault'
- xmsg08l equ $-xmsg08
- xmsg1 db 'Fault '
- xmsg1a db 'xx'
- xmsg1l equ $-xmsg1
-
- ; Interrupt Fault Handlers
-
- int00: mov cx,0
- mov si,0
- jmp int_comm
- int01: mov cx,1
- mov si,0
- jmp int_comm
- int02: mov cx,2
- mov si,0
- jmp int_comm
- int03: mov cx,3
- mov si,0
- jmp int_comm
- int04: mov cx,4
- mov si,0
- jmp int_comm
- int05: mov cx,5
- mov si,0
- jmp int_comm
- int06: mov cx,6
- mov si,0
- jmp int_comm
- int07: mov cx,7
- mov si,0
- jmp int_comm
- int08: mov cx,8 ; Double Fault
- mov AX,s_ds ; get some addressability
- mov DS,AX
- Vtype xmsg08,xmsg08l,line02
- jmp $ ; SPIN - go no further
- int09: mov cx,9
- mov si,0
- jmp int_comm
- int10: mov cx,10
- mov si,0
- jmp int_comm
- int11: mov cx,11
- mov si,0
- jmp int_comm
- int12: mov cx,12
- mov si,0
- jmp int_comm
- int13: mov cx,13
- mov si,0
- jmp int_comm
- int14: mov cx,14
- mov si,0
- jmp int_comm
- int15: mov cx,15
- mov si,0
- jmp int_comm
- int16: mov cx,16
- mov si,0
- jmp int_comm
-
- ; Misc Interrupt Handler
-
- intxx: mov cx,255
- mov si,0
- jmp int_comm
-
- ; Common routine for handling interrupts
- int_comm:
- push AX ; temp get a reg
- mov ax,s_ds ; to get addressability
- mov DS,AX
- pop AX
- pusha ; save all regs
- mov AX,CX
- mov BX,offset xmsg1a
- call Hexit
- Vtype xmsg1,xmsg1l,Line00
- jmp $ ; ****DEBUG**** SPIN
- popa
- IretD
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;
- ; This controls a signal which gates address bit 20.
- ;
- ; The gate A20 signal is an output of the 8042 slave processor.
- ; Address bit 20 should be gated ON before entering protect
- ; mode so that memory is addressed properly (if not, then odd numbered
- ; megs are mapped to the next lowest even numbered meg!!. When
- ; exiting protect mode (going back to real mode), the address A20
- ; should be gated back off.
- ;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-
- Empty_8042 proc near
- mov ecx,100000h ; for timeout (big number)
- empty: in al,port_status ; read the 8042 status port
- and al,00000010b ; test input buffer full flag
- loopnz empty ; loop until empty or timeout
- ret
- Empty_8042 endp
-
- Gate_A20 proc near
- ;
- ; On entry, AH contains the code (enable or disable)
- ;
- call Empty_8042
- jnz short exit_8042 ; yes
- mov al,0D1h ; 8042 command to write output port (I hope)
- out port_status,al
- call empty_8042
- jnz short exit_8042
- mov al,ah
- out port_a,al ; output gate signal
- call empty_8042
- Exit_8042:
- ret
- Gate_A20 endp
-
-
- Exec_Prot proc near ; Setup and switch to PE
- cld
- cli
- mov savecs,CS
- mov savess,SS
- mov savesp,SP
-
- ; First, Enable the A20 line
- mov ah,bit20_enable
- call gate_a20
- or al,al ; zero if OK
- jz A20_ON
- Vtype Emsg3,Emsg3L,Line24
- ret
- A20_ON:
-
- ; Convert segment regs into linear addresses.
- mov ES,Vram
- segcvt ES,d_crt
- mov Vram,s_crt ; Protected Mode Video
- segcvt CS,d_cs
- segcvt DS,d_ds
- segcvt SS,d_ss
-
-
- ; Setup GDT, IDT, etc. to run protected
-
- segadr DS
- mov dsaddr,EAX
- sub EBX,EBX
- lea EBX,gdt_def
- add EBX,EAX
- mov dtload,EBX ; set addr
- mov dtsize,gdt_size-1
- LGDT FWORD PTR dtsize
-
- sub EBX,EBX
- lea EBX,idt_def
- add EBX,EAX
- mov dtload,EBX ; set addr
- mov dtsize,idt_size-1
- LIDT FWORD PTR dtsize
-
- mov EAX,CR0 ; get control reg
- or AL,1 ; turn PE on
- mov CR0,EAX ; set it
- jmp short @f ; clear pipeline, etc.
- @@: nop
-
- mov AX,s_ds ; and seg regs
- mov DS,AX
- mov ES,AX
- mov FS,AX
- mov GS,AX
- mov AX,s_ss
- mov SS,AX
- db 0eah ; do far jump to set CS
- dw go_prot_2-_text,s_cs
- go_prot_2:
-
- mov al,80h ; disable the NMI interrupt
- out NMIport,al
-
- call Check_Extended
-
- ; restore for real mode
- cld
- cli
- mov EAX,CR0 ; get control reg
- and AL,0FEh ; turn PE off
- mov CR0,EAX ; set it
- jmp go_real
- go_real:
- mov SS,savess
- mov SP,savesp
- mov AX,savecs
- mov DS,AX
- mov ES,AX
- mov FS,AX
- mov GS,AX
- mov Vram,0b800h ; Restore Real Mode Video
- Vtype msgd3,msgd3L,Line22
- jmp $ ; SPIN - pending interrupts screwed up,
- ; leave video display up rather
- ; than re-booting.
- sti
- ret
- Exec_Prot endp
-
- ProgEnd equ $
-
- _text ends
- end start