Перейти к содержанию
    

Как в асемблерной вставке обратится к масиву?

Суть вопроса состоит в том чтоб в асемблерной вставке обратится к масиву чисел и одно из чисел извлечь.... Массив должен быть описан как unsigned char... Как его правильно описать и как его вызывать в асемблерной вставке....

 

Вставка организованна таким образом:

 

В main.c:

 

extern void set_int(void);

 

void main(void){

set_int();

}

 

В Text file.asm:

 

NAME set_int

#include <iom16.h>

PUBLIC set_int

RSEG CODE

 

set_int:

 

; (в этом месте и надо обратится и извлеч число из масива)

 

ret

END set_int

 

Заранее благодарю за помощь.....

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А где обозначен сам массив из которого нужно извлекать число? И какой смысл для такой простой операции вызывать функию, да еще и ассемблерную?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А где обозначен сам массив из которого нужно извлекать число? И какой смысл для такой простой операции вызывать функию, да еще и ассемблерную?

 

 

Суть вопроса в том что етот кусочек кода надо сделать максимально оптимизированным по скорости....

В самой функции будьт еще другой код... но это уже не важно... с остальным кодом вопросов нет...

А где именно обозначить этот массив для решени проблеммы не имет никакого значения...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ух как давно я не писал для AVR!

 

NAME set_int

#include <iom16.h>

PUBLIC set_int

RSEG CODE

EXTERN chartabl

 

set_int:

; (в этом месте и надо обратится и извлечЬ число из масива)

ldi ZL,LOW(chartabl)

ldi ZH,HIGH(chartabl)

ld r0,Y ; или ld r0,Y+ если нужно с инкрементом

 

ret

END set_int

_______________________

Это если массив расположен в RAM. А если во флэше, то так:

 

NAME set_int

#include <iom16.h>

PUBLIC set_int

RSEG CODE

EXTERN chartabl

 

set_int:

; (в этом месте и надо обратится и извлечЬ число из масива)

ldi ZL,LOW(chartabl*2)

ldi ZH,HIGH(chartabl*2)

lpm ; или lpm rx,z+ , где rx - любой регистр, и можно z, z+, y, y+

ret

END set_int

 

хотя могу ошибаться на счёт умножения на 2. Я это делал когда метка находилась в этом же ASM-файле. Глобальный адрес может уже быть умножен на 2.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ух как давно я не писал для AVR!

 

NAME set_int

#include <iom16.h>

PUBLIC set_int

RSEG CODE

EXTERN chartabl

 

set_int:

; (в этом месте и надо обратится и извлечЬ число из масива)

ldi ZL,LOW(chartabl)

ldi ZH,HIGH(chartabl)

ld r0,Y ; или ld r0,Y+ если нужно с инкрементом

 

ret

END set_int

_______________________

Это если массив расположен в RAM. А если во флэше, то так:

 

NAME set_int

#include <iom16.h>

PUBLIC set_int

RSEG CODE

EXTERN chartabl

 

set_int:

; (в этом месте и надо обратится и извлечЬ число из масива)

ldi ZL,LOW(chartabl*2)

ldi ZH,HIGH(chartabl*2)

lpm ; или lpm rx,z+ , где rx - любой регистр, и можно z, z+, y, y+

ret

END set_int

 

хотя могу ошибаться на счёт умножения на 2. Я это делал когда метка находилась в этом же ASM-файле. Глобальный адрес может уже быть умножен на 2.

 

 

А где и как описать сам масив если массив расположен во флеше???

Изменено пользователем Professor

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Чё-то я намудрил немного. Вобщем так. Если указатель загружается в пару ZH:ZL то далее указывается ld Rx,Z или ld Rx,Z+. А если пара YH:YL то ld Rx,Y или ld Rx,Y+. А ещё можно через пару XH:XL и команду ld Rx,X или ld Rx,X+.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Чё-то я намудрил немного. Вобщем так. Если указатель загружается в пару ZH:ZL то далее указывается ld Rx,Z или ld Rx,Z+. А если пара YH:YL то ld Rx,Y или ld Rx,Y+. А ещё можно через пару XH:XL и команду ld Rx,X или ld Rx,X+.

 

 

А где и как описать сам масив если массив расположен во флеше???

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну блин так и писали бы в начале. Я-то думал, что у вас сишный проект с асмовской вставкой и массив уже описан в си-файле. Значит так:

 

