Announcement

Collapse
No announcement yet.

REG command / CALL INTERRUPT

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • REG command / CALL INTERRUPT

    I have recently converted a QuickBasic program to PB/DOS 3.50.
    This program reads a disk's serial number and media type using interrupt &h21.

    Obviously, something went wrong, as the results contain nothing but chr$(0).
    But when I replaced the REG and CALL INTERRUPT commands by their ASM equivalents the program worked fine.

    Can anybody tell me what went wrong?
    Thanks a lot for your help!

    Heinz Salomon
    Code:
    ' Gets a disk's media descriptor and also its serial number.
    ' Based on an idea by Ethan Winer (SERIAL 1.0).
    '
    
    $ERROR ALL ON
    
    %UsePureAsm = 1
    %UseCallInterrupt = 0
    %CompileVar = %UseCallInterrupt
    
    %AX = 1
    %BX = 2
    %CX = 3
    %DX = 4
    
    TYPE SNType
      Zero  AS INTEGER
      SerLo AS INTEGER
      SerHi AS INTEGER
      Label AS STRING * 11
      Media AS STRING * 8
    END TYPE
    DIM SN AS SNType
    
    CLS
    PRINT
    PRINT "Get a disk's media descriptor and serial number"
    PRINT "(based on Ethan Winer's SERIAL 1.0)"
    PRINT
    INPUT "Enter drive letter: ", DriveLetter$
    
    Drive% = ASCII(UCASE$(DriveLetter$)) - 64
    If Drive% < 1 THEN END
    
    SNoffset?? = VARPTR(SN)
    
    $IF %CompileVar
      ! MOV AX, &H6900
      ! MOV BX, Drive%
      ! MOV DX, SNoffset??
      ! INT &H21
    $ELSE
      REG %AX, &H6900
      REG %BX, Drive%
      REG %DX, SNoffset??
      CALL INTERRUPT &H21
    $ENDIF
    
    PRINT
    PRINT "Media descriptor: "; RTRIM$(SN.Media, CHR$(0))
    PRINT "   Serial number: "; padHex$(SN.SerHi%); "-"; padHex$(SN.SerLo%)
    
    END
    
    
    FUNCTION padHex$(rInt%)
      padHex$ = RIGHT$("000" + HEX$(rInt%), 4)
    END FUNCTION


    [This message has been edited by Heinz Salomon (edited May 25, 2005).]

  • #2

    >DS X = buffer to contain extended BIOS Parameter Block (~BPB~, AL=0)

    You didn't set DS to equal the stack segment, which is where it is when LOCAL.

    you can use this:
    Code:
    dsdx&     = VARPTR32(SN)
    REG %DS, dsDx \ &h1000
    REG %DX, dsDx MOD &h1000
    I think you also need to save and restore DS if you put this into a function

    FWIW, that call is clearly marked "undocumented DOS 4+"

    Michael Mattias
    Tal Systems (retired)
    Port Washington WI USA
    [email protected]
    http://www.talsystems.com

    Comment


    • #3
      Michael,

      my program works fine if I change the critical code portion according to your suggestion:
      Code:
         REG %AX, &H6900
         REG %BX, Drive%
           dsdx& = VARPTR32(SN)
         REG %DS, dsDx& \ &h10000
         REG %DX, dsDx& MOD &h10000
         CALL INTERRUPT &H21
      Conclusion:
      I erroneously assumed REG(%DS) contains the data segment by default.
      Instead, REG(%DS) must always be assigned explicitly before using CALL INTERRUPT, otherwise any junk it contains at that time gets filled into the 'real' DS register.

      Thank you!

      But why do you think the variable SN is stored on the stack?
      After all, it is declared in the main program and not within a sub or function.

      Heinz



      [This message has been edited by Heinz Salomon (edited May 26, 2005).]

      Comment


      • #4
        >But why do you think the variable SN is stored on the stack?

        I don't know that it is.. I guess I am now thinking purely in "windows mode" where I use essentially nothing but LOCAL vars which are stored on stack.

        All I know is you can always get segffset of any var using high and low 16 bits of VARPTR32 regardless of where that var is stored. I also never assume anything like "where is DS".. if doc says DSX needs to be set, I set DS and DX.

        Michael Mattias
        Tal Systems (retired)
        Port Washington WI USA
        [email protected]
        http://www.talsystems.com

        Comment

        Working...
        X