No announcement yet.

AMS Code and RGB Types

  • Filter
  • Time
  • Show
Clear All
new posts

    AMS Code and RGB Types

    Hi All,

    I am a newbie to ASM. I am looping through a 2D array of data. the trick is that it is of type rgbtriple, which is a 3 byte size per entry. I was able to get the code to work and to get me to the exact memory address of the data, but the problem is getting the rgbtriple value out of that location. I used an 1 element array to DIM...AT the memory location (z) to get the value. I then look at the color components and compare them to the known components and they do not match. any ideas? code below.

         !mov y,2
             !mov x,2
                 LOCAL z AS LONG
                 !mov eax, 640  'get the size of the first array dimension
                 !mov ebx,y
                 !sub ebx,1
                 !imul eax,ebx       'to get how many items to skip for each member of this dimension
                 !mov ebx,x
                 !add eax,ebx         'add the offset into the next dimension
                 !imul eax,3                 'there are 3 bytes per element
                 '!mov ebx,eax
                 '!mov i,ebx
                 '!mov eax,ebx
                 !add eax, arrPtr      'add the start address of the data
                 !sub eax,3
                 !mov z,eax
                 REDIM y(1) AS rgbtriple AT z
                 PRINT#12,"actual ";inImg(x, y).rgbtred,inImg(1).rgbtblue,inImg(1).rgbtgreen
                 PRINT#12,"bctual ";y(1).rgbtred,y(1).rgbtblue,y(1).rgbtgreen
            !add x,1              'add 1 to b&
            !cmp x,ecx             'has it exceeded the loop limit?
            !jle xloop             'it's less than or equal so no, loop back.
        !add y,1              'add 1 to b&
        !cmp y,edx            'has it exceeded the loop limit?
        !jle yloop             'it's less than or equal so no, loop back.

    is REDIM y(1) not going to give you a 2 element array with element 0 at the place you want?

    An alternative method is to use a pointer, something like this:
    LOCAL pTriple AS rgbtriple PTR     'a pointer to a rgbtriple type
    LOCAL MyResult AS rgbtriple
    '..your other code here
    pTriple = z            'set pointer to point to the address of the data just calculated
    MyResult = @pTriple    'read the triple from the array at memory address z
    '.. other code here
    PRINT MyResult.rgbtred,MyResult.rgbtblue,MyResult.rgbtgreen

    In the PRINT#12 line you use (x,y) as the index for red but (1) as the index for blue and green.

    You need to be careful of which registers you use. See here:




      Hi Paul,

      Thanks for pointing me in the right direction...your answer explains why i needed to add another few bytes on their to get the correct data. I forgot that arrays are zero based unless you specify otherwise.

      FYI....I think I was borrowing some ideas from old posts in putting this code together as well as some 2D array copy a belated thanks for sharing that as well.



        One more thing...thanks for that link on ASM and PB. I wish that information was in the PBWin User Guide cause it would have saved me a lot of trouble! I kept getting "funky" things happening when using registers and now i know exactly why.



          Originally posted by Kevin Cramer View Post
          ...I wish that information was in the PBWin User Guide cause it would have saved me a lot of trouble!

          That information IS in the PowerBASIC Doc. The page you read was located in the PowerBASIC Help File. There's lots more information available right in that section... Check it out! {smile]

          Bob Zale
          PowerBASIC Inc.


            a few notes that might be of help.
            The CPU has 8 general purpose registers.

            EAX, ECX, EDX can be used whenever you like. You don't need to preserve them but if you leave your own ASM code for any reason then the code you call will not preserve them either. Keep that in mind when you have a BASIC statement in among your ASM. If you want to preserve these registers while you call a BASIC routine then you need to save them yourself and restore them when you return from BASIC.

            EBX, ESI, EDI you need to preserve so make sure that, if you use them in your own ASM, you save them first and restore them afterwards before executing another BASIC statement.
            Also ESI and EDI are where the compiler keeps its register variables so it's usually a good idea, until you get more used to ASM, to disable register variables with a #REGISTER NONE statement otherwise you'll use a register without realising you've overwritten a variable as well.

            ESP is the stack pointer and it's not usually a good idea to mess directly with this.

            EBP usage is more involved. It is usable as a general purpose register and must be preserved like EBX, ESI and EDI but it is also used by the compiler to reference BASIC variables.
            You can use this register but only if your ASM does not access named BASIC variables while you're using it.
            It's usually better to avoid using EBP but if you really need that one extra register in your ASM then it can be used with care.

            Remember these 2 opcodes, they can be useful:
            !pushad		'save all CPU registers on the stack
            .. your own ASM here  
            !popad          'restore all CPU registers from the stack