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开发者_Go百科 language programming. Thanks
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.
;This code grabs data bits from accumulator and outputs it to the carry
Main:
clr C
mov A, #00101010b;
call array;
jmp Main;
array:
subb A, #80H; mov can work here if you did not clr C
cpl A; check for proper array location
mov B, #8; set division factor
DIV AB; bit offset contained in B;
mov R6,B;
subb A, #30H; this bit will allow you to mov around the chosen register
cpl A;
mov R7, A;
mov A, @R7; this is the array position
inc R6;
loop:
rlc A; this takes the array bit to the carry for easy access
djnz R6, loop;
精彩评论