Многомерные массивы на языке ассемблера - PullRequest
3 голосов
/ 27 декабря 2010

Привет, все могут! Любой, пожалуйста, скажите мне, как работать с двумерными массивами на языке ассемблера 8086.Я новичок в программировании на ассемблере.Спасибо

Ответы [ 2 ]

6 голосов
/ 27 декабря 2010

Ссылка Мадхура в значительной степени охватывает его, вы читали это?

если вы уже понимаете, например, двумерный массив на уровне программирования C, то ассемблер - следующий логический шаг.

Использование 8-битных байтов, например, массива z [1] [2] является третьим элементом второй строки, если вы хотите думать об этом таким образом, чтобы вычислить адрес, как он есть в C-адресе z плюс первый индекс умножается на ширину массива, скажем, его ширина составляет 13 байт, плюс второй индекс, так что & z + (13 * 1) +2 = & z + 15;

Использование псевдокода, а не кода x86 (на случай, если это домашнее задание).

;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

если у вас были циклы в 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];
  }
}

Переход на ассемблер довольно прост.


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

Грубая сила всегда будет работать для каждой платформы, грубая сила - это базовый адрес + (ширина, умноженная на первый индекс) + (вторая раз умноженная на размер элемента). Оптимизация в значительной степени зависит от того, что вы пытаетесь сделать, например, в первых примерах сборки, которые я делал, глупо умножать на единицу, если первый индекс жестко задан, и / или глупо перемещать # 2 в регистр, если это жестко запрограммированное число, просто добавьте 2. Если вычисление один раз против цикла меняет оптимальное количество регистров для использования и т. д., если ваша платформа не имеет умножения или это болезненно, то сделать ваши массивы степенями двух, если это возможно, хорошо идея, избавьтесь от умножения или других трюков, чтобы избавиться, если умножение, если вы не можете изменить ширину, и ваша платформа не имеет или делает умножение болезненным.

Платформы, которые имеют своего рода адресацию смещения регистров [r0, r1], где адрес, например, является суммой двух регистров, сохраняют добавление и предотвращают уничтожение регистра базового адреса, чтобы вы могли использовать его снова в петля. Если вы хотите использовать стиль указателя с указателем уничтожения по ходу (* ptr ++), это может изменить способ реализации ваших циклов, некоторые платформы позволяют вам использовать базовый регистр и добавлять к нему значение, например [r0], # 16 будет использовать адрес в r0, тогда после использования r0 добавьте 16 к r0, так что вам не нужно записывать дополнительную инструкцию добавления ... Я не думаю, что в x86 есть такая возможность, но есть и другие функции, которые вы можете использовать для этой задачи.

Начните с грубой силы, то есть x86, что означает, что вам, вероятно, придется использовать память для хранения переменных цикла, поскольку у вас, вероятно, недостаточно регистров для этой задачи (это нормально, потому что в x86 есть много инструкций, основанных на памяти), затем оптимизируйте, используя преимущества загрузки и сохраняя варианты.

0 голосов
/ 02 марта 2017
;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; 
...