|
Keil и thumb ассемблер ARM, проблема с передачей и возвращением данный из си ф-ии в асм |
|
|
|
Mar 16 2011, 09:52
|

Местный
  
Группа: Участник
Сообщений: 255
Регистрация: 3-02-09
Из: Омск
Пользователь №: 44 323

|
Создал си проект программы имеющую асм подрограмму, при этом абсолютно не могу понять каким образом передавать данные подпрограмме и извлекать результат(что в какие регистры попадает и по каким правилам). Еще один момент это использование asm вставок в режиме Thumb (ни в какую не компилируется и не могу понять в чем загвоздка). Пробовал: asm("MOV R1, R0"); __asm("MOV R1, R0");Ошибка: использование inline ассемблера не возможно в режиме Thumb. main файл: #include <stdio.h> extern void strcopy(int d, int s); int main() { int srcstr = 3; int dststr = 1; /* dststr is an array since we’re going to change it */ strcopy(dststr,srcstr); return (0); }Функция strcopy находится в файле scopy.s с содержанием: PRESERVE8 AREA SCopy, CODE, READONLY EXPORT strcopy THUMB strcopy ; R0 points to destination string. ; R1 points to source string. MOV R1,#2 ; Load byte and update address. MOV R2,#5 ; Store byte and update address. BX lr ; Return. ENDКомпилируется, работает, однако значение srcstr не возвращается. Только начинаю работать со связкой асм+си пожэтому сильно не пинайте(или пните в сторону туда где чего почитать). Проект прилагаю.
Сообщение отредактировал drum1987 - Mar 16 2011, 09:53
Прикрепленные файлы
Blinky.rar ( 51.67 килобайт )
Кол-во скачиваний: 16
|
|
|
|
|
Mar 16 2011, 10:00
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(drum1987 @ Mar 16 2011, 12:52)  Создал си проект программы имеющую асм подрограмму, при этом абсолютно не могу понять каким образом передавать данные подпрограмме и извлекать результат(что в какие регистры попадает и по каким правилам). Правила описаны в стандарте AAPCS. Цитата(drum1987 @ Mar 16 2011, 12:52)  Еще один момент это использование asm вставок в режиме Thumb (ни в какую не компилируется и не могу понять в чем загвоздка). Так сами же себе и ответили ведь: Цитата(drum1987 @ Mar 16 2011, 12:52)  Ошибка: использование inline ассемблера не возможно в режиме Thumb.
|
|
|
|
|
Mar 16 2011, 10:16
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(drum1987 @ Mar 16 2011, 12:52)  Только начинаю работать со связкой асм+си пожэтому сильно не пинайте(или пните в сторону туда где чего почитать). Почитать, как обычно, в руководстве пользователя: RealView Compiler User GuideRealView Compiler Reference GuideЦитата(drum1987 @ Mar 16 2011, 12:52)  Ошибка: использование inline ассемблера не возможно в режиме Thumb. Если Вы почитаете руководство, то обнаружите, что этот компилятор не поддерживает функцию inline assembler при генерации кода Thumb: Differences from previous versions of the ARM C/C++ compilersЦитата(drum1987 @ Mar 16 2011, 12:52)  Компилируется, работает, однако значение srcstr не возвращается. Поясните. Работает, но не работает? Что должно было произойти, и что на самом деле произошло?
|
|
|
|
|
Mar 16 2011, 10:37
|

Местный
  
Группа: Участник
Сообщений: 255
Регистрация: 3-02-09
Из: Омск
Пользователь №: 44 323

|
Цитата(scifi @ Mar 16 2011, 17:16)  Поясните. Работает, но не работает? Что должно было произойти, и что на самом деле произошло? Работает, но возвращаемую переменную я не знаю как словить  я хотел бы знать как в соответствие регистру поставить указатель на переменную передаваемую или возвращаемую подпрограмме. Доки щас прочитаю. На счет inline ассемблера понял.
Сообщение отредактировал drum1987 - Mar 16 2011, 10:40
|
|
|
|
|
Mar 16 2011, 12:03
|

Местный
  
Группа: Свой
Сообщений: 397
Регистрация: 3-12-09
Из: Россия, Москва
Пользователь №: 54 040

