|
本帖最后由 Joesn 于 2014-3-8 14:44 编辑
编译器: WinAVR
IDE: Code::Blocks 13.12
AVR指令集中没有像51的ROL ROR等循环位移指令,最近要用到,所以我想着写一段汇编去实现这个。
于是我写了这么一段宏:
- #define right_rotate_byte(data) \
- __asm__ __volatile__ ( \
- "lsr %0" "\n\t" \
- "sbrc __SREG__, 0" "\n\t" \
- "sbr %0,128" "\n\t" \
- :"=r" (data) \
- :"0" (data) \
- )
- #define left_rotate_byte(data) \
- __asm__ __volatile__ ( \
- "lsl %0" "\n\t" \
- "sbrc __SREG__,0" "\n\t" \
- "inc %0" "\n\t" \
- :"=r" (data) \
- :"0" (data) \
- )
复制代码
我在编译的时候,编译器提示我出错:
C:\Users\Forward\AppData\Local\Temp/cccafCoM.s: Assembler messages:
C:\Users\Forward\AppData\Local\Temp/cccafCoM.s:87: Error: number must be positive and less than 32
C:\Users\Forward\AppData\Local\Temp/cccafCoM.s:87: Error: register name or number from 0 to 31 required
C:\Users\Forward\AppData\Local\Temp/cccafCoM.s:113: Error: number must be positive and less than 32
C:\Users\Forward\AppData\Local\Temp/cccafCoM.s:113: Error: register name or number from 0 to 31 required
看文字很奇怪。于是我查看了它生成的汇编:
- ld r25,Z
- .LVL2:
- .LM7:
- mov r24,r25
- /* #APP */
- ; 97 "display.c" 1
- lsr r24
- sbrc __SREG__, 0
- sbr r24,128
-
- ; 0 "" 2
- /* #NOAPP */
- st Z,r24
复制代码
显然用到的寄存器是r0-r31里面的!
于是我觉得很奇怪了。究竟是什么问题了?
后来我写了个C样式的宏,但是编译器优化后就不能用左循环移位,于是最终只能用到函数(囧)效率差了点。
我上传一下代码吧(主要是实现16*16LED点阵屏的显示,还没写好):
- #include <avr/io.h>
- #include <avr/interrupt.h>
- #include <avr/pgmspace.h>
- #include <string.h>
- #include "display.h"
- const char table_number[][16] PROGMEM =
- {
- {0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00}, //number '0'
- {0x00,0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00} //number '1'
- };
- static uint8_t buf[16][2];
- /*
- void left_rotate_byte(uint8_t * tmp)
- {
- *tmp <<= 1;
- if (SREG & _BV(SREG_C))
- {
- (*tmp) ++;
- }
- }
- void right_rotate_byte(uint8_t * tmp)
- {
- *tmp >>= 1;
- if (SREG & _BV(SREG_C))
- {
- (*tmp) |= 0x80;
- }
- }
- */
- void display_init(void)
- {
- memset(buf, 0, sizeof(buf));
- DISPLAY_DDR = 0XFF;
- TCCR1A = 0x00;
- TCCR1B = 0x18;
- ICR1 = F_CPU/64/500 - 1;
- TIMSK |= 0X20;
- TCCR1B |= 0X03; //start the timer
- sei();
- }
- void display_number(uint8_t number)
- {
- uint8_t i,j;
- if (number < 10)
- {
- for (i=0; i < 16; i++)
- {
- buf[i][0] = pgm_read_byte(&table_number[0][i]);
- }
- for (i=0; i < 16; i++)
- {
- buf[i][1] = pgm_read_byte(&table_number[number][i]);
- }
- }
- else if (number < 100)
- {
- j = number / 10;
- for (i=0; i < 16; i++)
- {
- buf[i][0] = pgm_read_byte(&table_number[j][i]);
- }
- j = number % 10;
- for (i=0; i < 16; i++)
- {
- buf[i][1] = pgm_read_byte(&table_number[j][i]);
- }
- }
- else
- {
- memset(buf, 0, sizeof(buf));
- }
- }
- ISR(TIMER1_CAPT_vect)
- {
- uint8_t i,tmp;
- uint8_t row = DISPLAY_PORT & 0X0F;
- DISPLAY_PORT |= _BV(GATE); //shutdown the output
- if (row == 0X0F)
- {
- row = 0;
- }
- else
- {
- row++;
- }
- for (i=0; i < 8; i++)
- {
- tmp = buf[row][0];
- right_rotate_byte(buf[row][0]);
- tmp &= _BV(DI);
- tmp |= _BV(GATE);
- DISPLAY_PORT = tmp;
- DISPLAY_PORT |= _BV(CLK);
- tmp = buf[row][1];
- right_rotate_byte(buf[row][1]);
- tmp &= _BV(DI);
- tmp |= _BV(GATE);
- DISPLAY_PORT = tmp;
- DISPLAY_PORT |= _BV(CLK);
- }//move the data to shift register
- DISPLAY_PORT |= _BV(LATCH);
- DISPLAY_PORT |= row;
- DISPLAY_PORT &= _BV(GATE); //turn on the output
- }
复制代码
头文件:
- #ifndef DISPALY_H_INCLUDED
- #define DISPALY_H_INCLUDED
- #include <avr/interrupt.h>
- //#define DISPLAY_LEFT 0
- //#define DISPLAY_RIGHT 1
- #define DISPLAY_DDR DDRC
- #define DISPLAY_PORT PORTC
- #define BIT_A 0
- #define BIT_B 1
- #define BIT_C 2
- #define BIT_D 3
- #define GATE 4
- #define CLK 5
- #define LATCH 6
- #define DI 7
- /*
- #define right_rotate_byte(data) data >>= 1 ;\
- if (SREG & 0X01) data |= 0x80
- #define left_rotate_byte(data) data <<= 1 ;\
- if (SREG & 0X01) data ++
- */
- #define right_rotate_byte(data) \
- __asm__ __volatile__ ( \
- "lsr %0" "\n\t" \
- "sbrc __SREG__, 0" "\n\t" \
- "sbr %0,128" "\n\t" \
- :"=r" (data) \
- :"0" (data) \
- )
- #define left_rotate_byte(data) \
- __asm__ __volatile__ ( \
- "lsl %0" "\n\t" \
- "sbrc __SREG__,0" "\n\t" \
- "inc %0" "\n\t" \
- :"=r" (data) \
- :"0" (data) \
- )
- #define right_rotate_hword(data) \
- __asm__ __volatile__ ( \
- "lsr %B0" "\n\t" \
- "ror %A0" "\n\t" \
- "sbrc __SREG__,0" "\n\t" \
- "sbr %B0,128" "\n\t" \
- :"=r" (data) \
- :"0" (data) \
- )
- #define left_rotate_hword(data) \
- __asm__ __volatile__ ( \
- "lsl %A0" "\n\t" \
- "rol %B0" "\n\t" \
- "sbrc __SREG__,0" "\n\t" \
- "inc %A0" "\n\t" \
- :"=r" (data) \
- :"0" (data) \
- )
- void display_init(void);
- //void display_flush(void);
- void display_number(uint8_t number);
- void display_left_shift(void);
- void display_right_shift(void);
- void display_up_shift(void);
- void display_down_shift(void);
- void display_clear_screen(void);
- //void left_rotate_byte(uint8_t * tmp);
- //void right_rotate_byte(uint8_t * tmp);
- #endif // DISPALY_H_INCLUDED
复制代码
生成的汇编代码就不传了。。太多了,
然后想问下,有哪位知道这可能是什么问题? |
阿莫论坛20周年了!感谢大家的支持与爱护!!
知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)
|