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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Не удается повторить сишный код в асме АРМ., контроллер at91sam7s
Bulat
сообщение Nov 23 2009, 06:15
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241



мне необходимо реализовать на асм-е следующий сишный код:
Код
if(datA&0x80000000) regA = 0x20000;
else regA = 0x0;

Но операнд в ARM-команде может иметь макс длину 12 бит, поэтому в асм-е я поступаю следующим образом:
Код
;r1 = datA, regA = r6
  mov      r6, r1
  mov      r6, r6, lsr #28
  and       r6, r6, #0x8                                                    
  ldrne     r6, =0x20000                                                    ;if(datA&0x80000000) regA = 0x20000
  ldreq     r6, =0                                                              ;else regA = 0x0

это правильно?
Заранее благодарен.
Go to the top of the page
 
+Quote Post
Bulat
сообщение Nov 23 2009, 06:34
Сообщение #2


Местный
***

Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241



мне необходимо реализовать на асм-е следующий сишный код - обработчик прерывания таймера:
Код
__ramfunc void timer0_irq_handler()
{  
  ii--;                                                                          
  if(ii==0) {MipsTimerBase->TC_CCR = AT91C_TC_CLKDIS;}
  MipsTimerBase->TC_RA = 30; MipsTimerBase->TC_RB = MipsTimerBase->TC_RC = 60;
  
  if(datA&0x80000000) regA = 0x20000;
  else regA = 0x0;
  regs->PIOA_ODSR = regA|front;    
  datA = datA<<1;  
    
  dummy = MipsTimerBase->TC_SR;  
}

Этот код рабочий, благодаря ему я получаю необходимую последовательность импульсов на выходе.
Так я повторил этот код на асме АРМ:
При прирывании вызываетя следующая функция:
__ramfunc void ASM_timer0_irq()
{
timer0_irq_ASM(ii,datA,front);
}
которая в свою очередь вызывает асм-функциюи сообщает туда 3 параметра.

Код
IO_base         DEFINE  0xFFFFF400
ODSR            DEFINE  0x38
TC_base         DEFINE  0xFFFA0000
TC0_CCR       DEFINE  0x0
TC0_RA          DEFINE  0x14
TC0_RB          DEFINE  0x18
TC0_RC          DEFINE  0x1C
TC0_SR          DEFINE  0x20
TC_CLKDIS     DEFINE  0x2          

PUBLIC     timer0_irq_ASM
                                                            
timer0_irq_ASM                                                                 ;r0 = ii, r1 = dataA, r2 = front

  ldr     r12,=TC_base                                                         ;смещение для TC
  ldr     r11,=IO_base                                                         ;смещение для PIO
  sub     r0, r0, #1                                                              ;ii--
  beq     Stop_TC0
  bne     Work_TC0

