EmbeddedRelated.com
Forums
Memfault Beyond the Launch

Re: Branch out of Range

Started by Bill Walker October 30, 2004
Actually the range of a branch is -128 to +127.

One other quirk in 68HC11 coding is that if you need to conditionally
branch to some where far away, then you have to branch over a jump
instruction using
the opposite condition. Like this:

BNE SKIP
JMP GOBACK ; You really wanted a branch on equal
SKIP ... ----- Original Message -----
From: "Darren" <>
To: <>
Sent: Saturday, November 06, 2004 2:41 AM
Subject: RE: [m68HC11] Branch out of Range >
> Hi Nimish
>
> Branch only has an 8 bit range, you will have to change
> how you do things. Change the code use more subroutines or
> use a jump instead.
>
> Branch is +128 to -127 if I remember correctly.
>
> Welcome to assembly... hehe
>
> Darren Moore
>
> > -----Original Message-----
> > From: nimish_sudan [mailto:]
> >
> >
> > Hey guys, another question here. I've got a program which originally
> > worked fine. I then added some lines of code to it, which also work
> > fine by themselves. But after I added these new lines of code, the
> > assembler started giving the error Branch out of Range.
> > I then tried logically to see why the BRA function would not work.
> > So what I had was:
> >
> > LOOP1
> > LDAA ....
> > ...
> > ...
> > BRA LOOP1 <-- it would give error here
> > ....
> >
> > So what I did was this:
> >
> > LOOP1
> > LDAA ....
> > ...
> > ...
> > BRA LOOPTRICK
> > ...
> > LOOPTRICK BRA LOOP1 (trying to trick it)
> >
> > I was just trying different things and discovered that the error now
> > was being displayed at the LOOPTRICK line. I also found out that if
> > I comment a few random lines of code, the error would no longer
> > appear. I'm kind of new to assembly, so I'm approaching this from a
> > C++ stand point. Is this some sort of memory issue? Seems to me that
> > I am somehow overwriting the code in memory which is why the error
> > disappears when I comment out a few lines.
> > Any help would be appreciated! >
> Yahoo! Groups Links > **************************************************************
> Scanned by VisNetic MailScan for SMTP Servers.
> Visit http://www.deerfield.com/products/visnetic_mailscan.
> ************************************************************** >





Hey guys, another question here. I've got a program which originally
worked fine. I then added some lines of code to it, which also work
fine by themselves. But after I added these new lines of code, the
assembler started giving the error Branch out of Range.
I then tried logically to see why the BRA function would not work.
So what I had was:

LOOP1
LDAA ....
...
...
BRA LOOP1 <-- it would give error here
....

So what I did was this:

LOOP1
LDAA ....
...
...
BRA LOOPTRICK
...
LOOPTRICK BRA LOOP1 (trying to trick it)

I was just trying different things and discovered that the error now
was being displayed at the LOOPTRICK line. I also found out that if
I comment a few random lines of code, the error would no longer
appear. I'm kind of new to assembly, so I'm approaching this from a
C++ stand point. Is this some sort of memory issue? Seems to me that
I am somehow overwriting the code in memory which is why the error
disappears when I comment out a few lines.
Any help would be appreciated!





Hi Nimish

Branch only has an 8 bit range, you will have to change
how you do things. Change the code use more subroutines or
use a jump instead.

Branch is +128 to -127 if I remember correctly.

Welcome to assembly... hehe

Darren Moore > -----Original Message-----
> From: nimish_sudan [mailto:] > Hey guys, another question here. I've got a program which originally
> worked fine. I then added some lines of code to it, which also work
> fine by themselves. But after I added these new lines of code, the
> assembler started giving the error Branch out of Range.
> I then tried logically to see why the BRA function would not work.
> So what I had was:
>
> LOOP1
> LDAA ....
> ...
> ...
> BRA LOOP1 <-- it would give error here
> ....
>
> So what I did was this:
>
> LOOP1
> LDAA ....
> ...
> ...
> BRA LOOPTRICK
> ...
> LOOPTRICK BRA LOOP1 (trying to trick it)
>
> I was just trying different things and discovered that the error now
> was being displayed at the LOOPTRICK line. I also found out that if
> I comment a few random lines of code, the error would no longer
> appear. I'm kind of new to assembly, so I'm approaching this from a
> C++ stand point. Is this some sort of memory issue? Seems to me that
> I am somehow overwriting the code in memory which is why the error
> disappears when I comment out a few lines.
> Any help would be appreciated!




On Sat, 2004-11-06 at 17:36, nimish_sudan wrote:
> But after I added these new lines of code, the assembler started
> giving the error Branch out of Range.

Nothing to do with memory or over-writing code. It means exactly what
it says - it's trying to tell you you are attempting to branch to a
place that is too far away for a signed 8-bit displacement - the
relative branches (including all the conditional ones) use a single byte
as the value.

Thanks Darren, but the branch is -128 to +127, and it's relative to
the *next* instruction, since the signed value is added to the program
counter *as well as* the normal stepping of the program counter. IIRC.

> So what I did was this:
>
> LOOP1
> LDAA ....
> ...
> ...
> BRA LOOPTRICK
> ...
> LOOPTRICK BRA LOOP1 (trying to trick it)

You tricked yourself - you made the *new* branch *even further*. The
"trick", if you wish to do this, is to do it like this:

LOOP1
> LDAA ....
> ...
> ...

> LOOPTRICK BRA LOOP1 (trying to make the jump *nearer*)

> ...
> ...
> BRA LOOPTRICK

