================================= [ QuickBasic 4.5 Tutorial ] [ How To Use Interrupts ] [ Copyright (c) 1996 by Tika Carr ] ================================= (Please read disclaimer at the end of this tutorial.) This tutorial hopes to cover the basics of how to use Interrupts in QuickBasic. Note that this method only works in QuickBasic 4.5. I hope to do a tutorial for those who use QBasic (which comes with MS-DOS 5.0 and higher). 1. Getting Started You will need to have started QuickBasic 4.5 by typing the following at the MS-DOS prompt: QB /L QB.QLB This QuickLiBrary will load in what you need to use interrupts. Many new programmers avoid using interrupts because they are afraid to damage their computer. I've noticed people mess up their system *without* using interrupts. Sections 7 - 9 have some tips on safe debugging and what to do if you have a crash. Further, BACK UP YOUR HARD DRIVES! This is MOST important! And save your programs onto floppy diskette before you run them. Ultimately, its still up to you to protect your system. This goes for any type of programming. 2. Your First Interrupt Type in the following and save it, then run it. We'll look at the program and see how it all works in a moment. =======>8 Snip 8<======= 'Example Program for CALL INTERRUPT Tutorial 'by Tika Carr '$INCLUDE: 'QB.BI' DIM Inregs AS RegType, Outregs AS RegType 'Int 10h (interrupt 10 hexadecimal) controls the video part. '0Ah tells the computer to write a character on the screen. 'We'll put the letter 'A' on the screen in this example. CLS Inregs.ax = &HA41 'load high and low bytes into ax register (&H0A01) Inregs.cx = 1 'write only 1 character CALL INTERRUPT(&H10, Inregs, Outregs) 'put the character on the screen =======>8 Snip 8<======= '$INCLUDE: 'QB.BI' defines the type structures used for the interrupts. DIM Inregs AS RegType, Outregs AS RegType The INCLUDE statement defines the type structures that is used for interrupts. These are found in the QB.BI file that comes with QuickBasic 4.5. The DIM Statement lets you specify what variable to put the registers defined in RegType in, so that its easy to pass all the registers to the interrupt. 3. What are registers and what do they do? A register is a place where you store values, and is a more direct way to communicate with the computer. The computer looks into registers for specific values, and uses them to perform different tasks. For example, we gave the computer some information in the AX register, telling it we wanted to write something on the screen, and what we wanted to write to the screen (the letter 'A'). We also put a value into the CX register, telling the computer we wanted to write only one copy of the letter 'A'. When you call an interrupt, you send all that information along to the computer (int 10h, which accesses your video). Basically, we just told the computer to PRINT "A" on the screen. Registers also let the computer send information back to your program. For example, INT 33 can give your program the X and Y coordinates of where the mouse currently is located. For CALL INTERRUPT: ax, bx, cx, dx, bp, si, di, flags Defined as RegType FOR CALL INTERRUPTX: ax, bx, cx, dx, bp, si, di, flags, ds, es Defined as RegTypeX Depending on the interrupt you want to use, you will need to pick the type of call that suits it. For instance, if you don't use the es register, then using CALL INTERRUPT would work fine. However, if the computer will be looking into the es register for something, or if you will need to know what is in the ds register, you will want to use the CALL INTERRUPTX. These definitions are all in the QB.BI file. You '$INCLUDE: 'QB.BI' in your program, then you DIM Inregs AS RegyType, OutRegs AS RegType. These will set up your variables so that you can access the registers. To put something into the registers, you use Inregs, and to read the registers, you use the OutRegs variable: Inregs.ax is where you would put something in the AX register. Outregs.cx is where you can find what the computer put in the CX register. 4. Storing Values into Registers: Since the registers take information in bytes only, you may have to do some converting to load the registers properly. Many times an interrupt listing will show something like: Interrupt 10h: Video Entry: ah = 0A write a character to the screen al = value of character to write bh = video page bl = attribute or color of character cx = number of times to write the character This can seem confusing. How do you load the AX register? Where IS it? There's an AH and an AL. These mean the High and Low bytes of the AX register, respectively. Here's how you would put a value into the AX register: Inregs.ax = &HA41 'load high and low bytes into ax register (&H0A01) (Note that QuickBasic likes to take away the leading 0s. Initially, we typed it as: Inregs.ax = &H0A41) The values go into the registers as: 0A41 HiLo Most of the time, you probably will run into this situation: Video$ = "0A" ' Tell computer to write to video Character$ = "A" ' Character to write on screen Here is how you would get it all into one register: Character$ = HEX$(ASC(A)) ' Convert 'A' into its ASCII value in ' Hexadecimal. Since Video$ already is in Hexadecimal, we won't need to change it. Now, we put them together: AX$ = Video$ + Character$ ' AX$ now contains 0A41 PRINT AX$ to ' see for yourself. Now that we got the full Hexadecimal value to put into the AX register, we still have to convert this into a *number*: Inregs.ax = VAL("&H" + AX$) This makes the string now say "&H0A41" and it also converts it into a numeric value (using VAL). Now you have the high and low bytes converted and stored into the AX register that will go into the computer (Inregs). When you do the CALL INTERRUPT (&H10, Inregs, Outregs), the values will be correctly loaded where the computer can find them. 5. Reading the Registers Outregs also holds register values. After you make a CALL INTERRUPT, you can read, let's say, the high and low bytes of the BX register and use it in your own program: BX$ = HEX$(Outregs.bx) ' Convert the value to Hexadecimal, its ' easier to extract the high and low bytes ' this way. Since the computer likes to truncate leading 0s, we have to convert the value of BX$: ' Get Low and High Byte of BX ' BH$ is the high byte, BL$ is the low byte, both in Hexadecimal. L = LEN(BX$) IF L = 1 THEN BH$ = "0" + BX$: BL$ = "00" IF L = 2 THEN BH$ = LEFT$(BX$, 2): BL$ = "00" IF L = 3 THEN BH$ = "0" + LEFT$(BX$, 1): BL$ = RIGHT$(BX$, 2) IF L = 4 THEN BH$ = LEFT$(BX$, 1): BL$ = RIGHT$(BX$, 2) bh = VAL("&H" + BH$) ' Decimal Value of high byte of BX bl = VAL("&H" + BL$) ' Decimal Value of low byte of BX Note that this is only applicable for any register you need to get specifically the low and high bytes of. Sometimes a register is a pointer to a memory address. If that is the case, you can just use that value directly, without any type of conversion. For example: Address = Outregs.es Value = Outregs.dx POKE Address, Value ' Or do whatever you need to with the address returned. 6. Calling the Interrupt When you do a CALL INTERRUPT you access a certain function within the computer. For example, in CALL INTERRUPT(&H10, Inregs, Outregs) you called the video interrupt 10h (&H10). Its best of course, to know what interrupt does what, what to put into the registers, and what the registers may return to your program that you may be able to use. The best Interrupt source I've found is Ralph Brown's Interrupt List, found on some programming BBSs and on the internet on different FTP sites (like Oakland, SimTel, and Garbo, which you can get current addresses for by searching Lycos at http://lycos.cs.cmu.edu) 7. What To Do About Crashes a) BACKUP YOUR PROGRAMS BEFORE RUNNING THEM! First and foremost, its good practice to save your program onto a floppy diskette before you run it. When your system crashes and you get back in, just reload the program into QuickBasic. b) System Crashes If your system crashes, or seems to hang, first try hitting CTRL-C or CTRL-Pause (which is also CTRL-Break). You may have to hit ENTER afterward to get back to the QuickBasic Interactive Debugging Editor (IDE) to look at your program. If this don't work, reboot the computer with CTRL-ALT-DEL (or hit the RESET button on the computer if that didn't work). Then reload and take a look at your program. If worse comes to worse, you can shut off the computer, wait a few moments and turn it back on. Personally, I have always been able to recover by breaking out of the program with CTRL-Break. c) Disk FAT crashes This is one situation that could occur if you are using interrupts to access the disk drives or hard disk, and you didn't get things loaded in right. Best to have your hard drive backed up before each programming session if you know you'll be using interrupts that will access the disk drives (ie. may have potential of writing to sectors or the FAT). Another good thing to have on hand is some utilities that repair damaged FAT tables and such. There are a number of good commercial programs out there, and some shareware ones as well. Put one of these on a bootable floppy. d) Video, Sound and other hardware Its rare that you can actually damage hardware with an interrupt call. If something goes "haywire" the best bet is to just hit the reset button on the PC right away. Usually, things will then reset and recover. 8. Safe Debugging Once you get your program written, put a remark before the CALL INTERRUPT: 'CALL INTERRUPT (&H10, Inregs, Outregs) Then set up the Debug to watch your variables: HEX$(Inregs.ax) HEX$(Outregs.bx) Or whatever variables you are working with. Then ALT-R R to restart. NOW SAVE THE PROGRAM TO FLOPPY DISK! Remove the disk from the drive. Hit F8 to step through your program one instruction at a time, paying close attention to the values in the variables. Are they loading properly? Once you think its working, you can again save the program and then remove the remark from the call. Step through again and pay attention to the Outregs registers if you are using them. It may seem like a lot to go through, but watching how your program works step by step, especially if you're first learning to use interrupts, will show you how the computer uses them, and how your programs behave (for better or for worse). 9. In Closing.... Interrupts are a great way to do things in QuickBasic that you can't find a command for. Normally, they don't hurt anything and at worse, just make you have to restart the computer. While a risk is there to mess up things like hard drives, its rare you'll run into that, if at all, as long as you don't use disk interrupts until you are comfortable with how interrupts work and how to use them. Stick with writing for video, mouse, printer, sound card for starters. Video is easiest, as is the mouse. And if weird things happen, don't panic - reset. :) ******* DISCLAIMER ******* The author of this article cannot gaurantee the usability or suitability of the information presented herein for any particular purpose. In addition, the user of the information in this article agrees not to hold the author, moderator or any other direct or indirect agent liable in any way for any damages, loss of data, or other consequences arising from use of this information. While I have made every conscious effort to ensure the information in this tutorial is accurate and safe to use on any PC compatible in the QuickBasic 4.5 environment, the end result depends on the person making use of the information presented here. Use the information in this tutorial at your own risk. ******* CONTACT INFORMATION ******* As of 8/3/96, comments, questions and suggestions, can be directed to: FidoNet: Tika Carr 1:2613/601 or 1:2613/313 Internet: t.carr@pobox.com ===================================================================== Tika Carr, former staff writer and later editor of GEnieLamp PC Multimedia Magazine, has been writing QuickBasic 4.5 programs since 1989, and is a frequent contributor to the QUICK_BAS FidoNet Echo. Her area of specialty is in "tools that make tools" (Steven Levy, "Hackers"), meaning anything that will make things easier for programmers to take control of the computer, and make their imaginations come alive. ===================================================================== Microsoft, QuickBasic 4.5, and QBasic are trademarks of Microsoft Corporation. MS-DOS is a registered trademark of Microsoft Corporation.