搜索
bottom↓
回复: 1

在Winavr中用内联汇编出现的奇怪错误

[复制链接]

出0入0汤圆

发表于 2014-3-8 14:44:31 | 显示全部楼层 |阅读模式
本帖最后由 Joesn 于 2014-3-8 14:44 编辑

编译器: WinAVR
IDE: Code::Blocks 13.12
AVR指令集中没有像51的ROL ROR等循环位移指令,最近要用到,所以我想着写一段汇编去实现这个。
于是我写了这么一段宏:
  1. #define right_rotate_byte(data) \
  2.                 __asm__ __volatile__ (        \
  3.                                 "lsr %0" "\n\t"        \
  4.                                 "sbrc __SREG__, 0" "\n\t"        \
  5.                                 "sbr %0,128" "\n\t"                        \
  6.                                 :"=r" (data)                                \
  7.                                 :"0" (data)                                        \
  8.                                 )


  9. #define left_rotate_byte(data)        \
  10.                 __asm__ __volatile__ (        \
  11.                                 "lsl %0" "\n\t"        \
  12.                                 "sbrc __SREG__,0" "\n\t"        \
  13.                                 "inc %0" "\n\t"                                \
  14.                                 :"=r" (data)                                \
  15.                                 :"0" (data)                                        \
  16.                                 )
复制代码


我在编译的时候,编译器提示我出错:
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

看文字很奇怪。于是我查看了它生成的汇编:
  1.         ld r25,Z
  2. .LVL2:
  3. .LM7:
  4.         mov r24,r25
  5. /* #APP */
  6. ;  97 "display.c" 1
  7.         lsr r24
  8.         sbrc __SREG__, 0
  9.         sbr r24,128
  10.        
  11. ;  0 "" 2
  12. /* #NOAPP */
  13.         st Z,r24
复制代码


显然用到的寄存器是r0-r31里面的!
于是我觉得很奇怪了。究竟是什么问题了?
后来我写了个C样式的宏,但是编译器优化后就不能用左循环移位,于是最终只能用到函数(囧)效率差了点。
我上传一下代码吧(主要是实现16*16LED点阵屏的显示,还没写好):
  1. #include <avr/io.h>
  2. #include <avr/interrupt.h>
  3. #include <avr/pgmspace.h>
  4. #include <string.h>
  5. #include "display.h"

  6. const char table_number[][16] PROGMEM =
  7.                 {
  8.                         {0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00},        //number '0'
  9.                         {0x00,0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00}        //number '1'
  10.                 };

  11. static uint8_t buf[16][2];

  12. /*
  13. void left_rotate_byte(uint8_t * tmp)
  14. {
  15.         *tmp <<= 1;
  16.         if (SREG & _BV(SREG_C))
  17.         {
  18.                 (*tmp) ++;
  19.         }
  20. }
  21. void right_rotate_byte(uint8_t * tmp)
  22. {
  23.         *tmp >>= 1;
  24.         if (SREG & _BV(SREG_C))
  25.         {
  26.                 (*tmp) |= 0x80;
  27.         }
  28. }
  29. */

  30. void display_init(void)
  31. {
  32.         memset(buf, 0, sizeof(buf));
  33.         DISPLAY_DDR = 0XFF;
  34.         TCCR1A = 0x00;
  35.         TCCR1B = 0x18;
  36.         ICR1 = F_CPU/64/500 - 1;
  37.         TIMSK |= 0X20;
  38.         TCCR1B |= 0X03;        //start the timer
  39.         sei();
  40. }

  41. void display_number(uint8_t number)
  42. {
  43.         uint8_t i,j;
  44.         if (number < 10)
  45.         {
  46.                 for (i=0; i < 16; i++)
  47.                 {
  48.                         buf[i][0] = pgm_read_byte(&table_number[0][i]);
  49.                 }
  50.                 for (i=0; i < 16; i++)
  51.                 {
  52.                         buf[i][1] = pgm_read_byte(&table_number[number][i]);
  53.                 }
  54.         }
  55.         else if (number < 100)
  56.         {
  57.                 j = number / 10;
  58.                 for (i=0; i < 16; i++)
  59.                 {
  60.                         buf[i][0] = pgm_read_byte(&table_number[j][i]);
  61.                 }
  62.                 j = number % 10;
  63.                 for (i=0; i < 16; i++)
  64.                 {
  65.                         buf[i][1] = pgm_read_byte(&table_number[j][i]);
  66.                 }
  67.         }
  68.         else
  69.         {
  70.                 memset(buf, 0, sizeof(buf));
  71.         }
  72. }

  73. ISR(TIMER1_CAPT_vect)
  74. {
  75.         uint8_t i,tmp;
  76.         uint8_t row = DISPLAY_PORT & 0X0F;

  77.         DISPLAY_PORT |= _BV(GATE);        //shutdown the output
  78.         if (row == 0X0F)
  79.         {
  80.                 row = 0;
  81.         }
  82.         else
  83.         {
  84.                 row++;
  85.         }

  86.         for (i=0; i < 8; i++)
  87.         {
  88.                 tmp = buf[row][0];
  89.                 right_rotate_byte(buf[row][0]);
  90.                 tmp &= _BV(DI);
  91.                 tmp |= _BV(GATE);
  92.                 DISPLAY_PORT = tmp;
  93.                 DISPLAY_PORT |= _BV(CLK);

  94.                 tmp = buf[row][1];
  95.                 right_rotate_byte(buf[row][1]);
  96.                 tmp &= _BV(DI);
  97.                 tmp |= _BV(GATE);
  98.                 DISPLAY_PORT = tmp;
  99.                 DISPLAY_PORT |= _BV(CLK);
  100.         }//move the data to shift register

  101.         DISPLAY_PORT |= _BV(LATCH);
  102.         DISPLAY_PORT |= row;
  103.         DISPLAY_PORT &= _BV(GATE);        //turn on the output
  104. }
