This article describes the main differences between the interrupt functions which exist in DOS-Plus running on the Master 512 and those which exist in MS-DOS running on a fully IBM-compatible PC. It is not intended to duplicate material which is available elsewhere. For this reason, no attempt has been made to describe the use of Interrupt E0h. This is the main CP/M-86 entry point, and is supported by DOS-Plus. For detailed information on this interrupt see, for example, Appendix C of the Master 512 Technical Guide by Robin Burton, or click here. Furthermore, I make no claim that all the differences other than this have been described. All the ones I know of are mentioned (at least, those worth talking about) but there may be others which I have not discovered.
The information here is only likely to be of use or of interest to programmers using assembly language, or at least a language such as C which can make use of DOS interrupts. Consequently the article assumes a general understanding of the architecture of the 80186 processor and the use of interrupts from DOS. It is probably best read in conjunction with an MS-DOS reference manual, remembering that DOS-Plus is intended to be compatible with MS-DOS Version 2, but not necessarily with later versions. (Lists of the MS-DOS interrupt functions can also be found on the Worldwide Web – for example click here.)
This page may give some indication of why certain programs written for PC compatibles will not work on the Master 512. However, it does not provide any real suggestions as to how they might be made to work properly on our machine.
I believe that the information included here is valid for all versions of Master 512 DOS-Plus, but most of it has only been tested with DOS-Plus 2.1.
A number of issues lie behind the differences between the way that interrupts are supported on the Master 512 and on an MS-DOS PC.
|The hardware of the Master 512 is quite different from that of a standard PC-compatible. This is probably the most significant issue. On a true PC a number of peripherals operate by generating hardware interrupts. For example, a keypress or release generates Interrupt 9. These interrupts do not happen on the Master 512. The only hardware interrupt is Interrupt Ch which is generated by the use of the Tube by the host. This is naturally very different from the same interrupt on other machines.|
|The system software is structured differently. With MS-DOS the BIOS is quite distinct from DOS itself. (DOS is in one file on the boot disk; the BIOS is split between the ROM and a second file.) These two sections of the software communicate with one another by means of interrupts, so when MS-DOS needs to call a more fundamental BIOS routine then it does so through the standard interrupt vectors. DOS-Plus, on the other hand, is a more integrated system. In DOS-Plus the basic routines are usually called directly rather than through the vectors. Much of the time this makes no difference, but it does affect certain programs which intercept the BIOS vectors. These programs (often the "pop-up" types) expect calls to be made through the BIOS vectors, but with DOS-Plus the calls do not come. A common consequence is that the "pop-up" program does not pop up.|
|With MS-DOS there are a number of "undocumented" interrupt functions. DOS "hackers" have managed to deduce the purposes of a number of these, and they are described in many of the reference books available (though not the "official" ones). Some of these turn out to be useful and programmers have used them. (Again, it tends to be "pop-up" TSRs.) However, hardly any of these functions are supported by DOS-Plus.|
|Because the Master 512 is constructed as it is, quite different from a standard PC, there are some interrupt functions provided to make use of its unique facilities. These include functions which access the host machine but there are others as well. Such functions, of course, will never be used by programs written for PCs. However, programmers writing specifically for the Master 512 may like to use them. None of these are adequately described elsewhere, so some detail is given below.|
|Some functions normal to DOS were never implemented in the 512's version. This is in addition to those which would be impossible or impracticable because of the hardware differences. Some of the less central functions have simply been left out. It appears that the programmers did intend to include some of them but, in the event, never actually did so.|
|Last and (hopefully) least, there are a few bugs. To be fair, it was not simple to make DOS work on a system quite different from the one it was originally designed for, and given the complexity of the task the bugs are remarkably few. Quite possibly most of the ones that remain would have been ironed out had the programmers been allowed a bit longer. However the fact remains that there are a few small system faults.|
The above may help to give some insight into why differences exist between the interrupt functions in Master 512 DOS-Plus and those in a standard MS-DOS PC. To list them, though, I have found it easier to use a somewhat simpler classification. First there are those interrupts or subfunctions which are provided in MS-DOS but which do not exist at all on the 512 or for which the implementation is incomplete. Secondly, there are the interrupts which can be found in both types of machine but which are implemented in a rather different way. (Sometimes the difference is minor; sometimes it is total.) Thirdly, there are the interrupts and functions which appear only in DOS-Plus, some of which are unique to the 512. The following list divides things up in this way.
No attempt has been made to allow "print screen" to work on the 512, and it does not appear that there was ever any intention of including the facility.
On a PC this happens whenever a key is pressed. Because the Master 512 works quite differently, this interrupt does not happen. It is sometimes used by pop-up programs, and the fact that it does not occur on the 512 may cause such programs to fail. However, the programs have to read the keyboard hardware directly, so even if the interrupt were simulated on the 512, it would not be easy to design it to allow these programs to work.
These are not supported, but they are unlikely to cause any problems that could ever have been solved otherwise. They are low-level hardware interrupts never called by the system. Some software (especially comms programs) might intercept them to use direct hardware manipulation, but again the Master 512's hardware is very different and it would have been extremely difficult, if not impossible, to allow these programs to work correctly.
The Master 512's screen attempts to emulate CGA, within the limitations of the hardware. The restrictions are primarily to do with the number of colours available. However, certain other features which might have been supported are not. These are:
|The cursor type cannot be changed. It remains fixed as the
familiar "below the line" type of cursor.
|Only one display page is possible.
|There is no light pen support.|
Of these, the last is insignificant. Very few programs use a light pen, and they do not work in the same way with more modern PCs in any case. The other two features could have been implemented fairly easily, but have not been. Consequently, this interrupt does not support Functions 1, 4, or 5. Naturally, because of the second of them, the display page number (normally passed in BH) is always ignored in other functions.
See below for Function 10h of this interrupt.
This is not implemented at all on the 512. For most of the functions it normally handles this is of small importance. These functions include support for the cassette system (on early PCs) and the joystick. There are also various other functions not implemented on all machines so rarely used. On a true PC, though, the interrupt is called at various times, such as at the completion of processing a character after a key-press. Some programs might intercept the system at these points, and such are not going to work on the 512. However, there do not seem to be many programs like this.
This is only implemented on genuine IBM machines (not compatibles by other manufacturers). No-one is going to miss this interrupt.
This function is meant to read or write the DOS clock counter. However, because of a bug in the system it will only read it on the 512. (In the interrupt handling code, AH is cleared before it is tested.) There has been no attempt to enable access to the Master host's real-time clock through this interrupt.
These functions of Interrupt 21h are not officially documented by Microsoft or IBM, though they do exist and are sometimes used by programs. They are not supported in Master 512 DOS-Plus. The lack of any of them might, in theory, cause a program to fail, but in practice most of them are rarely used except by sophisticated disk-handlers which are probably not going to work on the 512 in any case. The one that is likely to cause problems is Function 34h, which normally returns the address of a flag indicating whether the processor is currently within the DOS system (rather than in a program's own code). It is used by interrupt-driven routines (again usually TSRs) to avoid re-entrant calls to DOS. The absence of an "in-DOS flag" means that some such programs will often work but can occasionally crash the system unpredictably.
Note that Functions 50h and 51h of Interrupt 21h are implemented in Master 512 DOS-Plus, though they are officially "undocumented". Function 37h is partially implemented. (See next entry.)
The switch character is the character supposed to be used to specify "command line switches". It is normally set to "/". This function is officially "undocumented", but in MS-DOS it can be used to read or write the switch character. In 512 DOS-Plus only Subfunction 0 (read the character) is supported. Read the documentation on FIDDLOAD for instructions on how to set the switch character, and the limitations on doing so.
The documentation status of this function is obscure. It began as "undocumented" but its existence has since been acknowledged. It is only partially implemented in DOS-Plus on the Master 512. The allocation strategy cannot be altered in DOS-Plus, so Subfunction 0 always returns with the value 1 ("best fit" strategy) and any attempts to change the strategy are ignored. It is hard to see why anyone would want to change it anyway.
This is another "undocumented" feature of MS-DOS. With MS-DOS, when DOS is "idling", such as when waiting for keyboard input, this interrupt is called regularly. This gives programs which operate in the background an opportunity to get on with some processing and to use DOS while it is otherwise doing nothing. The calls through the interrupt vector are not made under DOS-Plus.
Yet another "undocumented" function. The lack of this one is not going to cause any problems for 512 users. It is called when a character is written to a device, and may be used by device drivers. However, MS-DOS style device drivers cannot be made to operate with the 512, so no harm is done by not providing the interrupt function. See the FIDDLOAD documentation for a little more on device drivers and the Master 512.
This is not provided as standard with MS-DOS, but is implemented through a separate mouse driver file supplied along with any PC mouse. Although a mouse is supplied with the Master 512, no mouse driver software is provided to go with it. (Click here for a mouse driver for the Master 512.)
Many true PC's are wired up to generate an NMI only on some fatal hardware fault (such as a RAM failure detected by a parity error). The 512 uses the NMI in a totally different (and unique) way to get round what might otherwise be a serious problem. This does not need to worry you, and it will not cause any incompatibilities. Only read the next few paragraphs if you are interested to know why the 512's NMI system is designed as it is.
The problem that must be overcome arises because of a hardware defect in many CGA boards on true PCs and compatibles. Many older systems with CGA are afflicted with what is called "snow" – white or coloured flickering spots all over the screen. With these machines snow will happen if a program writes to the screen adapter memory at the same time as the video system itself is reading data from this memory to display on the screen.
Programmers soon found a way of avoiding the snow problem. The technique is to make sure that your program only writes to screen adapter memory during the re-trace intervals. (The re-trace intervals are the times when the electron beam that scans the screen is being whisked back to start the next line or the next screen). During these intervals the screen memory is not being read by the video system. Programs can identify re-trace intervals by examining one of the video system's status registers. The relevant one is located at input port 3DAh on a true compatible. A couple of bits in this register – one for the horizontal re-trace interval and one for the vertical – are set during the intervals. Many programs, especially the better ones, use this method of snow avoidance on CGA screens.
Now consider what will happen if a program using this technique is run on a Master 512. As soon as it needs to display anything on the screen the program will begin to examine input port 3DAh, waiting until one or other of the appropriate bits is set. On the 512 this port is not connected to anything and reading it could return any value at all. There is a high probability that the bit the program is looking at will always appear clear. This will cause the program to freeze in a small loop, waiting for something that is never going to happen!
The NMI is used on the 512 to escape from this situation. The NMI line is actually connected to the output of a timer. (The 80186 contains a number of timers as part of its design.) This means that NMIs happen at regular intervals. When one occurs, the system first examines the DX register. If this turns out to have the value 3DAh, the system next looks at the instruction currently being executed by the main program. If this happens to be an IN instruction using DX, then the system knows (or rather assumes!) that the current program is using the technique just described. What then happens is that the few instructions which form the polling loop are over-written with other instructions (mostly NOPs) so that the test is no longer carried out.
So now suppose that the processor gets itself caught up in one of these little polling loops. Sooner or later an NMI will occur, and before long one will occur just as the IN instruction is about to be issued. (The fact that the NMI line is used means that it does not matter if normal hardware interrupts have been disabled.) The interrupt handler will then change the main program a little, and the processor can get on with displaying the character. Next time the same routine is called the polling loop will no longer exist, so displaying the character will be much faster.
It has to be admitted that, when you think about this, it looks very like a bodge. However in practice it works surprisingly well.
It may be worth noting that the NMIs are only enabled in PC screen modes 0 to 3. Modes 4 to 6 are not subject to "snow", so programs using these modes do not need to use the snow-prevention technique. Mode 7 is not a true PC mode, so the NMI action could have no point in this mode.
This does nothing except call Interrupt 1Ch and preserve a few registers. It is called once every three VSync events. This gives it a call frequency of 16.7 times per second, which is not all that far away from the PC standard of 18.2 times per second, but it is too far away for it to be used to control the system clock.
This is totally different on the Master 512 from any other machine since it is the hardware interrupt used by the Tube. Any problems caused by this being different from MS-DOS are likely to be few, and in any case they are inevitable. Leave this interrupt strictly alone!
When called from a user program this interrupt works as normal. (Only Functions 0, 1 and 2 are supported, but this is the standard on the original PC and XT.) The main difference from MS-DOS is that in DOS-Plus the console input functions of Interrupt 21h do not make calls through this vector. Once again, this can cause a problem with programs which intercept the vector, expecting it to be called whenever console input is requested.
There is one additional function for this interrupt, namely Function FFh. See below for details.
This function operates just like Function 0 of Interrupt 10h (set screen mode), except that it does not clear the screen memory area. Naturally, this normally leaves the screen in a complete mess, and it is hard to see any purpose for it. It is apparently intended as a fix to make the Microsoft Flight Simulator work.
Note that this function has a completely different meaning on PCs fitted with EGA, MCGA or VGA cards. It is normally unsupported on CGA machines.
DOS-Plus is designed to be compatible with both the MS-DOS and CP/M-86 operating systems. It thus responds both to Interrupt 21h (the normal MS-DOS interrupt) and Interrupt E0h (the CP/M interrupt). There are certain features of the system, though, which normally operate slightly differently under CP/M from the way they operate under MS-DOS. Consequently, DOS-Plus runs in two modes, known as PC Mode and CP/M Mode.
In normal use, the machine is in CP/M Mode when it is at the command line, or when a .CMD program is running. It is in PC Mode when a .COM or .EXE program is running. (Loading a second copy of COMMAND.COM allows you to work at the command line in PC Mode. This is because by doing this you make COMMAND.COM into the running program, and it is a .COM program.)
There are two obvious differences between the two modes. The first is that in PC Mode there are 25 lines available on the screen, in CP/M Mode there are only 24 lines. (The bottom line is always left blank.) The reason for this is that in some versions of CP/M and DOS-Plus the bottom line is reserved for a status display. This was never implemented in the Master 512's version of DOS-Plus, but the provision for it remains. CP/M background programs (such as ALARM.CMD) can also use this line for messages.
The second difference between the two modes is that the keyboard responds differently for a few keys. In CP/M Mode the Delete key (on the main keyboard) returns character 7Fh rather than character 8, the function keys are expanded (so f0 starts GEM, for example), and the cursor "arrow" keys behave differently.
There are also other, less obvious, differences between the two modes. XIOS function 8Bh works differently, for example.
You can safely swap between the two modes using Function FFh of Interrupt 16h. (Do not do anything too drastic, like trying to enter the background from PC Mode.) Call the interrupt with:
AL=0 - to enter CP/M Mode
AL=1 - to enter PC Mode
Note that if you enter CP/M Mode from PC Mode while the cursor is on the bottom line of the screen, then the screen will scroll up by one line.
These interrupts give access to the normal MOS functions in the BBC Micro host. They are implemented in the 512's ROM rather than in DOS-Plus, and are really intended for use by the 80186 Monitor and any stand-alone 80186 programs which are to be run directly from the Monitor rather than from DOS (but like what?).
With care, you can use these from DOS programs to utilize the facilities of the host machine. This might be, for example, to read or write a BBC format disk.
|First and most important, before using any one of them you must "claim" the Tube. You do this using XIOS function 81h. Equally important, after using the function you must "release" the Tube with XIOS function 82h. Failure to do either of these guarantees that the machine will crash.|
|Secondly, some of the interrupts do not behave as you might at first expect. Note the bug in Interrupt 45h (OSFILE). Also, you need to be careful with any MOS functions which normally affect the screen. Unless you have selected DOS Screen Mode 7, the DOS screen is regularly updated across the Tube, as described in the article on the operation of the screen.|
|Thirdly, and this is perhaps the most awkward problem to get round, you must be very careful with any functions which may cause the BBC Micro host to generate an error. This is most likely with OSCLI or one of the filing system functions. If a host error occurs while processing one of these functions, then the Tube protocol will not be completed and the machine will hang. (To be strictly accurate, this will only happen for those functions for which the protocol is not completed before the action. This means everything except OSWRCH and OSBYTEs &82, &83, &84 and &9D.) To get round this you must set up some method of "breaking in" to a loop (probably using a timer tick), and regularly use XIOS function 87h to check whether an error has occurred. If one has, then your program will need to take appropriate action, including restoring the stack and releasing the Tube.|
These complications (especially the third one) may lead you to conclude that it is better to get at the MOS functions by directly manipulating the Tube registers (in a similar way to that described for OSFILE below). You can then check for errors at the point when they might occur. Chapter 12 of Watford's Advanced Reference Manual for the BBC Master gives details of the protocols, except that the one for OSFILE is misleading.
If you do want to use any of Interrupts 40h to 4Ch, details about how to use them (though without mentioning any of the above difficulties) can be found in Chapter 6 of Robin Burton's Master 512 Technical Guide, in Chapter 14 of Watford's Advanced Reference Manual for the BBC Master, or in the Master 512 : Technical Information and Monitor Documentation from Acorn. (Be careful – there are misprints and other errors in all of these.)
There is a unifying logic about how the calling parameters are related to those of the host. Data in AL corresponds to that in the 6502's A-register. The CF bit is used for the 6502's C flag. BL corresponds to the 6502's X-register and BH to Y. So when calls pass data in a control block (including a character string terminated with a Return character), then DS:BX is a pointer to the block. There is one exception (surprise, surprise!) With OSARGS, BX is used as a pointer to the data block. (In the host only X is used, assuming that the block is on page zero.) This means that AH has to be used for Y.
For completeness, the calls are summarized here:
Function code in AL; If AL=0, handle of file to close in BH, otherwise DS:BX points to the name of the file to be opened. File handle returned in AL. (0 means failure, as normal.) [None of the three documents referred to above mention the use of BH for the file handle when closing a file.]
Function number in AL; DS:BX point to control block. C value returned in CF. [A curiosity here – the documents state that this call will return with AL=0 if the call is attempted. This is true with Acorn's own DFS and ADFS, but only because they break Acorn's own rules! (OSGBPB should preserve A.) It would be unwise to rely on this feature!]
Handle in BH; byte to write in AL.
Handle in BH; byte value returned in AL, C value in CF.
Function number in AL; file handle or 0 (ie Y-value) in AH; DS:BX points to 4-byte parameter block. A-value (filing system number for call 0,0) returned in AL. 4-byte block can be anywhere in memory.
There is a serious bug in this. It will not work!
If you wish to use OSFILE, you can do it by reading and writing the control and data bytes "manually" to and from Tube Register 2. (See the article on Tube operation for a description of the Tube registers.) Unfortunately, the literature is misleading. The sequence you must follow is this (all bytes are written to or read from Tube Register 2):
|Claim the Tube (see above).|
|Use XIOS function 87h to clear the error occurrence flag.|
|Write a byte of value 14h. (This signals the start of OSFILE to the Tube host code).|
|Write the 16 bytes which would normally form the top 16 bytes of the OSFILE control block (ie not the two address bytes). The bytes must be written last byte first.|
|Write the characters of the file name (in the natural order), including the final Return character.|
|Write the function number value (6502 A-register value).|
|The operation will happen at this point. Then:|
Wait to see whether the function completes correctly or whether an error occurs. The best way is alternately to use XIOS function 87h and check Tube Status Register 2 for a returned byte.
|If an error occurs:|
|Release the Tube and take suitable action.|
|Read the returned A value (normally only relevant for function number 5, but it always has to be read).|
|Read 16 returned bytes. These are the bytes normally returned in the control block (apart from the first two), and again they are in reverse order.|
|Release the Tube.|
An alternative approach, if you just wanted to load or save a file, would be to create a *LOAD or *SAVE command line, and pass this to the host using Interrupt 4Ch (OSCLI). This would by-pass the bug by calling OSFILE from the host. You would still need to work out how to handle errors, though.
C value returned in CF; character value or error code in AL.
Character to write in AL.
(No entry conditions)
Character to write in AL.
Function number in AL; DS:BX points to parameter block. Function 0 returns C-value in CF and line length (excluding the Return) in BH.
Note that for non-zero OSWORDs, XIOS function 8Ah provides a "pre-packaged" OSWORD without the need for the Tube claims, and it is likely to be simpler to use.
This OSWORD interrupt can be used for OSWORD calls to Sideways ROMs (such as the ADFS or DFS OSWORDs) or for the 512's special OSWORD FAh. (There are bugs in this last one, though – see the discussion in Appendix F of the Master 512 Technical Guide. You need to patch the host code, using OSWORD 6.) The interrupt will not handle correctly the special DOS-Plus OSWORDs, FBh to FFh. You need to program these "manually".
To call a host OSWORD manually, follow this sequence (for all reads and writes use Tube Register 2):
|Claim the Tube (see above).|
|Note that most OSWORDs do not generate host errors. If you happen to be using one that might, then at this point use XIOS function 87h to clear the error occurrence flag.|
|Write a byte of value 8h. (This signals the start of non-zero OSWORD to the Tube host code).|
|Write the function number value (6502 A-register value).|
|Write the number of parameters in the parameter block.|
|Write the bytes of the OSWORD parameter block as the host would expect to find them, but last byte first.|
|The operation will happen at this point. If you need to check for host errors then do so here, eg in the way outlined under XIOS function 8Ah.|
|Write the number of parameters to be returned from the host.|
Read the returned parameters from the host. They will be returned in reverse order.
|Release the Tube.|
Function number in AL; X-value in BL; Y-value in BH; X and Y values returned in same registers and C-value in CF. If you wish to call OSBYTE from DOS it is easier to do it using XIOS Function 89h.
DS:BX points to the command string. Note that the system will first check the string for one of the 80186 Monitor's commands. If it finds one, it will act on this (with possibly disastrous results from inside DOS). Only if the Monitor does not recognize the command will it be passed to the host.
Like Interrupts 40h to 4Ch, this is implemented in the 512 ROM. However, unlike them it cannot be used from DOS. It is used by the Monitor to display messages and tidy up a little after an error. However it uses memory which is allocated to other purposes by DOS and code which has been overwritten by DOS-Plus on system boot. It will corrupt the system and almost certainly crash if called when DOS has been activated.
This interrupt can be used to perform numerous functions. The functions of this interrupt are not described here. See reference manuals on DOS-Plus or CP/M, or Appendix C of the Master 512 Technical Guide.
This interrupt merely returns in AX the segment address of the System Data Segment. (See the Master 512 Technical Guide or the article on the XIOS for an explanation of what this means.) The interrupt is provided primarily for the use of GEM which cannot use Interrupt E0h for some reason, but which still needs to know the position of this segment. There is nothing to prevent other programs using it to read the SYSDAT address, provided that they are not expected to work on any other machine than the Master 512.
This interrupt is designed to simulate an error. It will terminate a program with the message "Register dump" and the familiar (all too familiar!) display of 80186 register contents. Clearly this interrupt can have no purpose in a working program, but it might conceivably be useful while debugging.