Announcement

Collapse
No announcement yet.

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

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

  • Lance Edmonds
    replied
    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>

    Leave a comment:


  • Alan Wirtz
    Guest replied
    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?

    Leave a comment:


  • Lance Edmonds
    replied
    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>

    Leave a comment:


  • Alan Wirtz
    Guest replied
    I forgot to mention that the operating system I'm using is IBM
    PC DOS 7.

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

    Leave a comment:


  • Alan Wirtz
    Guest replied
    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.

    Leave a comment:


  • Lance Edmonds
    replied
    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>

    Leave a comment:


  • Alan Wirtz
    Guest started a topic In-Line Assembly for I/O Port to Memory Array

    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

    ------------------
Working...
X
😀
🥰
🤢
😎
😡
👍
👎