Q:

Multidimensional Arrays in Assembly Language

Hi All 
Can Any one plz tell me how to handle 2d arrays in 8086 assembly language.
i am beginer in assembly language programming.
Thanks

A:

Madhur's link pretty much covers it, did you read through that?
if you already understand a 2d array at the C programming level for example then the assembler is the next logical step.
Using 8 bit bytes for example an array z[1][2] is second row third item over if you want to think of it that way, to compute the address it is as it is in C   address of z plus the first index times width of the array, lets say it is 13 bytes wide, plus the second index so &z + (13*1)+2 = &z+15;
Using pseudo code and not x86 code (in case this is homework).

;brute force
ldr r0,=z ;load address of z into r0
mov r1,#13
mul r1,#1 ;make this a register or load from a memory location
mov r2,#2 ;make this a register or load from a memory location
add r0,r1
add r0,r2
ldrb r1,[r0] ;read the byte
strb r3,[r0] ;write the byte

;if your instruction set allows register offset
ldr r0,=z ;load address of z into r0
mov r1,#13
mul r1,#1
mov r2,#2
add r1,r2
ldrb r4,[r0,r1] ;read the byte
strb r3,[r0,r1] ;write the byte

;or immediate offset and offset is hardcoded
ldr r0,=z ;load address of z into r0
mov r1,#13
mul r1,#1
add r0,r1
ldrb r4,[r1,#2] ;read the byte
strb r3,[r1,#2] ;write the byte

if you had loops in C

unsigned char x[4][16];
unsigned char z[4][16];
unsigned int ra,rb;

for(ra=0;ra<4;ra++)
{
  for(rb=0;rb<16;rb++)
  { 
      x[ra][rb]=z[ra][rb];
  }
}

The conversion to assembler is pretty straight forward.

ldr r0,=x
ldr r1,=z
mov r2,#0 ;ra
outer:
  mov r3,#0 ;rb
  inner:
    mov r4,r2 lsl #2 ;16 bytes wide
    add r4,r3
    ldrb r5,[r1,r4]
    strb r5,[r0,r4]
    add r3,r3,#1
    cmp r3,#16
    bne inner
  add r2,r2,#1
  cmp r2,#4
  bne outer

Brute force will always work for each platform, brute force being base address + (width times first index) + (second index times size of element).   Optimizations rely heavily on what you are trying to do, in the first assembly examples I did for example it is silly to multiply by one if the first index is a hardcoded one, and/or silly to move #2 to a register if that is a hardcoded number, just add 2.  If computing one time vs a loop changes the optimal number of registers to use, etc.  if your platform does not have a multiply or it is painful then making your arrays powers of two if possible is a good idea, get rid of the multiply, or other tricks to get rid if the multiply if you cannot change the width and your platform does not have or makes multiplies painful.
Platforms that have some sort of register offset addressing [r0,r1] where the address is the sum of the two registers for example, saves you an add and prevents destroying the base address register so that you can use it again in a loop.  If you want to go pointer style with a destroy as you go pointer (*ptr++), that could change how you implement your loops, some platforms allow you to use a base register and add a value to it, for example [r0],#16 would use the address at r0 then after using r0 add 16 to r0 so you dont have to burn an extra add instruction...I dont think x86 has that but it has other features that you can use for this task.
Start with brute force, being x86 that means you are likely going to have to use memory to keep loop variables as you probably do not have enough registers for the task (that is okay because x86 has lots of memory based instructions), then optimize taking advantage of load and store variations.

