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

 
 
> присоединение программы на ассемблере(asm) к программе на С
KosTTTT
сообщение Aug 27 2014, 13:42
Сообщение #1





Группа: Новичок
Сообщений: 4
Регистрация: 12-08-14
Пользователь №: 82 523



Как присоединить большую программу, написанную в AVR Studio на ассемблере к программе на С? В интернете вроде бы прочел, что надо присоединить объектный файл программы на ассемблере на этапе линковки, но как это сделать?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Alex11
сообщение Aug 27 2014, 17:08
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 106
Регистрация: 23-10-04
Из: С-Петербург
Пользователь №: 965



Две программы соединить нельзя. Кто-то из них должен быть программой, а кто-то подпрограммой, из нее вызываемой. Обычно на С пишется головная программа, а на ассемблере подпрограмма. В этом случае подпрограмма должна соблюдать некоторые ограничения, накладываемые С-компилятором. Далее, в Вашем случае будут, скорее всего, еще дополнительные сложности, т.к. AVR-студия не имеет своего С-компилятора. Вам нужно найти С-компилятор с линкером, который поймет формат объектного файла, сформированного AVR-студией. Либо транслировать программу, написанную под студию другим ассемблером. Здесь возможны расхождения в синтаксисе и куча правок руками. А в принципе, достаночно линкеру указать два модуля для линковки, и они соединятся.
Go to the top of the page
 
+Quote Post
KosTTTT
сообщение Aug 28 2014, 06:34
Сообщение #3





Группа: Новичок
Сообщений: 4
Регистрация: 12-08-14
Пользователь №: 82 523



Объектный файл, сформированный AVR Stuio имеет формат .obj, а компилятор Си, GCC - .o. Я так понял, я не смогу их соединить на этапе линковки?
Кстати не могли бы вы объяснить, как мне в какой-нибудь среде (WinAVR, Eclipse, CVAVR) присоединять готовые объектные файлы, чтобы не компилировать по нескольку раз файлы .с?
Go to the top of the page
 
+Quote Post
=GM=
сообщение Aug 28 2014, 07:24
Сообщение #4


Ambidexter
*****

Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282



Есть несколько вариантов объединения.

1) Самый простой - можно объединить на уровне хекс-файлов. Компилируете ассемблерную подпрограмму (или программу в общем случае) с определенного адреса, а в сишной программе указываете адрес вызова (или перехода) перехода на данный адрес. Прошивки можно объединить на уровне хекс-текста, или прошить независимо, не стирая кусок, прошитый первым.

2) Оформляете ассемблерную подпрограмму в стиле, понятном компилятору cи, скажем, winavr. Ну там есть мощные ограничения, и вообще ублюдочно сделано на уровне компилятора. Вот яркий пример "ублюдочности"
Код
void static inline Signal_OUT(const uint8_t *signal, uint8_t ad2, uint8_t ad1, uint8_t ad0)
{
asm volatile(
   "eor r18, r18 ;r18<-0"                 "\n\t"
   "eor r19, r19 ;r19<-0"                 "\n\t"
"1:"                                     "\n\t"
  "add r18, %0;1 cycle"                "\n\t"
  "adc r19, %1;1 cycle"                "\n\t"    
  "adc %A3, %2;1 cycle"                "\n\t"
  "lpm     ;3 cycles"              "\n\t"
  "out %4, __tmp_reg__;1 cycle"    "\n\t"
  "sbis %5, 2;1 cycle if no skip" "\n\t"
  "rjmp 1b    ;2 cycles. Total 10 cycles"    "\n\t"
  :
  :"r" (ad0),"r" (ad1),"r" (ad2),"e" (signal),"I" (_SFR_IO_ADDR(PORTA)), "I" (_SFR_IO_ADDR(SPCR))
  :"r18", "r19"
);
}


3) Оформляете ассемблерную подпрограмму в отдельном файле с расширением .S Чуть попозже подготовлю пример оформления.


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Aug 28 2014, 07:34
Сообщение #5


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(=GM= @ Aug 28 2014, 11:24) *
Позволю себе прокомментировать..

В первый вариант я вообще не верю, т.к. программа на асме вряд ли написана структурно и она 100% будет портить СИ-контекст, так что можете об этом даже и не мечтать...

Второй вариант самый трудозатратный и лично я не вижу в нём хоть какого-нибудь смысла касательно перепахивания всей программы в таком стиле.
Ну а что касается "ублюдочности" формата асм вставок, так это плата за возможность отдать на откуп распределение регистров ассемблеру-компилятору.
И ни один другой инструмент не может в этом плане сравниться с gcc/gas.

