|
Не удается повторить сишный код в асме АРМ., контроллер at91sam7s |
|
|
|
Nov 23 2009, 06:15
|
Местный
  
Группа: Участник
Сообщений: 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 это правильно? Заранее благодарен.
|
|
|
|
|
Nov 23 2009, 06:34
|
Местный
  
Группа: Участник
Сообщений: 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
|
|
|
|
|
Nov 23 2009, 06:50
|
Гуру
     
Группа: Свой
Сообщений: 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-компилятор.
|
|
|
|
|
Nov 23 2009, 07:30
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(Bulat @ Nov 23 2009, 09:34)  асм-код не работает так же, как и сишный Для начала стоит ознакомится с тем кодом, который был сгенерирован компилятором - на 100% уверен, что он компактнее и быстрее приведенного ассемблерного фрагмента (пожалуй, даже при выключенной оптимизации). Кроме того, если уж хотите использовать ассемблер, стоит почитать стандарт AAPCS - ваш код может быть неработоспособен хотя бы потому, что с регистрами R4-R11 так обращаться нельзя. Да, ну и логика работы C и asm программ у вас отличаются - первая не вываливается по условию "if(ii==0)".
|
|
|
|
|
Nov 23 2009, 09:13
|
Местный
  
Группа: Участник
Сообщений: 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 где тут ошибка?
|
|
|
|
|
Nov 23 2009, 09:27
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Цитата(Bulat @ Nov 23 2009, 15:13)  Почему не выходит по условию ii==0? Код sub r0, r0, #1 ;ii-- где тут ошибка? sub не устанавливает флаги. Нужно SUB S
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
Nov 23 2009, 09:44
|
Местный
  
Группа: Участник
Сообщений: 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
|
|
|
|
|
Nov 23 2009, 10:18
|
Местный
  
Группа: Участник
Сообщений: 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,... и напрямую к нему обращаться из сишного когда?
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|