Joesn 发表于 2014-3-8 14:44:31

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

本帖最后由 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[] 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;

/*
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 = pgm_read_byte(&table_number);
                }
                for (i=0; i < 16; i++)
                {
                        buf = pgm_read_byte(&table_number);
                }
        }
        else if (number < 100)
        {
                j = number / 10;
                for (i=0; i < 16; i++)
                {
                        buf = pgm_read_byte(&table_number);
                }
                j = number % 10;
                for (i=0; i < 16; i++)
                {
                        buf = pgm_read_byte(&table_number);
                }
        }
        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;
                right_rotate_byte(buf);
                tmp &= _BV(DI);
                tmp |= _BV(GATE);
                DISPLAY_PORT = tmp;
                DISPLAY_PORT |= _BV(CLK);

                tmp = buf;
                right_rotate_byte(buf);
                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


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

Joesn 发表于 2014-3-8 16:18:49

我是菜鸟,程序很多错。。。大家别见怪。。
页: [1]
查看完整版本: 在Winavr中用内联汇编出现的奇怪错误