复制代码


头文件:
  1. #ifndef DISPALY_H_INCLUDED
  2. #define DISPALY_H_INCLUDED

  3. #include <avr/interrupt.h>

  4. //#define DISPLAY_LEFT        0
  5. //#define DISPLAY_RIGHT        1
  6. #define DISPLAY_DDR                DDRC
  7. #define DISPLAY_PORT        PORTC

  8. #define BIT_A        0
  9. #define BIT_B        1
  10. #define BIT_C        2
  11. #define        BIT_D        3
  12. #define        GATE        4
  13. #define        CLK                5
  14. #define        LATCH        6
  15. #define        DI                7

  16. /*
  17. #define right_rotate_byte(data)        data >>= 1 ;\
  18.                                                                 if (SREG & 0X01)        data |= 0x80
  19. #define left_rotate_byte(data)         data <<= 1 ;\
  20.                                                                 if (SREG & 0X01)        data ++

  21. */
  22. #define right_rotate_byte(data)                 \
  23.                 __asm__ __volatile__ (        \
  24.                                 "lsr %0" "\n\t"        \
  25.                                 "sbrc __SREG__, 0" "\n\t"                \
  26.                                 "sbr %0,128" "\n\t"                        \
  27.                                 :"=r" (data)                                \
  28.                                 :"0" (data)                                        \
  29.                                 )


  30. #define left_rotate_byte(data)                \
  31.                 __asm__ __volatile__ (        \
  32.                                 "lsl %0" "\n\t"        \
  33.                                 "sbrc __SREG__,0" "\n\t"                \
  34.                                 "inc %0" "\n\t"                                \
  35.                                 :"=r" (data)                                \
  36.                                 :"0" (data)                                        \
  37.                                 )


  38. #define right_rotate_hword(data)        \
  39.                 __asm__ __volatile__ (                        \
  40.                                 "lsr %B0" "\n\t"                        \
  41.                                 "ror %A0" "\n\t"                        \
  42.                                 "sbrc __SREG__,0" "\n\t"        \
  43.                                 "sbr %B0,128" "\n\t"                \
  44.                                 :"=r" (data)                        \
  45.                                 :"0" (data)                                \
  46.                                 )

  47. #define left_rotate_hword(data)                                \
  48.                 __asm__ __volatile__ (                        \
  49.                                 "lsl %A0" "\n\t"                        \
  50.                                 "rol %B0" "\n\t"                        \
  51.                                 "sbrc __SREG__,0" "\n\t"        \
  52.                                 "inc %A0" "\n\t"                        \
  53.                                 :"=r" (data)                        \
  54.                                 :"0" (data)                                \
  55.                                 )

  56. void display_init(void);
  57. //void display_flush(void);
  58. void display_number(uint8_t number);
  59. void display_left_shift(void);
  60. void display_right_shift(void);
  61. void display_up_shift(void);
  62. void display_down_shift(void);
  63. void display_clear_screen(void);

  64. //void left_rotate_byte(uint8_t * tmp);
  65. //void right_rotate_byte(uint8_t * tmp);

  66. #endif // DISPALY_H_INCLUDED
复制代码


生成的汇编代码就不传了。。太多了,
然后想问下,有哪位知道这可能是什么问题?

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

 楼主| 发表于 2014-3-8 16:18:49 | 显示全部楼层
我是菜鸟,程序很多错。。。大家别见怪。。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-24 00:26

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表