I'm currently trying to learn HLA assembler and I'm reading the Art of Assembly book. I'm stuck at the following example:
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 );
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.
Currently, the code 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 ;>
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)
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 (in relation to recType) 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) as (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
Am I wrong and missing something?