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 intoaryOfRecsarrayField 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) instructionintmul( @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?