News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Problem with HLA example

Started by dataskin, August 20, 2014, 09:23:03 AM

Previous topic - Next topic

dataskin

Hi,

I'm currently trying to learn HLA assembler and I'm reading the Art of Assembly book.
I'm stuck at the following example from the book, which I don't understand at all.

//beginning of the code
type
  recType:
      record
          arrayField: dword[4,5];
          << Other fields >>
     endrecord;

static
aryOfRecs: recType[3,3];

// Access aryOfRecs[i,j].arrayField[k,l]:

intmul( 5, i, ebx ); // Computes index into aryOfRecs
add( j, ebx ); // as (i*5 +j)*@size( recType ).
intmul( @size( recType ), ebx );

intmul( 3, k, eax ); // Computes index into aryOfRecs
add( l, eax ); // as (k*3 + j) (*4 handled later).

mov( aryOfRecs.arrayField[ ebx + eax*4 ], eax );

// end of the code

So, first of all. recType is a record, having arrayField: dword [4,5] plus - some other, unspecified fields.
Then - we've got aryOfRecs which is an array [3,3] of recType declared in a static section. That's ok.

What doesn't make any sense for me is what the comments say:

// Access aryOfRecs[i,j].arrayField[k,l]: <- "shouldn't that be aryOfRecs[k,l].arrayField[i,j]" ?

intmul( 5, i, ebx ); // Computes index into aryOfRecs  <- shouldn't that be "Computes index into arrayField" ?
add( j, ebx ); // as (i*5 +j)*@size( recType ).
intmul( @size( recType ), ebx );

why is it being multiplied by the whole size of the recType record and not the size of the dword (4 bytes)? arrayField isn't an array of the recType records, after all..

intmul( 3, k, eax ); // Computes index into aryOfRecs
add( l, eax ); // as (k*3 + j) (*4 handled later).
mov( aryOfRecs.arrayField[ ebx + eax*4 ], eax );

Why is eax being multiplied by 4 and not by the size of recType?

Could someone explain, what's happenning (and why), in this example?


AssemblyChallenge

Hi.

Correct me if I'm wrong. What I see is a [3x3] array where every element (9 in total if counted by 1 index) is formed by a recType record, one of wich contains, also, a [4x5] array.

If that's true, then it makes sense multiplying by the size of recType as it must travel first by one of the first 9 elements and then, the elements inside the inner array (arrayField).

Just my two cents.  :icon_mrgreen:

dataskin

Quote from: AssemblyChallenge on August 20, 2014, 03:40:57 PM
Hi.

Correct me if I'm wrong. What I see is a [3x3] array where every element (9 in total if counted by 1 index) is formed by a recType record, one of wich contains, also, a [4x5] array.

If that's true, then it makes sense multiplying by the size of recType as it must travel first by one of the first 9 elements and then, the elements inside the inner array (arrayField).

Indeed.. That's what I've thought - it should be doing. But, for some reason - that's not what it does.
Currently, it multiplies ebx by @size( recType ) to compute the address of the inner array (arrayField[4,5]), which doesn't make any sense, imho.

So, the whole formula in the book for the address computation works like this: BASE ADDRESS (aryOfRecs) +  (k*3+l)*4 + ((i*5+j)* @size( recType )

I guess it should be: BASE ADDRESS (aryOfRecs) +  (k*3+l)*@size( recType ) + ((i*5+j)*4 instead ?

So, either - Randall Hyde has made a mistake in this example (and yes, I've checked the errata on HLA page. It says nothing about this), or I'm having a brainfart since yesterday  :icon_mrgreen:..

The last line is: mov( aryOfRecs.arrayField[ ebx + eax*4 ], eax );
Basically, it sums up the OFFSET(aryOfRecs) + OFFSET(arrayField) + OFFSET(ebx) + OFFSET(eax*4)
                                                                                 \\+0

arrayField is the first field in the recType record, so I've assumed that in this particular case - the value of the offset of arrayField would be +0. It basically - maps at the beginning of the recType. So I guess it has been included only as a general rule, to cover the cases in which the order of the fields within recType record would've been different (and arrayField wouldn't be the first field in the recType).
So - I've skipped the value of OFFSET(arrayField) in the two formulas, above.

And again - OFFSET(eax*4) goes with "outer" array. Multiplying eax by the size of the dword (4) - doesn't make any sense..

So, I'd expect the code to do something like this:

intmul( 5, i, ebx ); // Computes index into aryOfRecs arrayField
add( j, ebx );       //  as (i*5 +j)*@size( recType ). as  (i*5 +j)*4 (or  (i*5 +j)@size(dword) ). *4 is handled later, in the last line with a scaled-index addressing, to save one (shl ebx by 2 or intmul ebx by 4) instruction
intmul( @size( recType ), ebx );

intmul( 3, k, eax ); // Computes index into aryOfRecs
add( l, eax ); //  as (k*3 + j)(*4 handled later) ((k*3+l)*@size(recType))
intmul( @size( recType ), eax );

mov( aryOfRecs.arrayField[ ebx + eax*4 ], eax );
mov( aryOfRecs.arrayField[ ebx*4 + eax], eax ); //ebx*4 because @size(dword) = 4

//addition is commutative

Correct me if I'm wrong and I'm missing something...