|
Вот например, что работает в Keil у меня: CODE // 24c32.h
#ifndef _24C32_H_ #define _24C32_H_
#define EEPROM_PAGE_SIZE 32
// int readBytesFrom24C32( unsigned int eepromStartAddr, unsigned char * dest, unsigned int bytesToRead ); // int i2cSavePagesTo24C32( unsigned int eepromStartPageAddr, unsigned char * src, unsigned int pagesToWrite );
#endif CODE ; 24c32.s
AREA TEXT, CODE, READONLY ARM
EXPORT readBytesFrom24C32
; read bytes from 24C32 ; IN ; r0 - start address in 24C32 ; r1 - target buffer address in memory ; r2 - bytes count ; OUT ; r0 - error state, == 0 if no errors readBytesFrom24C32 stmfd SP!, {r1,r2,r5-r11,LR} ; prepare transfer address and work constants bl i2cSetTransferAddress ; check result tst r8, r8 movne r0, r8 bne readBytesFrom24C32_exit ; set another start condition bl i2cMakeStart ; check result tst r8, r8 movne r0, r8 bne readBytesFrom24C32_exit ; send address with /WR=1 ldr r9, =0xA1 bl i2cSendByte ; get ACK bl i2cReadAckState bne readBytesFrom24C32_deviceNotFound ; read one byte readBytesFrom24C32_loop bl i2cRecvByte ; store byte to buffer strb r9, [r1], #1 ; send ACK or NACK cmp r2, #1 ; drop SDA to 0 if need receive more bytes strne r6, [r7, #PIO_OER] ; rise SDA to 1 if it was last byte streq r6, [r7, #PIO_ODR] ; pulse SCL str r5, [r7, #PIO_ODR] ; SCL = 1 bl i2cDelay str r5, [r7, #PIO_OER] ; SCL = 0 bl i2cDelay ; loop subs r2, r2, #1 bne readBytesFrom24C32_loop ; make stop ; rise SCL up str r5, [r7, #PIO_ODR] ; SCL = 1 bl i2cDelay ; rise SDA up str r6, [r7, #PIO_ODR] ; SDA = 1 bl i2cDelay ldr r0, =0 readBytesFrom24C32_exit ldmfd SP!, {r1,r2,r5-r11,PC} readBytesFrom24C32_deviceNotFound ldr r0, =ERR_I2C_DEVICE_NOT_FOUND b readBytesFrom24C32_exit
EXPORT i2cSavePagesTo24C32
; save 1 or more pages (32 bytes per page) to EEPROM ; IN ; r0 - start address in EEPROM (32 bytes aligned!) ; r1 - source buffer in local memory ; r2 - pages count ; OUT ; r0 - error state, = 0 if no errors i2cSavePagesTo24C32 stmfd SP!, {r1,r2,r5-r12,LR} i2cSavePagesTo24C32_loop ; tries count ldr r12, =120 i2cSavePagesTo24C32_waitLoop ; prepare transfer address and work constants bl i2cSetTransferAddress ; check result tst r8, r8 beq i2cSavePagesTo24C32_sendPage subs r12, r12, #1 bne i2cSavePagesTo24C32_waitLoop ;ldr r0, =ERR_WRITE_PAGE_TIMEOUT mov r0, r8 b i2cSavePagesTo24C32_exit i2cSavePagesTo24C32_sendPage ; send page ldr r12, =EEPROM_24C32_PAGE_SIZE i2cSavePagesTo24C32_pageLoop ldrb r9, [r1], #1 bl i2cSendByte ; get ACK bl i2cReadAckState ldrne r0, =ERR_I2C_ACK_NOT_RECEIVED bne i2cSavePagesTo24C32_exit ; next byte subs r12, r12, #1 bne i2cSavePagesTo24C32_pageLoop ; make stop ; drop SDA down str r6, [r7, #PIO_OER] ; SDA = 0 bl i2cDelay ; rise SCL up str r5, [r7, #PIO_ODR] ; SCL = 1 bl i2cDelay ; rise SDA up str r6, [r7, #PIO_ODR] ; SDA = 1 bl i2cDelay ; next page addr add r0, r0, #EEPROM_24C32_PAGE_SIZE ; next page loop subs r2, r2, #1 bne i2cSavePagesTo24C32_loop ; delay after last page write ldr r12, =71000 i2cSavePagesTo24C32_delayLoop subs r12, r12, #1 bne i2cSavePagesTo24C32_delayLoop ldr r0, =0 i2cSavePagesTo24C32_exit ldmfd SP!, {r1,r2,r5-r12,PC}
|
|
|
|
|
Mar 16 2011, 12:32
|

