Announcement

Collapse
No announcement yet.

In-Line Assembly for I/O Port to Memory Array

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

  • In-Line Assembly for I/O Port to Memory Array

    I can really use some assistance to help me determine why my
    simple assembly language subroutine does not function as I would
    like. What I need to do is move a number of 16 bit A to D
    converter values located at I/O port &H300 to an array in
    memory. The A to D values are in a First in-First out memory
    that will automatically address the next sample each time an “IN”
    instruction to port &H300 is executed. The transfers need to
    be done very quickly so have attempted to do the transfers via
    in-line assembly in a sub routine. I have established an
    ABSOLUTE array starting at &H30000 in which to put the A to D
    data values. The following test program shows what I would like
    to accomplish. When the program is run, it shows that memory
    locations that should have been replaced by the A to D port
    values remain as previously initialized.

    ' Test Program to put A/D Converter Values into memory array
    ' starting at addres &H30000

    DEFINT I 'All "I" Variables are Intergers (%)

    DIM ABSOLUTE AtoD??(1:32760) AT &H30000 'Create Large Array Starting
    'at address &H30000.
    DIM AtoDAddress AS DWORD PTR 'Address pointer to A to D Data
    AtoDAddress = &H30000 'Set the AtoD address pointer to the start of AtoD Data
    CLS

    PRINT "AtoDAddress Pointer is "HEX$(AtoDAddress)
    PRINT "Fill part of the AtoD array with known values"
    ' Want to fill the AtoD array with a seqence of known values
    I = 8
    W1?? = 0
    DO ' Fill AtoD array with words from 0 to 8
    @AtoDAddress = W1?? 'put Word value into AtoD array
    AtoDAddress = AtoDAddress + 2 ' Increment to next Word address
    W1?? = W1?? + 1 'Increment W1
    I = I - 1
    LOOP While I > 0

    PRINT "AtoDAddress Pointer is " HEX$(AtoDAddress)

    I = 0
    AtoDAddress = &H30000
    PRINT "AtoDAddress Pointer is "HEX$(AtoDAddress)
    ' Want to display the word values in the AtoD array
    DO ' Display AtoD array words from locations 0 through 8
    W1?? = @AtoDAddress 'put Array value into W1??
    PRINT "A/D Array Address/Values " HEX$(AtoDAddress), HEX$(W1??) ' Display
    ' address then Hex value
    AtoDAddress = AtoDAddress + 2 ' Increment to next Word address
    I = I + 2
    LOOP While I < 16
    PRINT "AtoDAddress Pointer is "HEX$(AtoDAddress)

    AtoDAddress = &H30000
    AddOffset?? = &H0000 ' Set address offset to 0000h
    NofS% = 6
    PRINT "Called INSTRING SubRoutine " (NofS%) (AddOffset??)

    CALL INSTRING(BYVAL NofS%, BYVAL AddOffset??) ' Call INSTRING

    I = 0
    PRINT "AtoDAddress Pointer is "HEX$(AtoDAddress)
    ' Want to display the word values in the AtoD array
    DO ' Display AtoD array words from locations 0 through 8
    W1?? = @AtoDAddress 'put Array value into W1??
    PRINT "A/D Array Address/Values is " HEX$(I), HEX$(W1??) ' Display address
    'then Hex value
    AtoDAddress = AtoDAddress + 2 ' Increment to next Word address
    I = I + 2
    LOOP While I < 16
    PRINT "AtoDAddress Pointer is "HEX$(AtoDAddress)

    END

    SUB INSTRING(BYVAL No%, BYVAL AddOff??) 'Move A/D Values to memory

    ! push DI ; Save DI
    ! pushf ; Save the flag register

    ! mov AX, &H3000 ; Move the segment 3000H to Register AX
    ! mov ES, AX ; Move the segment 3000H in AX to Register ES

    ! mov AX, AddOff?? ; Move Offset address into AX
    ! mov DI, AX ; Move the Address Offset in AX to Register DI

    ! mov CX, No% ; Move Number of A/D samples to CX
    ! mov DX, &H300 ; Move the A/D port address into DX

    ! cld ; Clear direction flag (to increment addrss pointer)
    TRANSDATA:
    ! in AX, DX ; Input A/D Word from I/O port &H300 & put into AX
    ! stosw ; Store A/D Word in [AtoDAddress] (ES I), Incr. DI,
    ! loop TRANSDATA ; Decrement CX. Jump to TRANSDATA if not zero

    ! popf ; Restore Flag Register
    ! pop DI ; Restore DI

    END SUB

    ------------------

  • #2
    Oh golly.

    Firstly, can you be sure there is nothing important at &H30000? Using an arbitary address like that seems quite unwise. Better you should DIM the array normally, then use VARPTR32() to obtain a pointer to the array. If you do so, you should notice the address provided is MUCH higher in memory.

    Next, what OS are you running under?

    Finally, when you say "does not function as I would like"... can you be a little more specific? What "fails" precisely?

    PS: When posting code, please use the [CODE] tags described at http://www.powerbasic.com/support/forums/ubbcode.html - Thanks!

    ------------------
    Lance
    PowerBASIC Support
    mailto:[email protected][email protected]</A>
    Lance
    mailto:[email protected]

    Comment


    • #3
      Thanks for your response Lance. You seem to have noticed that
      am a beginner at programing (this is my first effort to do any
      significant programing in any language). The test program that
      I included writes known values to the array then reads the known
      values back successfully. Then, the subroutine with the assembly
      language is called which is supposed to read from I/O port &H300
      and put the port values in the array. When the array values are
      printed out again, they have not changed from the original values.
      I assumed from this result that the assembly language subroutine
      is not functioning as I would like.

      I know it would be best to dimension an array normally as you
      suggest but I can't figure out how to get the Address for the
      array into the ES I registers so that I can put the I/O port
      values into the correct memory locations. I also need to be
      able to address any arbitrary location within the array - not
      just the start of the array.

      Comment


      • #4
        I forgot to mention that the operating system I'm using is IBM
        PC DOS 7.

        ------------------

        Comment


        • #5
          Try this to get you going:
          Code:
           dim x as integer, w(1:32760) as word
           x = varseg(w(1))
           !push DS
           !push DI
           !pushf
           !mov DX, &H300
           !mov ES, x
           !mov DI, 0
           !mov cx, 32760
           !cld
          TransData:
           !mov AX, CX  ; test purposes only, substitute "!in AX, DX"
           !stosw
           !loop TransData
           !popf
           !pop DI
           !pop DS
           print "Done! Test values:", w(1), w(16380), w(32760)
          ------------------
          Lance
          PowerBASIC Support
          mailto:[email protected][email protected]</A>
          Lance
          mailto:[email protected]

          Comment


          • #6
            Lance; Your suggestion works just fine as best I can tell at
            this time. Thanks Very Much! I now understand how to pass an
            address to an assembly language routine.

            I have placed the assembly code inside a Subroutine and I am
            passing BYVAL the number of transfers needed (mov CX, N%),
            the address segment (mov DS, S%) and the address offset into the
            data array (mov DI, o%). Everything seems to work fine but I
            would like to know if there are any restrictions to what I use
            for the address offset for the DI register other than to keep it
            an even number less than 32768?

            Comment


            • #7
              None that spring to mind over and above those you have mentioned.

              Of course, you could do more than 32768 elements in your "sample", but you'd have to add code to work across the segment boundary (that's what I love about Windows programming - flat addressing means no segments, and no segment boundary addressing to deal with! )

              Have fun with your project!

              ------------------
              Lance
              PowerBASIC Support
              mailto:[email protected][email protected]</A>
              Lance
              mailto:[email protected]

              Comment

              Working...
              X