реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Как в асемблерной вставке обратится к масиву?, Компилятор Embedded Workbench 2.3
Professor
сообщение May 16 2006, 18:07
Сообщение #1


Участник
*

Группа: Новичок
Сообщений: 35
Регистрация: 12-05-06
Из: Украина Харьков
Пользователь №: 17 045



Суть вопроса состоит в том чтоб в асемблерной вставке обратится к масиву чисел и одно из чисел извлечь.... Массив должен быть описан как 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

Заранее благодарю за помощь.....
Go to the top of the page
 
+Quote Post
rezident
сообщение May 16 2006, 18:15
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



А где обозначен сам массив из которого нужно извлекать число? И какой смысл для такой простой операции вызывать функию, да еще и ассемблерную?
Go to the top of the page
 
+Quote Post
Professor
сообщение May 16 2006, 18:21
Сообщение #3


Участник
*

Группа: Новичок
Сообщений: 35
Регистрация: 12-05-06
Из: Украина Харьков
Пользователь №: 17 045



Цитата(rezident @ May 16 2006, 21:15) *
А где обозначен сам массив из которого нужно извлекать число? И какой смысл для такой простой операции вызывать функию, да еще и ассемблерную?



Суть вопроса в том что етот кусочек кода надо сделать максимально оптимизированным по скорости....
В самой функции будьт еще другой код... но это уже не важно... с остальным кодом вопросов нет...
А где именно обозначить этот массив для решени проблеммы не имет никакого значения...
Go to the top of the page
 
+Quote Post
GetSmart
сообщение May 16 2006, 18:31
Сообщение #4


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Ух как давно я не писал для 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.


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
Professor
сообщение May 16 2006, 18:37
Сообщение #5


Участник
*

Группа: Новичок
Сообщений: 35
Регистрация: 12-05-06
Из: Украина Харьков
Пользователь №: 17 045



Цитата(GetSmart @ May 16 2006, 21:31) *
Ух как давно я не писал для 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 - May 16 2006, 18:38
Go to the top of the page
 
+Quote Post
GetSmart
сообщение May 16 2006, 18:38
Сообщение #6


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



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


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
Professor
сообщение May 16 2006, 18:40
Сообщение #7


Участник
*

Группа: Новичок
Сообщений: 35
Регистрация: 12-05-06
Из: Украина Харьков
Пользователь №: 17 045



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



А где и как описать сам масив если массив расположен во флеше???
Go to the top of the page
 
+Quote Post
GetSmart
сообщение May 16 2006, 18:46
Сообщение #8


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



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

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


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
Professor
сообщение May 16 2006, 19:14
Сообщение #9


Участник
*

Группа: Новичок
Сообщений: 35
Регистрация: 12-05-06
Из: Украина Харьков
Пользователь №: 17 045



set_int:
; (в этом месте и надо обратится и извлечЬ число из масива)
ldi ZL,LOW(LightTabl*2)
ldi ZH,HIGH(LightTabl*2)
; тут добавляете к паре ZH:ZL нужное смещение
lpm ; или lpm Rx,Z+ , где Rx - любой регистр, и можно Z, Z+

END set_int
[/quote]

А если надо извлечь не один из эелементов массива а один раз к примеру нулевой а вдругой раз первый как вызывать элемент массива в таком случае(когда номер извлекаемого элемента массива всегда меняется)?
Go to the top of the page
 
+Quote Post
GetSmart
сообщение May 16 2006, 19:28
Сообщение #10


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



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

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

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


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
Professor
сообщение May 16 2006, 19:50
Сообщение #11


Участник
*

Группа: Новичок
Сообщений: 35
Регистрация: 12-05-06
Из: Украина Харьков
Пользователь №: 17 045



Цитата(GetSmart @ May 16 2006, 22:28) *
"тут добавляете к паре ZH:ZL нужное смещение"


А добавлять смещение таким образом:
add ZL, rx
add ZH, rx
где rx регистр в котором храниться номер извлекаемого эелемента....
????
ПРОЦ ATmega16

Сообщение отредактировал Professor - May 16 2006, 20:03
Go to the top of the page
 
+Quote Post
GetSmart
сообщение May 16 2006, 20:21
Сообщение #12


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



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

Во-первых, добавлять надо так:
add ZL, r0
adc ZH, r1
то есть с переносом.

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

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


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
vet
сообщение May 16 2006, 20:37
Сообщение #13


Знающий
****

Группа: Свой
Сообщений: 550
Регистрация: 16-06-04
Из: Казань
Пользователь №: 32



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


--------------------
Главная линия этого опуса ясна мне насквозь!
Go to the top of the page
 
+Quote Post
_Bill
сообщение May 18 2006, 11:18
Сообщение #14


Местный
***

Группа: Участник
Сообщений: 416
Регистрация: 18-04-06
Из: Челябинск
Пользователь №: 16 219



Цитата(Professor @ May 16 2006, 21:07) *
Суть вопроса состоит в том чтоб в асемблерной вставке обратится к масиву чисел и одно из чисел извлечь.... Массив должен быть описан как unsigned char... Как его правильно описать и как его вызывать в асемблерной вставке....

Выдумываете себе проблемы, чтобы потом с успехом их преодолевать? Зачем вообще нужны ассемблерные вставки? Это и некрасиво, и неэффективно.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 19 2006, 13:23
Сообщение #15


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



самый эффективный способ:
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];
    }
}
Ставишь галочку "генерить ассемблерный файл" в опцияк компилятора на вкладке листинг, компилишь, внимательно изучаешь полученную "рыбу". Или пишешь нужную функцию полностью на С, компилишь, получаешь ассемблерный исходник и его оптимизируешь. Только не забудь прочитать в документации какие регистры функция может портить, а какие должна сохранять.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
3 чел. читают эту тему (гостей: 3, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 21:01
Рейтинг@Mail.ru


Страница сгенерированна за 0.01505 секунд с 7
ELECTRONIX ©2004-2016