Announcement

Collapse
No announcement yet.

Accessing data in arrays

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

    Accessing data in arrays

    I knew I was going too well.

    Ok, what I'd like to do is something like

    Code:
    [Snip]
                                        !mov eax,0
                                        !add eax,n(g,a)
                                        !add eax,n(g,b)
                                        !add eax,n(g,c)
                                        !add eax,n(g,d)
                                        !add eax,n(g,e)
                                        !add eax,n(g,f)
                                        !cmp eax,3
    [/snip]
    but that falls in a heap PDQ so I guess I'm missing something profound, probably to do with pointers.
    Neil Croft (cissp)

    #2
    That or your array is not dimensioned. Or g,a, b, c,d,e, or f out of range. Code not shown. (snipped).
    Michael Mattias
    Tal Systems (retired)
    Port Washington WI USA
    [email protected]
    http://www.talsystems.com

    Comment


      #3
      Code:
      [Unsnipped bits]
          DIM n(162,49) AS LOCAL LONG
          LOCAL a,b,c,d,e,f,g,sc,bsc AS LONG
      and a,b,c,d,e,f and g are not out of scope. Error is

      Code:
      PowerBASIC Console Compiler
      PB/CC   Version 5.01 
      Copyright (c) 1998-2009 PowerBasic Inc.
      Venice, Florida USA
      All Rights Reserved
      
      Error 497 in C:\DOCUME~1\ADMINI~1\Desktop\assemb\phase-1.bas(91:001):  Assembler syntax error
      Line 91:                                     !add eax,n(g,a)
      ==============================
      Compile failed at 00:19:50 on 16/07/2009
      Neil Croft (cissp)

      Comment


        #4
        Neil,
        accessing a single variable in ASM is easy but accessing an element of an array involves calculating where that element is in the array and is a lot more complicated as it depends on the number of dimensions in the array and the sizes of those dimensions and the size of the element.

        Paul.

        Comment


          #5
          So, say 0-162, 0-49 and long?
          Neil Croft (cissp)

          Comment


            #6
            Neil,
            there are shortcuts that can be used but the following program shows you in seperate steps what you need to do.
            Code:
            'PBCC 5.01 program
            #DIM ALL
            #REGISTER NONE                 'advise you stop compiler using register variables while you experiment with ASM, it can cause confusion
            #INCLUDE "win32api.inc"
            
            FUNCTION PBMAIN () AS LONG
            LOCAL ArrayAddress, FirstIndexLimit, SecondIndexLimit, FirstIndex, SecondIndex AS LONG
            LOCAL BasicAnswer, AsmAnswer AS LONG
            
            FirstIndexLimit = 162
            SecondIndexLimit = 49
            
            DIM n(FirstIndexLimit,SecondIndexLimit) AS LONG
            
            'Fill array with test data
            FOR FirstIndex = 0 TO FirstIndexLimit
                FOR SecondIndex = 0 TO SecondIndexLimit
                    n(FirstIndex,SecondIndex) = FirstIndex * 1000 + SecondIndex
                NEXT
            NEXT
            
            'set the required element to look up
            FirstIndex = 100
            SecondIndex = 20
            
            'First, do it the easy way with BASIC
            BasicAnswer = n(FirstIndex,SecondIndex)
            PRINT "BasicAnswer=";BasicAnswer
            
            
            'now do it the complicated way, with ASM
            ArrayAddress = VARPTR (n(0,0))      'get the address of where BASIC has put the first array element
            
            !mov eax, FirstIndexLimit   'get the size of the first array dimension
            !add eax,1                  'add 1 because we have zero based arrays
            !imul eax,SecondIndex       'to get how many items to skip for each member of this dimension
            !add eax,FirstIndex         'add the offset into the next dimension
            !imul eax,4                 'there are 4 bytes per element
            !add eax, ArrayAddress      'add the start address of the data
            !mov eax,[eax]              'get the long pointed to by eax into eax, (look up the data from the address we just calculated).
            
            !mov AsmAnswer, eax         'store the result somewhere BASIC can get it
                              
            PRINT "  AsmAnswer=";AsmAnswer
                      
            WAITKEY$
            
            END FUNCTION

            Comment


              #7
              Help does not say if array elements may/may not be referenced directly in ASM statements:
              Accessing PowerBASIC variables by name
              Most variables in a PowerBASIC module are visible to Inline Assembler code created with the ASM statement. You can reference LOCAL, STATIC, and GLOBAL variables by name by simply using the name as an operand of the assembler opcode. That isn't possible with INSTANCE and THREADED variables, as their access requires multiple operations best handled by higher level PowerBASIC code. You can also reference procedure parameters by name, though you must differentiate between parameters passed by reference ( ), and those passed by value ( ). Any variable referenced in an assembly-language statement must be defined prior
              Maybe an array element referenced by subscript is not eligible for direct use?
              Michael Mattias
              Tal Systems (retired)
              Port Washington WI USA
              [email protected]
              http://www.talsystems.com

              Comment


                #8
                The essence of the problem is this... When you write ASM code, you must use Intel opcodes. ADD EAX, n(g,a) is not an Intel opcode. That type of operation requires the execution of numerous Intel opcodes, which vary greatly depending upon the nature of the array and the nature of the reference.

                That's one of the good reasons you chose PowerBASIC. It handles all of that messy stuff automatically when you code in PowerBASIC syntax.

                Bob Zale

                Comment


                  #9
                  Code:
                  X =  n(g,a) 
                  !add eax, X
                  ?????

                  Or, also qualified by "?????" : bypass array engine using PTR vars with "two subscript offsets".
                  Michael Mattias
                  Tal Systems (retired)
                  Port Washington WI USA
                  [email protected]
                  http://www.talsystems.com

                  Comment


                    #10
                    Michael,
                    the purpose is to learn to do in assembler what is currently done in BASIC in order to become more proficient at programming in assembler.
                    Bypassing the tricky bits using BASIC doesn't help with that objective.

                    Paul.

                    Comment


                      #11
                      I suspected "learning assembly language" was probably the real goal here.

                      I guess I was just hoping the Real Goal (not shown) was, "I want to do something faster and think I can use the posted assembly language code to do it" and that alternate solutions would be, if not welcomed with open arms, at least accepted in good faith.
                      Michael Mattias
                      Tal Systems (retired)
                      Port Washington WI USA
                      [email protected]
                      http://www.talsystems.com

                      Comment


                        #12
                        >Maybe an array element referenced by subscript is not eligible for direct use?

                        This usage is somewhat like an array subscript, and can be used with some other data types too.
                        Code:
                        #COMPILE EXE
                        #DIM ALL
                        
                        FUNCTION PBMAIN () AS LONG
                        
                            LOCAL sArr AS STRING * 32
                            sArr = CHR$(49 TO 80)
                            'think of it kinda like: DIM sArr(32) AS BYTE AT VARPTR(s)
                            
                            !mov al, sArr[0]   ;"1" is the chr moved to al
                            !mov al, sArr[1]   ;"2"
                            !mov al, sArr[2]   ;3
                            !mov al, sArr[3]   ;4
                            !mov al, sArr[4]   ;5
                            !mov al, sArr[24]  ;I
                            !mov al, sArr[25]  ;J
                            !mov al, sArr[31]  ;P
                        
                        END FUNCTION

                        Comment


                          #13
                          Originally posted by Michael Mattias View Post
                          I suspected "learning assembly language" was probably the real goal here.

                          I guess I was just hoping the Real Goal (not shown) was, "I want to do something faster and think I can use the posted assembly language code to do it" and that alternate solutions would be, if not welcomed with open arms, at least accepted in good faith.
                          The latter is the prime driver. As Bob points out, my programming language of choice is PowerBASIC because it does >99.99% of what I want and need in a way I can understand and at a speed far in excess of anything else I've used which also is plenty fast enough >99.99% of the time.

                          That said, there are times where a little more speed would be handy and, again, PowerBASIC comes up trumps by allowing me to most easily incorporate assembler directly into my programs.

                          I am, at heart, a simple and old fashioned BASIC programmer from the days when the BASIC came with the machine. I understand the concepts of pointers (and again, PB makes these trivial to implement) and other constructs and I do like to learn new things to add tools to the toolbox as it were.

                          Looking at Paul and Bob's answers, it's clearer to me (so I learned something) that arrays in assembler effectively need to be treated like arrays accessed by pointers in PB. That makes sense to me and I'm happy I've learned a bit more about PB and Assembler from the question and it's prompted a bit of debate too so it's all good. I also think Michael's suggested cheat/trick could work for me. I need to play some with the code in the answers and, for me at least, that's what this is all about. It's just a hobby to me. Thanks again to everyone.
                          Neil Croft (cissp)

                          Comment


                            #14
                            Well, since results matter....

                            Given: n() is an array of LONG integers, with zero-based subscripts

                            Also Given:
                            PowerBASIC stores arrays in column-major order: Array(0,0) is first (lowest) in memory, then Array(1,0), then Array(2,0), and so on through all the rows of the array. After the rows are taken care of, the next column is stored
                            .. then I better fix my original plan, since I thought it was row-major order before I RTFM..

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

                            Comment

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