Stop_TC0:
  ldr      r7, =TC_CLKDIS
  str      r7,[r12,#TC0_CCR]                                                   ;MipsTimerBase->TC_CCR = AT91C_TC_CLKDIS
  b        timer0_irq_ASM_end  
  
  Work_TC0:
  ldr      r7, =30
  str      r7,[r12, #TC0_RA]                                                    ;MipsTimerBase->TC_RA = 30
  ldr      r7, =60
  str      r7, [r12, #TC0_RB]                                                    ;MipsTimerBase->TC_RB = 60
  str      r7, [r12, #TC0_RC]                                                    ;MipsTimerBase->TC_RC = 60
  
  
  mov      r6, r1, lsr #28                                                       ;смещаем содержимое r1 (datA) вправо на 28 бит, так как операнд не может быть больше 12 бит в длину, а мне необходимо анализировать состояние 32-бита r1
  and      r6, r6, #0x8                                                    
  ldrne    r6, =0x20000                                                        ;if(datA&0x80000000) regA = 0x20000
  ldreq    r6, =0                                                                  ;else regA = 0x0
  orr      r6, r6, r2
  str      r6, [r11, #ODSR]                                                      ;regs->PIOA_ODSR = regA|front
  mov      r0, r0, lsl #1                                                          ;datA = datA<<1
  ldr      r6, [r12, #TC0_SR]                                                    ;dummy = MipsTimerBase->TC_SR
    

  timer0_irq_ASM_end:
  bx       lr

асм-код не работает так же, как и сишный. то есть таймер запускается, импульсы нужной частоты идут, но таймер не останавливается при обнулении счетчика ii и не меняет ldrne r6, =0x20000 или ldreq r6, =0 в зависимости от содержимого r1.

Заранее благодарен.

Сообщение отредактировал Bulat - Nov 23 2009, 07:05
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Nov 23 2009, 06:50
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Bulat @ Nov 23 2009, 09:34) *
это правильно?

Нет, правильно будет так:
Код
;r1 = datA, regA = r6
ANDS     r6,r1,#0x80000000
MOVNE    r6,#0x20000

Числа вида "константа со сдвигом" можно загружать командой MOV. Ну а вообще в таких конструкциях бесполезно пытаться переплюнуть C-компилятор.
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Nov 23 2009, 07:02
Сообщение #4


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



Код
tst         r1, #2, 2; -2147483648 (0x80000000)
movne       r6, #2, 16
moveq       r6, #0
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Nov 23 2009, 07:30
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Bulat @ Nov 23 2009, 09:34) *
асм-код не работает так же, как и сишный

Для начала стоит ознакомится с тем кодом, который был сгенерирован компилятором - на 100% уверен, что он компактнее и быстрее приведенного ассемблерного фрагмента (пожалуй, даже при выключенной оптимизации).
Кроме того, если уж хотите использовать ассемблер, стоит почитать стандарт AAPCS - ваш код может быть неработоспособен хотя бы потому, что с регистрами R4-R11 так обращаться нельзя.

Да, ну и логика работы C и asm программ у вас отличаются - первая не вываливается по условию "if(ii==0)".
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Nov 23 2009, 08:06
Сообщение #6


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



Авторы многих книг предупреждают о вреде преждевременной оптимизации. На практике это означает, что сначала надо написать работоспособную программу, а потом заниматься поиском узких мест в ней (если такие будут иметь место) и их оптимизацией.
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Nov 23 2009, 08:52
Сообщение #7


.
******

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



Цитата(sergeeff @ Nov 23 2009, 14:06) *
Авторы многих книг предупреждают о вреде преждевременной оптимизации.

smile.gif Можно с этого места поподробней. Прямо как преждевременные роды smile.gif


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
andrew_b
сообщение Nov 23 2009, 08:58
Сообщение #8


Профессионал
*****

Группа: Свой
Сообщений: 1 975
Регистрация: 30-12-04
Из: Воронеж
Пользователь №: 1 757



Цитата(GetSmart @ Nov 23 2009, 12:52) *
smile.gif Можно с этого места поподробней. Прямо как преждевременные роды smile.gif

google://"premature optimization is root of all evil"
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Nov 23 2009, 09:08
Сообщение #9


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



Цитата(GetSmart @ Nov 23 2009, 11:52) *
smile.gif Можно с этого места поподробней. Прямо как преждевременные роды smile.gif


Применительно к данному топику: что за нужда писать обработчик прерывания на ассемблере? Не хватает скорости обработки? С/С++ компиляторы генерят не слишком эффективный код? Автор все написал супер эффективно и без ошибок?

Как говорят театральные работники - не верю!
Go to the top of the page
 
+Quote Post
Bulat
сообщение Nov 23 2009, 09:13
Сообщение #10


Местный
***

Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241



Цитата(aaarrr @ Nov 23 2009, 13:30) *
Да, ну и логика работы C и asm программ у вас отличаются - первая не вываливается по условию "if(ii==0)".

Почему не выходит по условию ii==0?
Код
  sub     r0, r0, #1     ;ii--
  beq     Stop_TC0     ;r0 == 0
  bne     Work_TC0    ;r0 !=0

где тут ошибка?
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Nov 23 2009, 09:27
Сообщение #11


.
******

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



Цитата(Bulat @ Nov 23 2009, 15:13) *
Почему не выходит по условию ii==0?
Код
  sub     r0, r0, #1    ;ii--
где тут ошибка?

sub не устанавливает флаги. Нужно SUBS


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Nov 23 2009, 09:35
Сообщение #12


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



Быстрее и короче:

Код
  ldr     r12,=TC_base                                                    ;смещение для TC
  ldr     r11,=IO_base                                                    ;смещение для PIO
  subs     r0, r0, #1                                                            ;ii--
  bne     Work_TC0

Stop_TC0:
  ldr      r7, =TC_CLKDIS
  str      r7,[r12,#TC0_CCR]                                    ;MipsTimerBase->TC_CCR = AT91C_TC_CLKDIS
  bx      lr
Go to the top of the page
 
+Quote Post
Bulat
сообщение Nov 23 2009, 09:44
Сообщение #13


Местный
***

Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241



Цитата(GetSmart @ Nov 23 2009, 15:27) *
sub не устанавливает флаги. Нужно SUBS


вроде все исправил. но картинка на осциллографе без изменений. таймер запускается с нужной частотой, но не останавливается когда нужно и данные не передаются:
Код
IO_base         DEFINE  0xFFFFF400
ODSR            DEFINE  0x38
TC_base         DEFINE  0xFFFA0000
TC0_CCR       DEFINE  0x0
TC0_RA          DEFINE  0x14
TC0_RB          DEFINE  0x18
TC0_RC          DEFINE  0x1C
TC0_SR          DEFINE  0x20
TC_CLKDIS     DEFINE  0x2  

  PUBLIC     timer0_irq_ASM
                                                            
timer0_irq_ASM                                                                 ;r0 = ii, r1 = dataA, r2 = front

  ldr     r12,=TC_base                                                         ;смещение, для обращения к регистрам TC
  subs    r0, r0, #1                                                             ;ii--
  bne     Work_TC0
  beq     Stop_TC0
  
  
Stop_TC0:
  ldr      r3, =TC_CLKDIS
  str      r3,[r12,#TC0_CCR]                                                   ;MipsTimerBase->TC_CCR = AT91C_TC_CLKDIS
  b        timer0_irq_ASM_end    

  
Work_TC0:
  ldr      r3, =30
  str      r3,[r12, #TC0_RA]                                                    ;MipsTimerBase->TC_RA = 30
  ldr      r3, =60
  str      r3, [r12, #TC0_RB]                                                    ;MipsTimerBase->TC_RB = 60
  str      r3, [r12, #TC0_RC]                                                    ;MipsTimerBase->TC_RC = 60  
  
  ands     r3, r1, #0x80000000                                                    
  movne    r3, #0x20000                                                        ;if(datA&0x80000000) regA = 0x20000
  moveq    r3, #0                                                              ;else regA = 0x0
  
  orr      r3, r3, r2
  ldr      r12,=IO_base
  str      r3, [r12, #ODSR]                                                      ;regs->PIOA_ODSR = regA|front
  mov      r0, r0, lsl #1                                                         ;datA = datA<<1
  ldr      r12,=TC_base
  ldr      r3, [r12, #TC0_SR]                                                    ;dummy = MipsTimerBase->TC_SR

  timer0_irq_ASM_end:
  bx       lr
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Nov 23 2009, 10:02
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Bulat, вы с дизассемблированным кодом C-программы ознакомились? От этого надо начинать.
Более того, могу с уверенностью сказать, что руками оптимизировать там нечего.
Go to the top of the page
 
+Quote Post
Bulat
сообщение Nov 23 2009, 10:18
Сообщение #15


Местный
***

Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241



Цитата(aaarrr @ Nov 23 2009, 16:02) *
Bulat, вы с дизассемблированным кодом C-программы ознакомились? От этого надо начинать.
Более того, могу с уверенностью сказать, что руками оптимизировать там нечего.

В дизассемблированном коде программы на одну операцию сдвига datA = datA<<1 приходится 5 асм-команд, в то время, как у меня в асм-коде на это тратится одна команда mov r0, r0, lsl #1.
А можно в Си-коде, допустим, в качестве сдвиговой переменной datA назначить один из регистров r0,r1,... и напрямую к нему обращаться из сишного когда?
Go to the top of the page
 
+Quote Post

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

 


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


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