A 2D array

Three rows of four words, one element reached by row and column, and a whole column added up by stepping a row at a time.

Twelve words laid out as three rows of four. The program reads one element by its row and column, and then adds up a whole column, which means stepping through memory a row at a time instead of an element at a time.

Every array up to here was one line of memory. A 2D array is the same line read in rows, and the two numbers you write in C as grid[row][col] have to be turned into one offset before anything can be read.

You need to know: the "Arrays, strings and (a0)+" lecture and the "Addressing modes" lecture. What is new here is the stride, the distance in bytes between one row and the next, which is what walking a column adds every pass.

The three dc.w lines are one array of twelve words at $2000, and the rows exist only in how they are written down. row * COLS + col is the element's number in that one line, and doubling it turns a number of elements into a number of bytes, which is what the address arithmetic actually needs. d3 comes out at 000000C8, which is 200, the second element of the last row.

Walking a column is the same arithmetic done once. a1 starts at the top of the column and then adds COLS*2, eight bytes, at every pass: one row further down is one whole row of elements further along in memory. The assembler works COLS*2 out while assembling, so there is nothing multiplying at run time. d5 comes out at 000000DE, which is 222, from 2, 20 and 200.

Walking a row would be the same loop with (a1)+ and no add at all, since the elements of a row sit next to each other and the postincrement mode steps by the size of what it read. A column is the direction the array is not laid out in, and it costs one instruction per pass to say so.

Try changing move.l #1, d1 to move.l #3, d1. d3 comes out at 00000190, which is 400, and the column total in d5 at 000001BC, which is 444.