ИМХО вариант 3 самый компромиссный, но придётся сделать нехилый рефакторинг асм кода (замечу, что может оказаться легче сразу на си переписывать вычлененные функ
ции).


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
=GM=
сообщение Aug 28 2014, 08:22
Сообщение #6


Ambidexter
*****

Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282



Цитата(demiurg_spb @ Aug 28 2014, 07:34) *
Позволю себе прокомментировать..
В первый вариант я вообще не верю, т.к. программа на асме вряд ли написана структурно и она 100% будет портить СИ-контекст, так что можете об этом даже и не мечтать...

Да ладно :-) С какой стати она будет портить си-контекст, который находится в пзу? Конечно, многое зависит от функциональности данной подпрограммы, и как она связана со всем остальным. Возьмём какой-нибудь пример, скажем, надо сделать два мака над 1000000 выборок и результат положить в две 8-байтные ячейки. Ассемблерная программа берет данные с АЦП, перемножает с синусом и косинусом из таблицы, кладёт результат в определенное место в озу и завершает работу. Сишная программа знает откуда взять результат, там место зарезервировано, и берет его. Вот и всё.


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Aug 28 2014, 09:11
Сообщение #7


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(=GM= @ Aug 28 2014, 12:22) *
Не так всё радужно.
У си контекста есть стек и иногда даже куча, есть область данных (инициализированных и нет) есть соглашения по использованию регистров,
а программа на асме об этом ничего не знает и не ведает, она обычно использует не только ПЗУ, но и ОЗУ и регистры как ей взбредёт в голову...


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
=GM=
сообщение Aug 28 2014, 09:38
Сообщение #8


Ambidexter
*****

Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282



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

Ниже приведен обещанный пример объединения по третьему варианту. Вырвано из рабочего проекта, кое-что удалено, кое-что подправлено.
CODE
// File: example.c
// Title: Example
// Version: 1.4
// Last updated: 09.03.13
// Author: GM
//Target: ATmega324PA (16MHz operating frequency)
//
// Support E-mail: xxxxx@xxxx.ru
//
// DESCRIPTION
// The routine measures
#define F_CPU 16000000UL //16MHz
#define PI 3.14159265359L
#include <avr/io.h>
#include <avr/sfr_defs.h>
#include <avr/pgmspace.h>

extern void mactest(void);
extern void asmroutine(void);

long long volatile re0=0;
long long volatile uval;
long volts[20] __attribute__ ((section (".block80")));
int ptra,ptrb;
unsigned char tab10k/ / __attribute__ ((section (".gentable")));
unsigned char tab10k/380/ =
{
128,137,147,157,167,176,185,194,
202,210,217,224,230,236,241,245,

248,251,253,254,255,254,253,251,
248,245,241,236,230,224,217,210
};

int main (void)
{
double num,R0;
int i,j;

mactest();

while(1) //loop forever
{
asmroutine();

re1=0;

im1=im1+(((long long)volts[j++])*((long long)sin10[i]));

}
}


;File: asmroutine.ASM
;Title: asm subroutine example
;Version: 1.1
;Last updated: 01.06.11
;Author: GM
;Target: ATmega324PA (16MHz operating frequency)
;
;Support E-mail: xxxxxx@xxxx.ru
;
;DESCRIPTION
; -----------------------

.nolist
#include <avr/io.h> // Include device specific definitions
.list
;#define tmp1 r16;
;#define rs 0
;#define rw 1
;#define e 2
;#define rst 6;
;#define cs 5;
;#define sclk 4;
;#define sda 3;

#define c0 r8
#define c1 r9
#define c2 r10
#define c3 r11
#define d0 r12
#define d1 r13
#define d2 r14
#define d3 r15
#define zl r30
#define zh r31

.global tab25k
.global re0
.global im0
.global asmroutine
.func asmroutine
asmroutine:
ldi ZL,lo8(tab25k)
ldi ZH,hi8(tab25k)

clr c0
clr c1

clr d1

asm1: lpm r0,Z+
lds c0,re0+0
lds c1,re0+1

add c0,d0

adc c1,d1
adc c2,d2

sts re0+1,c1
sts re0+2,c2
sts re0+3,c3

; rjmp asm1
ret

.endfunc


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post



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

 


RSS Текстовая версия Сейчас: 19th August 2025 - 08:37
Рейтинг@Mail.ru


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