home *** CD-ROM | disk | FTP | other *** search
- ;---------------
- ; XBIOS test driver for BIOS.8
- ;---------------
-
- ; Copyright 1987-88 Eric Isaacson. All rights reserved. Permission to
- ; copy and use this module is granted ONLY for machines registered for both
- ; the A86 assembler and the D86 debugger.
-
- ; XBIOS is a program that exercises the BIOS.8 module. I am providing it
- ; to assist those who wish to assist me in porting my D86 debugger to
- ; machines with non-IBM-compatible BIOSes.
- ;
- ; You may simulate the "B" switch of the D86 debugger by providing a digit
- ; in the command tail. The digit must follow the single space following
- ; the XBIOS name; e.g. XBIOS 9 for Sirius/Victor.
-
- ; You use this source module as follows:
- ;
- ; 1. Modify the module BIOS.8 to accommodate your specific machine. You
- ; should NOT need to modify this module, except possibly to add a
- ; new HELP-key name just before the declcaration HELP_HELP below.
- ;
- ; 2. Assemble both modules with the command A86 XBIOS.8 BIOS.8
- ; (Command is provided as MAKX.BAT in this package; just type MAKX.)
- ;
- ; 3. Run the resulting program XBIOS.COM. The program will run tests
- ; of the BIOS function calls, and tell you about them. If everything
- ; looks good, then your BIOS.8 probably works.
- ;
- ; 4. The XBIOS program ends with an interactive mode, displaying keystrokes.
- ; Please try every key on your keyboard, both with and without any
- ; shift-style keys (ALT, SHIFT, CTRL, SECOND, etc.). Write down the
- ; codes that result.
- ;
- ; 5. Send me the codes you wrote down, together with your new BIOS.8. I'll
- ; incorporate it into D86. Thanks!
-
-
-
- ; This is a "quick-and-dirty" program. It does not meet my standards for
- ; professionally-documented source code (no procedure-level comments).
-
-
- JMP MAIN
-
- ALTF10_HELP: ; HELP-key name for the IBM-PC
- DB 'Alt-F10',0
- F11_HELP: ; HELP-key name for the TI-PC
- DB 'F11',0
- PF5_HELP:
- DB 'Ctrl-PF5',0
- ALTJ_HELP:
- DB 'Alt-J',0
- MENU_HELP:
- DB 'Menu',0
-
- ; If your machine uses a different HELP-KEY, declare its name above this line.
-
- HELP_HELP:
- DB 'HELP',0
-
- SWITCH EQU B[$-'A']
- DB 26 DUP 080
-
- EGA_ATTRS DW 04D1F ; attribute bytes for EGA video
- CGA_ATTRS DW 0F007 ; attribute bytes for CGA video
-
- LAST_LINE DW ? ; variable stored by the D86 BIOS interface
- ENABLE_PORT DW ? ; BIOS specific, used by Wang for a port number
- V_FLAG DB ? ; debugger variable consulted by IBM BIOS_INIT
- WAVY_COUNT DB ? ; count of how many wavy messages have been output
-
- ; DWB causes the initialization of alternating words and bytes
-
- DWB MACRO #RX1L
- DW #X
- DB #AX
- #E2#EM
-
- SKIP2 MACRO ; skip over the following 2 opcode bytes
- DB 03D ; CMP AX,iw opcode will do the job
- #EM
-
-
- SCREEN_P EQU 08000 ; screen buffer is at 08000
-
- ; The following are convenient prefix-abbreviations for returned key-codes.
-
- CTRL EQU -040 ; e.g. CTRL'A' -- WARNING CTRL'a' will be wrong!!
- FUNC EQU 59+111 ; e.g. FUNC 1 for the F1 function key
- SHIFT_F EQU 84+111 ; e.g. SHIFT_F 3 for the shifted F3 key
- CTRL_F EQU 94+111 ; e.g. CTRL_F 10 for the control-F10 key
- ALT_F EQU 104+111 ; e.g. ALT_F 4 for the Alt-F4 key
- ALT_N EQU 120+111 ; e.g. ALT_N 5 for the Alt-5 key
-
- BIOS_CALLS: ; pointers to BIOS-specific action routines
- VID_COPY DW MONO_COPY ; video copy
- VID_ATTR DW IBM_ATTR ; set attribute at DI to AL
- VID_FIX DW IBM_FIX ; fix video screen
- BIOS_BELL DW IBM_BELL ; ring bell
- BIOS_KEY DW IBM_KEY ; fetch a keystroke
- BIOS_SAVE DW IBM_SAVE ; save user's BIOS state (Sanyo only)
- BIOS_RESTORE DW IBM_RESTORE; restore the saved BIOS state (Sanyo only)
- VIDEO_SEG DW ? ; pointer to physical video display segment
- ATTR_BYTES DW ; hardware-dependent video codes
- NORM_ATTR DB 7 ; code for normal video display
- REV_ATTR DB 070 ; code for reversed-video display
- N_BIOS_CALLS EQU ($-BIOS_CALLS)/2
-
-
- ; CTRL_JUMPS defines the single-key commands recognized by the debugger. Each
- ; DW below is an address to be jumped to whenever the following DB byte is
- ; taken as a single-key input by the debugger command processor.
-
- CTRL EQU -040
-
- CTRL_JUMPS:
- DWB F1_MSG, FUNC 1
- DWB F2_MSG, FUNC 2
- DWB F3_MSG, FUNC 3
- DWB F4_MSG, FUNC 4
- DWB F5_MSG, FUNC 5
- DWB F6_MSG, FUNC 6
- DWB F7_MSG, FUNC 7
- N_FUNCS EQU ($-CTRL_JUMPS)/3
-
- L1: ; control-key functions start here
- DWB DOWN_MSG, 80+112
- DWB PGDN_MSG, 81+112
- DWB UP_MSG, 72+112
- DWB PGUP_MSG, 73+112
- DWB HOME_MSG, 71+112
- DWB SHF7_MSG, SHIFT_F 7
- DWB ALTF9_MSG, ALT_F 9
- N_CONTROL_KEYS EQU ($-L1)/3
-
- DW F10_MSG
- SWITCH_KEY DB FUNC 10 ; key code for FUNC 10 (switch screens)
-
- DW HELP_HELP
- HELP_KEY DB ALT_F 10 ; key code for the debugger's HELP key
-
- DWB 0, 0FF ; terminator for this table
-
-
-
-
-
- MAIN:
- CALL XBIOS_SWITCH ; scan the command-tail switch, if any
- CALL BIOS_INIT ; initialize our specific BIOS
- MOV DS,ES,SS ; restore segment registers
- CALL TEST_INIT ; display the settings produced, prompt for key
- CALL TEST_KEY_BELL ; test the simple key input and bell functions
- CALL TEST_VIDEO ; test some simple video displays
- CALL TEST_KEY_CODES ; enter the interactive key-code display loop
- MOV AX,04C00 ; MS-DOS codes for successful program exit
- INT 33 ; exit back to the operating system
-
-
- FIRST_TESTING:
- DB 'Survived BIOS_INIT.',0D,0A
- DB 'Subdirectory character is set to "'
- SUBDIR_CHAR DB '\'
- DB '".',0D,0A
- DB 'Video memory is at segment register value '
- VIDEO_DISPLAY:
- DB 'xxxx.',0D,0A
- DB 'The normal attribute byte is '
- NORM_DISP:
- DB 'xx.',0D,0A
- DB 'The reverse attribute byte is '
- REV_DISP:
- DB 'xx.',0D,0A
- DB 'The HELP key is labelled ',0
-
- HELP_MSG DW ALTF10_HELP
-
- POST_HELP:
- DB '.',0D,0A
- DB 'Is this right?',0D,0A,0D,0A
- DB 'First testing BIOS key input and bell-ringing.',0D,0A,0
-
- TEST_INIT: ; make initial display of BIOS variables
- MOV BX,VIDEO_SEG ; fetch the video segment register value
- MOV DI,VIDEO_DISPLAY ; point to it position in the display message
- MOV AL,BH ; fetch the high byte of the value
- CALL HEX_AL ; output the high byte
- MOV AL,BL ; fetch the low byte of the value
- CALL HEX_AL ; output the low byte
- MOV DI,NORM_DISP ; point to NORM_ATTR value in message
- MOV AL,NORM_ATTR ; fetch the value
- CALL HEX_AL ; put the hex value into the message
- MOV DI,REV_DISP ; point to REV_ATTR value in message
- MOV AL,REV_ATTR ; fetch the value
- CALL HEX_AL ; put the hex value into the message
- MOV SI,FIRST_TESTING ; point to the first message
- CALL MESSAGE ; output the message
- MOV SI,HELP_MSG ; point to the name of the HELP key
- CALL MESSAGE ; output the name
- MOV SI,POST_HELP ; point to the message after the HELP name
- JMP MESSAGE ; output the message
-
- XBIOS_SWITCH:
- MOV AX,[081] ; fetch the command-tail switch, if any
- CMP AL,0D ; is there a command tail?
- JE RET ; return if not
- MOV AL,AH
- SUB AL,'0' ; reduce digit to its binary value
- JC RET ; return if there was not a digit
- MOV SWITCH'B',AL ; there was a digit: set the B switch to its value
- RET
-
-
- VID_TEST_MSG:
- DB 'Now we''ll output directly to video memory.',0D,0A
- DB 'Type any two keys--',0D,0A
- DB 'The screen will go blank after the first keystroke.',0D,0A,0
-
- ALPHABET_MSG:
- DB 'Now letters A to X go down the left.',0
- H_MSG:
- DB 'Reverse video on the H.',0
- AFTER_M_MSG:
- DB 'Reverse video in second character beyond the M.',0
-
- H_SPOT EQU ('H'-'A') * 160
- AFTER_M_SPOT EQU ('M'-'A') * 160 + 4
-
- TEST_VIDEO:
- MOV SI,VID_TEST_MSG ; point to the "Now testing video" message
- CALL MESSAGE ; output the message
- CALL KEY_ONLY ; take a keystroke
- CALL FIRST_FILL ; blank the screen
- CALL GET_KEY ; take another keystroke
- CALL ALPHA_LINES ; put out the alphabet along the side
- MOV SI,ALPHABET_MSG ; point to message telling about it
- CALL TOP_LINE ; output the message
- CALL REFRESH ; send it all to the video
- CALL GET_KEY ; take another key
- MOV SI,H_MSG ; point to cursor-on-H message
- CALL TOP_LINE ; output the message
- CALL REFRESH ; refresh the video memory
- MOV ES,VIDEO_SEG ; point to the video segment
- MOV DI,H_SPOT ; point to "H" character within that segment
- MOV AL,REV_ATTR ; load the reverse-attribute byte
- CALL VID_ATTR ; output the byte to the video segment
- MOV ES,SS ; restore ES
- CALL GET_KEY ; take another keystroke
- MOV SI,AFTER_M_MSG ; point to cursor-after-M message
- CALL TOP_LINE ; output the message
- CALL REFRESH ; refresh the video memory
- MOV ES,VIDEO_SEG ; point to the video segment
- MOV DI,H_SPOT ; point to the previous cursor position in segment
- MOV AL,NORM_ATTR ; load normal attribute
- CALL VID_ATTR ; cancel the previous cursor output
- MOV DI,AFTER_M_SPOT ; point to the new cursor position
- MOV AL,REV_ATTR ; load reverse-attribute byte
- CALL VID_ATTR ; output the new cursor
- MOV ES,SS ; restore ES
- GET_KEY:
- CALL BIOS_RESTORE
- CALL BIOS_KEY
- RET
-
-
- PLEASE_TYPE:
- DB 'Please type any key.',0D,0A,0
- KEY_ONLY_MSG:
- DB 'The BIOS returned hex code '
- KEY_ONLY_HEXCODE:
- DB 'xx.',0D,0A,0
-
- KEY_ONLY:
- MOV SI,PLEASE_TYPE ; point to "Please type any key"
- CALL MESSAGE ; output "Please type any key"
- MOV DI,KEY_ONLY_HEXCODE ; output goes to the key-value report
- MOV SI,KEY_ONLY_MSG ; point to start of key-value report
- CALL GET_KEY ; fetch a keystroke from the BIOS
- CALL HEX_AL ; place the hex code into the message
- MESSAGE: ; output null-terminated SI-message to standard out
- PUSH BX,CX,DX ; save registers across call
- MOV DX,SI ; MS-DOS wants the message pointer in DX
- L1: ; loop here to scan for the terminator
- LODSB ; fetch a string byte
- TEST AL ; is it the zero terminator?
- JNZ L1 ; loop if not
- LEA CX,[SI-1] ; point CX to the terminator byte
- SUB CX,DX ; compute the number of characters in the message
- MOV AH,040 ; MS-DOS function number for WRITE
- MOV BX,1 ; handle number for standard output is 1
- INT 33 ; call MS-DOS to make the output
- POP DX,CX,BX ; restore clobbered registers
- RET
-
-
-
- NOW_BELL:
- DB 'Now we''re using BIOS to ring the bell...',0D,0A,0
- HEAR_IT?:
- DB 'Did you hear it?',0D,0A,0
-
- TEST_KEY_BELL: ; take 4 test keystrokes
- CALL KEY_ONLY ; take key without bell
- CALL KEY_ONLY ; take second key, without bell
- CALL KEY_BELL ; take a key then ring the bell
- KEY_BELL: ; prompt for key, then ring the bell
- CALL KEY_ONLY ; prompt for and take a keystroke
- MOV SI,NOW_BELL ; point to bell message
- CALL MESSAGE ; put out the bell message
- CALL BIOS_BELL ; ring the bell
- MOV SI,HEAR_IT? ; point to the post-bell message
- JMP MESSAGE ; output the post-bell message
-
-
-
- ; REFRESH updates the console screen to the desired contents, as indicated by
- ; the SCRBASE buffer. The buffer is updated to show that the actual screen
- ; contents matches the desired contents.
-
- REFRESH:
- PUSH BX,CX,DX,BP,SI,DI,ES,DS ; preserve all registers but AX
- MOV ES,VIDEO_SEG ; we will copy to the screen-segment
- MOV AH,NORM_ATTR ; characters will have the normal attribute
- MOV SI,SCREEN_P ; source pointer is our screen buffer
- SUB DI,DI ; offset of the screen is zero
- MOV BL,24 ; BL will count down lines
- D86_LINES EQU B[$-1]
- MOV CH,0 ; CX will always hold byte counts
- L1: ; main loop for actual vs. desired comparison
- MOV CL,80 ; count number of characters in a line
- CALL VID_COPY ; copy this line to the video buffer
- OR SI,0FF ; advance SI to the end of this buffer-page
- INC SI ; bump SI to the beginning of the next page
- DEC BL ; count down lines
- JNZ L1 ; loop if there are more lines
- POP DS,ES,DI,SI,BP,DX,CX,BX ; restore all the registers
- RET
-
-
-
- ; This section of code defines the message-displays for the control keys.
-
- MSG MACRO
- #1_MSG:
- DB '#1',0
- #EM
-
- MSG F1
- MSG F2
- MSG F3
- MSG F4
- MSG F5
- MSG F6
- MSG F7
- MSG F10
- MSG DOWN
- MSG PGDN
- MSG PGUP
- MSG UP
- MSG HOME
- MSG SHF7
- MSG ALTF9
-
- ; HEX_AL outputs to DI-pointed memory the 2-digit hex number representing
- ; the value of AL.
-
- BINHEX_AL MACRO
- ADD AL,090H ; these 4 lines convert AL into an ASCII hex digit,
- DAA ; in an outrageously clever and incomprehensible
- ADC AL,040H ; fashion!!! (I got the 8080 version of this out
- DAA ; of an early BYTE magazine.)
- #EM
-
- HEX_AL:
- AAM 16 ; unpack AL into nibbles AH and AL
- CALL >L3 ; swap nibbles, then output new low nibble
- L3: ; call here to output nibble AH
- XCHG AL,AH ; swap the nibble into AL
- BINHEX_AL ; convert AL to a hex digit
- STOSB ; output the digit
- RET
-
-
-
- FIRST_FILL: ; fill the video screen with its first contents
- MOV DI,SCREEN_P ; point to our screen image
- MOV CX,(24 BY 0)/2 ; load the number of words in the image buffer
- SUB AX,AX ; we will zero-fill the buffer
- REP STOSW ; buffer is initialized to all-zeroes
- MOV AL,' ' ; now load a blank
- CALL FILL_LINES ; fill the character line-buffers with blanks
- CALL VID_FIX ; insure that this first screen was actually sent
- CALL REFRESH ; send our screen buffer to video memory
- RET
-
-
-
- ALPHA_LINES: ; put alphabet A to X down the left side
- MOV DI,SCREEN_P ; point to the upper left corner
- MOV CX,24 ; load the lines count
- MOV AL,'A' ; load the first letter
- L1: ; loop here to output each letter
- STOSB ; output the letter
- INC AX ; increment to the next letter
- ADD DI,255 ; advance output pointer to the next line
- LOOP L1 ; loop to output the next letter
- RET
-
-
-
- FILL_LINES: ; fill all 24 image-lines with AL
- MOV DI,SCREEN_P ; point to the start of the image-buffer
- MOV BL,24 ; number of lines in the buffer
- L1: ; loop here for each line
- CALL FILL_LINE ; fill the line with AL
- DEC BL ; count down lines
- JNZ L1 ; loop to fill the next line
- RET
-
-
-
- FILL_LINE: ; fill the DI-pointed line with AL, advance DI
- MOV CX,80 ; number of characters in the line
- REP STOSB ; fill the line
- ADD DI,256-80 ; advance output pointer to the next line buffer
- RET
-
-
-
- PRESS_KEY:
- DB ' Press any key',0
-
- TOP_LINE: ; put SI-message and "press key" on top line
- MOV DI,SCREEN_P+3 ; point to the fourth character of the top line
- CALL COPY_STRING ; output the caller's SI-pointed message
- MOV SI,PRESS_KEY ; now point to our "press key" message
- COPY_LINE:
- CALL COPY_STRING ; output the "press key" message
- MOV CX,DI ; copy the beyond-output pointer to CX
- MOV CL,80 ; advance the pointer to the end of the top line
- SUB CX,DI ; calculate the number of trailing bytes in the line
- MOV AL,' ' ; load blank
- REP STOSB ; blank-fill the trailing bytes
- RET
-
-
-
- ALL_KEYS:
- DB 'Now try out all possible keystrokes.',0
- CAP_Q:
- DB 'Capital Q exits program; capital T trashes the screen.',0
- TRASH_MESSAGE:
- DB 'The message is output via MS_DOS.',0D,0A
- DB 'It will roll the screen, thereby trashing the display.',0D,0A
- DB 'Type capital-F to fix the screen if it is trashed.',0D,0A,0
- KNOWN_MSG:
- DB 'I recognize that function key, its name is '
- KNOWN_TAIL:
- DB ' ',0
- UNKNOWN_MSG:
- DB 'That key code is not in my table. Its value is '
- UNKNOWN_HEXCODE:
- DB 'xx',0
- DISPLAYING_MSG:
- DB 'Displayable character was typed: the character is "'
- DISPLAYING_CHAR DB 'x"',0
-
- TEST_KEY_CODES: ; interactive routine for displaying key codes
- MOV SI,ALL_KEYS ; point to the main prompting message
- MOV DI,SCREEN_P+3 ; point to the location in our buffer for message
- CALL COPY_LINE ; output the first line of the message
- MOV SI,CAP_Q ; point to second line of message
- MOV DI,SCREEN_P+0103 ; point to location in buffer for that message
- CALL COPY_LINE ; output the second line
- L1: ; loop here for each keystroke
- CALL REFRESH ; refresh the video screen
- CALL GET_KEY ; take a keystroke
- CMP AL,'Q' ; is it the exiting capital-Q?
- JE RET ; if yes then exit
- CMP AL,'T' ; is it the TRASH command?
- JE >L6 ; jump if yes
- CMP AL,'F' ; is it the FIX command?
- JE >L7 ; jump if yes
- MOV BL,AL ; copy character to BL for WAVY-function
- CMP AL,' ' ; is the character a control character?
- JB >L5 ; jump if yes
- CMP AL,07E ; is the character above the displaying range?
- JA >L5 ; jump if yes
- MOV DISPLAYING_CHAR,AL ; character is displayable-- put it into message
- MOV SI,DISPLAYING_MSG ; point to the displayable message
- JMP >L4 ; jump to propagate the message
-
- L5: ; keystroke is not a displayable character
- MOV DI,CTRL_JUMPS+2 ; point to our table of function keys
- L2: ; loop here to search each entry of function table
- CMP B[DI],0FF ; is the table exhausted?
- JE >L3 ; jump if yes, key not in table
- SCASB ; does our key match the table entry?
- LEA DI,[DI+2] ; advance table pointer in case not
- JNE L2 ; loop if not
- MOV SI,[DI-5] ; the key matches-- fetch the pointer from that record
- MOV DI,KNOWN_TAIL ; point to the end of the known-message
- CALL COPY_STRING ; tack the key's name onto the known-message
- MOV AL,0 ; load terminator
- STOSB ; null-terminate the known-message
- MOV SI,KNOWN_MSG ; point to the start of the known-message
- JMP >L4 ; jump to propagate the message
-
- L3: ; keystroke was not found in the function table
- MOV DI,UNKNOWN_HEXCODE ; point to hex-display part of unknown-message
- CALL HEX_AL ; output our keycode as hex digits
- MOV SI,UNKNOWN_MSG ; point to the start of the unknown message
- L4: ; common output point
- CALL WAVY_MESSAGES ; output the SI-pointed message in a wavy display
- JMP L1 ; loop to take another keystroke
-
- L6: ; capital T is seen
- MOV SI,TRASH_MESSAGE ; point to our message that trashes the screen
- CALL MESSAGE ; trash the screen with the message
- CALL BIOS_SAVE
- JMP L1 ; loop to take another keystroke
-
- L7: ; capital F is seen
- CALL VID_FIX ; fix up the trashed screen
- JMP L1 ; loop to take another keystroke
-
-
-
- COPY_STRING: ; copy SI-pointed string to DI
- LODSB ; load the first character
- L1: ; loop here for each nonzero character
- STOSB ; output the character
- LODSB ; fetch the next character
- TEST AL ; is it the terminating zero?
- JNZ L1 ; loop if not
- RET
-
-
- WAVY DB 3,4,5,6,7,6,5,4
-
- WAVY_MESSAGES: ; make 20 copies of SI-message in a wavy pattern
- INC WAVY_COUNT ; increment display count
- MOV DI,SCREEN_P+0404 ; point to the first line of the wavy display
- MOV BH,20 ; load the count of lines to be output
- L1: ; loop here to output each line
- MOV CX,DI ; fetch the output pointer
- MOV CL,CH ; low byte tells us a reltive line number
- ADD CL,BL ; add in character code, just to mix things up
- SUB CL,WAVY_COUNT ; now a repeat of same key will make waves
- AND CX,7 ; waviness will have a period of 8 lines
- XCHG BX,CX ; swap the line-index into BX, for addressing
- MOV BL,WAVY[BX] ; translate line-index into an indetation count
- XCHG CX,BX ; swap the count back into CX
- MOV AL,' ' ; load blank
- REP STOSB ; indent the message-- this creates the waviness
- PUSH SI ; save the message pointer for the next line
- CALL COPY_LINE ; copy the message to this line, with trailing blanks
- POP SI ; restore the message pointer
- ADD DI,260-80 ; advance output to the next line
- DEC BH ; count down lines
- JNZ L1 ; loop to output the next line
- RET