Trouble interpreting compiler asm

Go To Last Post
7 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have the following code in my ATMega 6450 program:

 

    x = read_fuse();    // Read fuse high byte to check OCDEN
    if (x & (1 << OCDEN) != 0) { 
    ...

The compiler turns it into this asm:

(0749)     x = read_fuse();    // Read fuse high byte to check OCDEN
    004B3 D018      RCALL    _read_fuse
    004B4 2EA0      MOV    R10,R16
(0750)     if (x & (1 << OCDEN) != 0) {
    004B5 FF00      SBRS    R16,0
    004B6 C006      RJMP    0x04BD

I've confirmed that the asm places the fuse high byte in R16 (in the read_fuse() function).  OCDEN, however, is bit 7 in the fuse byte, so I can't figure out why the SBRS instruction at 004B5 is testing bit 0.  What's more, the value of the fuse byte (and x) is 0x19, yet the if statement evaluates to true.  Is (1 << OCDEN) being compared to 0 before being ANDed with x?  What am I doing wrong?  Thanks.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Which compiler?  Doesn't seem like avr-gcc, since that would return function arguments in r24, and named the bit FUSE_OCDEN...

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Imagecraft Jumpstart C.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Check your C precedence table.  != is higher than &.  Use more parentheses.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks. That's easy to fix. What about the SBRS?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I get the correct bit 7 and it is skipping the RJMP instrucion if the bit is set

 

(0033)      x = read_fuse();    // Read fuse high byte to check OCDEN
_main:
    000B2 DFF8      RCALL	_read_fuse
    000B3 9300 0100 STS	_x,R16
(0034) 
(0035)     if ((x & (1 << OCDEN)) != 0)
    000B5 FF07      SBRS	R16,7
    000B6 C002      RJMP	0x00B9
(0036)         {
(0037)         PORTA=0;
    000B7 2422      CLR	R2
    000B8 B822      OUT	0x02,R2
(0038)         }
(0039)     }while(0);
(0040) 
(0041)     return 0;
    000B9 2700      CLR	R16
    000BA 2711      CLR	R17
    000BB 9508      RET

 

C code

 

#include <iccioavr.h>
#include <macros.h>

unsigned char x;

char read_fuse(void) {

//  point z to 0x0003 (high fuse byte )

asm("ldi R31,0x00\n"

"ldi  R30,0x03\n"

"ldi  R16,0x05\n"       //(1<<BLBSET | 1<<SPMEN 0x05

"out  0x37,R16\n"       // SPMCSR

"lpm  R16,z\n"

"ret\n");
}

int main(void)
{

    // Insert code

    do
    {
     x = read_fuse();    // Read fuse high byte to check OCDEN

    if ((x & (1 << OCDEN)) != 0)
        {
        PORTA=0;
        }
    }while(0);

    return 0;
}

 

I'm really disappointed that the in line assembly doesn't understand BLBSET  SPMEN or even SPMCSR even though they are defined in the header file which, by the way, the project "wizard" or what ever is called did NOT include in the start file generated even though the correct chip was selected in the drop down menu.

 

But I guess it's silly ol' me again. cheeky

 

Boy I really must find something more useful to combat boredom. devil

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Aah, maybe it's the proper parens that are producing the right bit to test. I'm not at my PC but I'll test it both ways in the morning. Thanks again for your effort.

Karl