Местный
  
Группа: Участник
Сообщений: 255
Регистрация: 3-02-09
Из: Омск
Пользователь №: 44 323

|
Цитата(scifi @ Mar 16 2011, 18:03)  Ну ё-маё. У Вас же эта функция объявлена с типом возвращаемого значения void. И Вы ещё хотите словить возвращаемое значение? Пора обратно за парту. Срочно штудируйте учебник языка Си. прошу прощенья, но эту функцию драл с примера...действия она делала немного другие, но строку возвращала  вот например пример 6.1 по адресу http://www.keil.com/support/man/docs/armcc...cc_caciddae.htm тоже void
Сообщение отредактировал drum1987 - Mar 16 2011, 12:38
|
|
|
|
|
Mar 16 2011, 12:50
|
Участник

Группа: Участник
Сообщений: 60
Регистрация: 31-08-10
Из: Минск-Витебск
Пользователь №: 59 203

|
Цитата Функция в примере никакого значения не возвращает. Просто копирует содержимое памяти с одного адреса в место с другим адресом, пока не встретиться ноль.
|
|
|
|
|
Mar 16 2011, 14:07
|

Местный
  
Группа: Участник
Сообщений: 255
Регистрация: 3-02-09
Из: Омск
Пользователь №: 44 323

|
Цитата(yashok @ Mar 16 2011, 19:50)  Функция в примере никакого значения не возвращает. Просто копирует содержимое памяти с одного адреса в место с другим адресом, пока не встретиться ноль. С этим разобрался. Спасибо. У меня вопрос немного иной(наверное я его плохо сформулировал): У меня есть функция к примеру int MULT(int A, int B ) но при этом в самой асм функции я могу оперировать лишь r0,r1.... Так вот по какому правилу у меня распределятся A,B и результат в регистры? Цитата(aaarrr @ Mar 16 2011, 17:00)  Правила описаны в стандарте AAPCS. Пропустил...Это то, что мне нужно
Сообщение отредактировал drum1987 - Mar 16 2011, 13:57
|
|
|
|
|
Mar 18 2011, 09:23
|
Участник

Группа: Участник
Сообщений: 60
Регистрация: 31-08-10
Из: Минск-Витебск
Пользователь №: 59 203

|
Попробуйте написать функции с требуемым количеством аргументов на си. Запустите все это дело в симуляторе и посмотрите в дисассемблере как с это сделал компилятор.
|
|
|
|
|
Mar 18 2011, 12:16
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(drum1987 @ Mar 18 2011, 11:36)  как быть если необходимо передать функции больше чем 4 переменных В этом случае используется стек. Цитата(drum1987 @ Mar 18 2011, 11:36)  как поступись в случае если требуется фунции передавать данные так:
mult(out, out, in, in, param, param, param) Поясните, чем этот случай отличается от "более четырех параметров"?
|
|
|
|
|
Mar 18 2011, 13:08
|

Местный
  
Группа: Участник
Сообщений: 255
Регистрация: 3-02-09
Из: Омск
Пользователь №: 44 323

|
Цитата(aaarrr @ Mar 18 2011, 19:16)  Поясните, чем этот случай отличается от "более четырех параметров"? Это был один и тот же вопрос... Код #include <stdio.h>
static __asm int MUL_F1(int rezult, int x, int y) { smull r5, r0, r2, r1; BX lr ; Return. }
static __inline int MUL_F2(int x, int y) { volatile int rezult; MUL_F1(rezult, x, y); return rezult; }
int main(void) { volatile int x=0xfffff, y=0xffff; volatile int z;
z=MUL_F2(x, y); } Наваял прогу, после выполнения асм функции MUL_F1 в R0 как и положено кладется нужный мне результат, но перевенная rezult не меняется. Понимаю что косяк детский и скорее всего я просто чтото не понимаю, поэтому прошу сильно не пинать...
|
|
|
|
|
Mar 18 2011, 13:23
|
Участник

Группа: Участник
Сообщений: 60
Регистрация: 31-08-10
Из: Минск-Витебск
Пользователь №: 59 203

|
Цитата Наваял прогу, после выполнения асм функции MUL_F1 в R0 как и положено кладется нужный мне результат, но перевенная rezult не меняется А почему она должна меняться?? Вы предаете параметры по значению.
Сообщение отредактировал yashok - Mar 18 2011, 13:23
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|