Assume I am working on ARM Cortex M7. Now take a look at:
int a[4][4];
a[i][j]=5;
Is in assembly language a function will be calculating the a[j][j] address or it uses lookuptable (pointer array with the same size) or some magical way to place 5
in correct place?
This is disassembler output:
136 array1[i][i 1]=i;
08000da6: ldr r3, [r7, #36] ; 0x24
08000da8: adds r3, #1
08000daa: ldr r2, [r7, #36] ; 0x24
08000dac: uxtb r1, r2
08000dae: ldr r2, [r7, #36] ; 0x24
08000db0: lsls r2, r2, #2
08000db2: add.w r0, r7, #40 ; 0x28
08000db6: add r2, r0
08000db8: add r3, r2
08000dba: subs r3, #36 ; 0x24
08000dbc: mov r2, r1
08000dbe: strb r2, [r3, #0]
CodePudding user response:
If you write the indices as in your example, the compiler will calculate the exact memory address required at compile time.
If the indices were variables, then address would be calculated at run time.
Here is a comparison of assembly output for both cases.
CodePudding user response:
Without considering optimization, the standard way a compiler implements a reference to an array element, say x[k]
:
- Start with the memory address of
x
. - Multiply the number of bytes in an element of
x
byk
. - Add that to the memory address of
x
.
Let’s suppose int
has four bytes.
With a[i][j]
of int a[4][4]
, there are two memory references, so the address is calculated:
- Start with the memory address of
a
. - The elements of
a
are arrays of 4int
, so the size of an element ofa
is 4 times 4 bytes, which is 16 bytes. - Multiply 16 bytes by
i
. - Add that to the address of
a
. Now we have calculated the address ofa[i]
. - We use the address of
a[i]
to start a new calculation. a[i]
is an array ofint
, so the size of an element ofa[i]
is 4 bytes.- Multiply 4 bytes by
j
. - Add that to the address of
a[i]
. This gives the address ofa[i][j]
.
Summarizing, if s
is the start address of a
, and we use units of bytes, then the address of a[i][j]
is s
16•i
4•j
.