duminică, 17 noiembrie 2013

Косвенный доступ к памяти SRAM. Массивы. Обработка массивов

 Главная страница курса         in romana

    Массивы

    Массив представляет собой последовательность переменных доступных по одному имени. На языке ASM мы не можем говорить о каком-либо специальном типе данных. Любая структура данных, простая или сложная, представлена областью памяти, выделенной под эту структуру. Это действительно и для таблиц(массивов), т.е. будет выделена область памяти доступна по имени ссылки (метки) .

Пример:

    .EQU TAB_SIZE=10     ; объявление переменной
    .DSEG                ; таблицы будут объявлены
                         ; в сегменте данных
     tab: .byte TAB_SIZE ; использование константы
                         ; в объявлении таблицы


    Из данного примера мы не можем сделать вывод, сколько элементов имеет таблица, но при условии, что элементы таблицы имеют тип byte, который занимает один байт в памяти, мы говорим, что tab представляет собой массив из 10 элементов типа byte. Если мы хотим выделить память для массива (объявить массив), элементами с размером больше, чем один байт, тогда выделенная память будет продуктом размера элементов и их количеством в массиве.


    Пример :

    .EQU ITEM_SIZE = 2
    .EQU TAB_SIZE = 10 * ITEM_SIZE
    .DSEG
    tab: .byte TAB_SIZE


    Доступ к элементам массива есть ни что иное, как доступ к адресам в памяти.     Например, если мы хотим прочесть значение 4-го элемента из массива в один байт: R16=tab[4] :

    .EQU TAB_SIZE = 10
    .DSEG
     tab: .byte TAB_SIZE

    .CSEG
        lds r16, tab+4


Косвенный доступ к памяти

    Метод, описанный выше, является прямым доступом к памяти, который используется в случае, если нам нужен доступ к одному определённому элементу в памяти. Но это неприемлемо, когда мы нуждаемся в более гибком доступе, например: итерация по массиву. В этом случае, более предпочтителен косвенный доступ к памяти, это означает, что адрес доступа к необходимой ячейке(элементу) памяти находится в косвенном регистре. МК AVR имеет 3 пары таких регистров :

    R27:R26 X XH:XL
    R29:R28 Y YH:YL
    R31:R30 Z ZH:ZL





    Для косвенного доступа используем следующие команды :

    a) косвенная запись     b) косвенное чтение
    ld R, X         st X, R
    ld R, Y         st Y, R
    ld R, Z         st Z, R


    Ещё раз отметим , что для доступа к ячейке(эл-ту)RAM, один из регистров X, Y, Z должны иметь адрес данной ячейки. Следовательно мы должны сначало проинициализировать данные косвенные регистры (X,Y,Z) :

    .DSEG
    a: .byte 1

    .CSEG
        ...
        ; a → X
        ldi XL, LOW(a)
        ldi XH, HIGH(a)
        ld R16, X
        ...


Относительный косвенный доступ к памяти (со смещением)

    Этот тип доступа обеспечивает доступ к памяти с фиксированным смещением q. Т.к. q представлен командой в 6 бит, соответственно относительный косвенный доступ возможен в зоне 64 адресов недалеко от регистра.

        ldd R, Y+q std Y+q, R
        ldd R, Z+q std Z+q, R





    Поскольку выделение памяти для переменных делается по конкретному адресу, константа, разница между адресами тоже – константа, которая может служить в качестве смещения для доступа
    Пример :

    .dseg
    a: .byte 1
    b: .byte 1
    .cseg
        ... ;a = b
        ldi YH, HIGH(a)
        ldi YL, LOW(a)
        ld R16, Y
        std Y+(b-a), R16 ; q=(b-a)
        ...

Итерационный косвенный доступ

    Косвенный доступ, предполагает, что выбранный адрес находится в регистре, позволяет динамический доступ к области памяти, изменяя косвенный регистр, фактически изменяем адрес доступа к памяти. Очень часто изменение адреса доступа, является одной повторяющейся, позволяет прямой и обратный обход массива.

Косвенный доступ с пред – декрементом

    Предположим, что регистр для косвенного доступа X,Y,Z пред декрементирован перед доступом расположения :

    ld R, -X st -X, R
    ld R, -Y st -Y, R
    ld R, -Z st -Z, R





    Похожий доступ используется для итерационной обработки области памяти в обратном направлении .
    Пример , заполнение массива нулями , очистка массива :


    .dseg
    tab: .byte 100

    .cseg
        ... ;clear tab
        ldi XL, LOW(tab+100)
        ldi XH, HIGH(tab+100)
        clr R15 ;R15 = 0
        ldi R17, 100
    loop:
        st -X, R15
        dec, R17
        (cpi R17, 0)
        brne loop
        ...


Косвенный доступ с пост – инкрементом

    Предполагается доступ к требуемому местонахождению , после чего , регистр косвенного доступа инкрементируется . Этот тип доступа используется в операциях итерационной обработки памяти в направлении от первого элемента до последнего .


    ld R, X+ st X+, R
    ld R, Y+ st Y+, R
    ld R, Z+ st Z+, R




    Пример копирования одного массива в другой :

    .dseg
    tabA: .byte 100
    tabB: .byte 100

    .cseg
        ...
    ;tabA = tabB (copy)
        ldi XL, LOW(tabA)
        ldi XH, HIGH(tabA)
        ldi YL, LOW(tabB)
        ldi YH, HIGH(tabB)
        ldi R17, 100
    loop:
        ld R16, X+
        st Y+, R16
        dec R17
        brne loop
        ...


Массивы в качестве входных параметров подпрограмм

    Из того , что мы знаем о передаче параметров с помощью подпрограмм на ASM , нам необходимо , сперва , проинициализировать регистры для этой цели . Число регистров будет зависеть , в большей степени , от параметров и их размеров . Но этот метод не очень удобен для отправки массива , по причине того , что объём памяти , который может занимать массив , во много раз больше , чем количество существующих регистров.
    Для того , чтобы передать массив подпрограмме , будет передаваться только отношение посредством этого массива при загрузке адреса в регистровую пару . В случае , когда регистровой парой будет являться один из косвенных регистров X,Y или Z , будет возможна итеративная обработка массива без инициализации одного из косвенных регистров в подпрограмме . Для передачи информации о размере , массив может использовать для его передачи через регистр , в качестве дополнительного параметра .
    Пример :

    .EQU N = 100
    .dseg
    tab: .byte N
    .cseg
        ...
        ldi XL, LOW(tab)
        ldi XH, HIGH(tab)
        ldi R16, N
        rcall ClearTab
        ...;
        ...;
    ClearTab:
        push r17
        clr r17
    loop:
        st X+, R17
        dec R16
        brne loop
        pop r17
        ret

 Главная страница курса         in romana