Category : Assembly Language Source Code
Archive   : D86BIOS4.ZIP
Filename : XBIOS.8

 
Output of file : XBIOS.8 contained in archive : D86BIOS4.ZIP
;---------------
; 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


  3 Responses to “Category : Assembly Language Source Code
Archive   : D86BIOS4.ZIP
Filename : XBIOS.8

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/