This divides the branch into two parts, each smaller than the original,
but you now have to branch *past* "LOOPTRICK".

Now this is actually wasteful - in the case of an unconditional branch
- because you simply code a JMP instead, allowing you to go anywhere in
the code space, but perfectly sensible for a conditional branch.

Quite often however, this is avoided by re-structuring the code. The
situation you describe is a "WHILE ... DO" loop (generally the same as a
DO ... WHILE, depending on how you interpret it). That is, of the
structure:

<Initialisation>
LOOP1:
<Set up a test>
<Do the test, i.e., flags are set>
BRANCH_IF EXIT1
<Body of iteration>
BRANCH LOOP1

EXIT1:
<next part of program>

One suggestion that Darren made, was to ensure the loop is compact, by
making the body of the iteration, a subroutine which is simply *called*
inside the loop. This may come unstuck if you place the subroutine
between the branch and the "EXIT1", because the extra overhead of the
subroutine may now make the conditional branch too far.

On the other hand, if you place the subroutine at the start of the
code (a common convention, with a "JMP START" as the first instruction
of all, to skip over all the subroutines, or simply vector to the actual
start location rather than the start of code memory), then you have to
use JSR rather than BSR and you are limited in building relocatable
modules.

Usually it helps (because it speeds execution by the delay of the
branch for each iteration) to re-organise the code thus:

<Initialisation>
BRANCH ENTRY1

LOOP1:
<Body of iteration>
ENTRY1:
<Set up a test>
<Do the test, i.e., flags are set>
BRANCH_IF_NOT LOOP1
<next part of program>

And sometimes it turns out that the body of the iteration is something
you really wanted to do as part of the initialisation anyway, or you can
allow to do it by a different initialisation, so that you don't need to
branch into it - you actually turn it into a "DO UNTIL" loop that only has
one branch. This is no faster than the "branch-entry" version, but may
sometimes save code space.

So there.
--
Cheers,
Paul B.




Well, that worked. Thanks Paul for the detailed explanation! Much
appreciated. And thanks to everyone else also for their ideas! You
guys are great! :)

--- In , "Paul B. Webster" <paulb@m...> wrote:
> On Sat, 2004-11-06 at 17:36, nimish_sudan wrote:
> > But after I added these new lines of code, the assembler started
> > giving the error Branch out of Range.
>
> Nothing to do with memory or over-writing code. It means
exactly what
> it says - it's trying to tell you you are attempting to branch to a
> place that is too far away for a signed 8-bit displacement - the
> relative branches (including all the conditional ones) use a
single byte
> as the value.
>
> Thanks Darren, but the branch is -128 to +127, and it's relative
to
> the *next* instruction, since the signed value is added to the
program
> counter *as well as* the normal stepping of the program counter.
IIRC.
>
> > So what I did was this:
> >
> > LOOP1
> > LDAA ....
> > ...
> > ...
> > BRA LOOPTRICK
> > ...
> > LOOPTRICK BRA LOOP1 (trying to trick it)
>
> You tricked yourself - you made the *new* branch *even
further*. The
> "trick", if you wish to do this, is to do it like this:
>
> LOOP1
> > LDAA ....
> > ...
> > ...
>
> > LOOPTRICK BRA LOOP1 (trying to make the jump *nearer*)
>
> > ...
> > ...
> > BRA LOOPTRICK
>
> This divides the branch into two parts, each smaller than the
original,
> but you now have to branch *past* "LOOPTRICK".
>
> Now this is actually wasteful - in the case of an unconditional
branch
> - because you simply code a JMP instead, allowing you to go
anywhere in
> the code space, but perfectly sensible for a conditional branch.
>
> Quite often however, this is avoided by re-structuring the
code. The
> situation you describe is a "WHILE ... DO" loop (generally the
same as a
> DO ... WHILE, depending on how you interpret it). That is, of the
> structure:
>
> <Initialisation>
> LOOP1:
> <Set up a test>
> <Do the test, i.e., flags are set>
> BRANCH_IF EXIT1
> <Body of iteration>
> BRANCH LOOP1
>
> EXIT1:
> <next part of program>
>
> One suggestion that Darren made, was to ensure the loop is
compact, by
> making the body of the iteration, a subroutine which is simply
*called*
> inside the loop. This may come unstuck if you place the subroutine
> between the branch and the "EXIT1", because the extra overhead of
the
> subroutine may now make the conditional branch too far.
>
> On the other hand, if you place the subroutine at the start of
the
> code (a common convention, with a "JMP START" as the first
instruction
> of all, to skip over all the subroutines, or simply vector to the
actual
> start location rather than the start of code memory), then you
have to
> use JSR rather than BSR and you are limited in building relocatable
> modules.
>
> Usually it helps (because it speeds execution by the delay of the
> branch for each iteration) to re-organise the code thus:
>
> <Initialisation>
> BRANCH ENTRY1
>
> LOOP1:
> <Body of iteration>
> ENTRY1:
> <Set up a test>
> <Do the test, i.e., flags are set>
> BRANCH_IF_NOT LOOP1
> <next part of program>
>
> And sometimes it turns out that the body of the iteration is
something
> you really wanted to do as part of the initialisation anyway, or
you can
> allow to do it by a different initialisation, so that you don't
need to
> branch into it - you actually turn it into a "DO UNTIL" loop that
only has
> one branch. This is no faster than the "branch-entry" version,
but may
> sometimes save code space.
>
> So there.
> --
> Cheers,
> Paul B.




Memfault Beyond the Launch