NAME set_int

#include <iom16.h>

PUBLIC set_int

RSEG CODE

 

set_int:

; (в этом месте и надо обратится и извлечЬ число из масива)

ldi ZL,LOW(LightTabl*2)

ldi ZH,HIGH(LightTabl*2)

; тут добавляете к паре ZH:ZL нужное смещение

lpm ; или lpm Rx,Z+ , где Rx - любой регистр, и можно Z, Z+

ret ; возвращаемый результат в регистре Rx

 

LightTabl:

.db 255,250,245,240,234,229,225,220,215,210,206,201,197,193,188,184

.db 180,176,172,169,165,161,158,154,151,147,144,141,138,134,131,128

.db 125,123,120,117,114,111,109,106,104,101,99,96,94,92,90,87

 

END set_int

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

set_int:

; (в этом месте и надо обратится и извлечЬ число из масива)

ldi ZL,LOW(LightTabl*2)

ldi ZH,HIGH(LightTabl*2)

; тут добавляете к паре ZH:ZL нужное смещение

lpm ; или lpm Rx,Z+ , где Rx - любой регистр, и можно Z, Z+

 

END set_int

 

А если надо извлечь не один из эелементов массива а один раз к примеру нулевой а вдругой раз первый как вызывать элемент массива в таком случае(когда номер извлекаемого элемента массива всегда меняется)?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А если надо извлечь не один из эелементов массива а один раз к примеру нулевой а вдругой раз первый как вызывать элемент массива в таком случае(когда номер извлекаемого элемента массива всегда меняется)?

Я же написал ремарку - "тут добавляете к паре ZH:ZL нужное смещение". Вы можете добавить к паре ZH,ZL любое нужное число - смещение в байтах от начала таблицы. Откуда вы его будете брать - ваши дела. А после того, как добавите, выполняете команду LPM. Ну и с результатом делаете что хотите. Судя по прототипу процедуры, возвращать его не нужно. Можете извлекать хоть десять чисел подряд.

 

Если ещё не понятно, то уточните заодно тип проца.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

"тут добавляете к паре ZH:ZL нужное смещение"

 

А добавлять смещение таким образом:

add ZL, rx

add ZH, rx

где rx регистр в котором храниться номер извлекаемого эелемента....

????

ПРОЦ ATmega16

Изменено пользователем Professor

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Блин, да вы вообще в асме ни бум-бум.

 

Во-первых, добавлять надо так:

add ZL, r0

adc ZH, r1

то есть с переносом.

 

Откуда взять r1:r0 ? Зависит от вас. Можете передавать из си-шного кода в качестве параметра процедуры. Можете объявить глобальную переменную WORD в RAM, в сишном коде её менять, а в асмовом читать и использовать в качестве индекса. Можете и читать и изменять только в асмовом файле. Вариантов до кучи.

 

Пока вы не опишите в одном посте сразу все требования к логике работы процедуры общаться так отрывками смысла нет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Хинт: вместо add/adc оптимальнее применять subi/sbci, чтобы обойтись без лишних загрузок.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Суть вопроса состоит в том чтоб в асемблерной вставке обратится к масиву чисел и одно из чисел извлечь.... Массив должен быть описан как unsigned char... Как его правильно описать и как его вызывать в асемблерной вставке....

Выдумываете себе проблемы, чтобы потом с успехом их преодолевать? Зачем вообще нужны ассемблерные вставки? Это и некрасиво, и неэффективно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

самый эффективный способ:

main.c

#include <stdint.h>

uint8_t const __flash Array[8] = {1,2,3,4,5,6,7,8};

extern void AsmFunc(void);
void main (void) {
    AsmFunc();
}

Asm_fish.c:

#include <stdint.h>
extern uint8_t const __flash Array[8];
uint8_t Tmp;
void AsmFunc(void) {
    uint8_t i;
    for(i = 0; i < 3; i++) {
       Tmp = Array[i*2];
    }
}

Ставишь галочку "генерить ассемблерный файл" в опцияк компилятора на вкладке листинг, компилишь, внимательно изучаешь полученную "рыбу". Или пишешь нужную функцию полностью на С, компилишь, получаешь ассемблерный исходник и его оптимизируешь. Только не забудь прочитать в документации какие регистры функция может портить, а какие должна сохранять.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...