Microsoft KB Archive/68908

Source Code: Calling DOS/BIOS Interrupts w/ FORTRAN and MASM

PSS ID Number: Q68908 Article last modified on 02-10-1993

5.00 MS-DOS MSINTERNAL | softlib q69152 S13012 appnote hf0405

Summary: The following article illustrates the source code on how to access DOS interrupts without using the functions INTDOS and INTDOSX. Listed below are two assembly code routines INTERRUPT and INTERRUPTX. An INCLUDE file and two FORTRAN sample programs demonstrate how to use the INTERRUPT and INTERRUPTX function calls. The application note titled “Calling DOS and BIOS Interrupts with FORTRAN and MASM” contains assembled versions of the MASM routines used to access DOS and BIOS interrups through FORTRAN. This application note is available from Microsoft Product Support Services. The text of this application note is also available in the Software/Data Library and can be found by searching on the word HF0405, the Q number of this article, or S13012. HF0405 was archived using the PKware file-compression utility.

More Information: DOS and BIOS interrupts can be called by specifying the interrupt number and the input register values within the main program. INTERRUPT(INTNUM,INREGS,OUTREGS) invokes the interrupt specified by the INTNUM using the values of INREGS and returns the result of the interrupt call in OUTREGS. INTERRUPTX(INTNUM,INREGS,OUTREGS) invokes the system in the same manner as INTERRUPT, but accepts segment register values. Microsoft cannot guarantee that the information stated here regarding how to use INTERRUPT and INTERRUPTX will perform all MS-DOS system or BIOS calls correctly because this information has not been tested rigorously and is not considered a feature of the product. A separate article with non-MSINTERNAL security describes how OnLine customers can obtain this file (FORINTER) in the Software/Data Library. FORINTER can be found in the Software/Data Library by searching on the keyword FORINTER or the Q number of this article. If you make changes to this article, the changes will also need to be made in the Software Library archive file and, if needed, in the non-MSINTERNAL article and in the Softlib database article. To utilize the INTERRUPT AND INTERRUPTX functions, the statement INCLUDE ‘INTERRPT.INC’ must be contained in the source file making the call. The two statement function definitions documented at the end of the INTERRPT.INC file must be uncommented and added to the source code of the main program. INTERRUPT.OBJ must be linked with the object file produced from compiling the main program. The following files define the INTERRUPT and INTERRUPT functions, and provide two FORTRAN sample programs demonstrating how these functions are called c******************* c INTERRPT.INC : include file for INTERRPT and INTERRPTX. C This file includes the INTERFACE to the assembler C routines and the register structures needed for these C routines. INTERFACE TO SUBROUTINE INTERRUPT + (intnum,inregs,outregs) structure /regs/ integer2 ax,bx,cx,dx,si,di,flags end structure integer2 intnum record /regs/ inregs [REFERENCE] ! Regs into ! INTERRUPT record /regs/ outregs [REFERENCE] ! Regs returned end INTERFACE TO SUBROUTINE INTERRUPTX + (intnum,inregsX,outregsX) structure /regsX/ integer2 ax,bx,cx,dx,si,di,es,ds,flags end structure integer2 intnum record /regsX/ inregsX [REFERENCE] ! Regs into ! INTERRUPTX record /regsX/ outregsX [REFERENCE] ! Regs returned end implicit integer (a-g) structure /wordregs/ ! Full word registers integer''2 ax,bx,cx,dx,si,di,flags end structure structure /wordregsX/ ! Full word registers integer2 ax,bx,cx,dx,si,di,es,ds,flags end structure integer2 intnum ! Interrupt number record /wordregs/ inregs,outregs record /wordregsX/ inregsX,outregsX c Copy these lines after your other declarations in your c main program c gethibyte (dataword) = dataword / 256 c getlobyte (dataword) = iand(dataword, 255) c''******************** ;********************* ; INTERRPT.ASM The assembler source listing of the INTERRUPT ; and INTERRUPTX routines. ; ; 15 october 1990 ; Program written by Thom Bierenbroodspot ; Microsoft B.V. ; The Netherlands .model large,fortran .code INTERRUPT proc far push bp ;Save necessary registers that mov bp,sp ;will be altered push di push si push es mov bx,[bp+0ch] ;Get segment of inregs mov es,bx ;move segment in es mov si,[bp+0ah] ;Get offset of inregs mov cx,07h ;Number of registers to load mov bx,02h ;Replacement of offset index ; getregs: mov ax,es:[si] ;get value of ax from inregs ; and save push ax ;continue with bx,cx..flags add si,bx ;Adjust offset with ; replacement loop getregs ;get far address interrupt from vectortable ;get interrupt number mov bx,[bp+10h] ;Get segment of intnum mov es,bx ;move segment in es mov si,[bp+0eh] ;get offset of intnum mov bx,es:[si] ;get value of intnum ;adjust to offset in vectortable sal bx,1 ;ShiftL2 for for 4 byte ; replacement in sal bx,1 ;vector table mov si,bx ;save in si xor bx,bx ;zero bx mov es,bx ;load 0 segment in es mov bx,es:[si] ;load offset of interrupt from ; table mov ax,bx ;save offset in ax mov bx,es:[si+2] ;load segment of interrupt ; from table ;and save far address on stack mov [bp+0eh],ax ;save offset on stack for use ; with call mov [bp+10h],bx ;save segment on stack for use ; with call popf ;load flags and registers pop di pop si pop dx pop cx pop bx pop ax pushf ;do the actual int x call dword ptr [bp+0eh] endprocint: pushf push di push si push dx push cx push bx push ax mov bx,[bp+08h] ;Get segment of outregs mov es,bx ;move segment in es mov si,[bp+06h] ;Get offset of outregs mov cx,07h ;Number of registers to save mov bx,02h ;Replacement for offset index saveregs: pop ax ;get value of ax and store it ; in outregs mov es:[si],ax ;continue with bx,cx..flags add si,bx ;Adjust offset with ; replacement loop saveregs pop es pop si ;restore values of saved ; registers pop di ;before returning from the ; procedure pop bp ret 12 ;and finish procedure INTERRUPT endp INTERRUPTX proc far push bp ;Save necessary registers that mov bp,sp ;will be altered push di push si push es push ds mov bx,[bp+0ch] ;Get segment of inregs mov es,bx ;move segment in es mov si,[bp+0ah] ;Get offset of inregs mov cx,09h ;Number of registers to load mov bx,02h ;Replacement of offset index getregsX: mov ax,es:[si] ;get value of ax from inregs ; and save push ax ;continue with bx,cx..flags add si,bx ;Adjust offset with ; replacement loop getregsX ;get far address interrupt from vectortable ;get interrupt number mov bx,[bp+10h] ;Get segment of intnum mov es,bx ;move segment in es mov si,[bp+0eh] ;get offset of intnum mov bx,es:[si] ;get value of intnum ;adjust to offset in vectortable sal bx,1 ;ShiftL2 for for 4 byte ; replacement in sal bx,1 ;vector table mov si,bx ;save in si xor bx,bx ;zero bx mov es,bx ;load 0 segment in es mov bx,es:[si] ;load offset of interrupt from ; table mov ax,bx ;save offset in ax mov bx,es:[si+2] ;load segment of interrupt ; from table ;and save far address on stack mov [bp+0eh],ax ;save offset on stack for use ; with call mov [bp+10h],bx ;save segment on stack for use ; with call popf ;load flags and registers pop ds pop es pop di pop si pop dx pop cx pop bx pop ax pushf ;do the actual int x call dword ptr [bp+0eh] ;end procedure pushf push ds push es push di push si push dx push cx push bx push ax mov bx,[bp+08h] ;Get segment of outregs mov es,bx ;move segment in es mov si,[bp+06h] ;Get offset of outregs mov cx,09h ;Number of registers to save mov bx,02h ;Replacement for offset index saveregsX: pop ax ;get value of ax and store it ; in outregs mov es:[si],ax ;continue with bx,cx..flags add si,bx ;Adjust offset with ; replacement loop saveregsX pop ds pop es pop si ;restore values of saved ; registers pop di ;before returning from the ; procedure pop bp ret 12 ;and finish procedure INTERRUPTX endp end ;*************** c*************** c INT.FOR A sample program which uses the INT 21, c function 2A hex to get the system date. c c Call MS-DOS interrupt 21 hex, with function 2A hex to get c the system date. INCLUDE ‘interrpt.inc’ gethibyte (dataword) = dataword / 256 getlobyte (dataword) = iand(dataword, 255) inregs.ax=#2a00 ! Function number intnum=#21 ! Interrupt number call interrupt(intnum,inregs,outregs) ! Call interrupt write (,) ‘Using INT 21, function 2A’ write (,) ’ Month= ‘, gethibyte(outregs.dx) ! High byte = month write (,)’ Day = ‘, getlobyte(outregs.dx) ! Low byte = day write (,)’ Year = ‘, outregs.cx ! Year end c*************** c*************** c INTX.FOR: A sample program which uses the INT 21, c function 41 hex to delete a file. c c Call MS-DOS interrupt 21 hex, with function 41 hex to c delete a file. c This example uses the segment registers. include ’interrpt.inc’ character filename''12 ! File to delete integer''2 flen ! Length of filename integer''4 addr ! Location of filename gethibyte (dataword) = dataword / 256 getlobyte (dataword) = iand(dataword, 255) print 10 10 format (’ Enter name of file to delete -> ’,$) read ('',‘(a)’) filename ! Get the file to delete flen=len_trim(filename) ! Remove extra spaces filename=filename(:flen)//char(0) ! Must be an ASCIIZ ! filename addr=locfar(filename) ! Get the segment and ! offset ! of the file intnum=#21 inregsX.dx=iand(addr,#FFFF) inregsX.ds=ishft(addr,-16) inregsX.ax=#4100 ! Function number call interruptX(intnum,inregsX,outregsX) ! Call DOS interruptX if (iand(outregsX.flags,1).eq.0) then ! No error on delete write (,) ‘File deleted successfully!’ else ! Error if carry is set write (,) ’ File not deleted! Status= ’, + outregsX.ax endif end c***************