# Relative addressing mode problem with HC05

#### JohnnyD

Joined Aug 29, 2006
79
Hi,

I'm having a problem with a Branch instruction in a program i'm trying to write for a Freescale HC05 micro.

Basically, in the HC05, when a branch instruction is executed, an 8-bit signed integer value is calculated and used to adjust the program counter (PC) forward or backwards so it continues execution at the correct location.

As an example i've just written a simple bit of code which loops back to the label 'HERE' until the value of PORTA = zero:
Rich (BB code):
HERE     LDA     PORTA
BNE     HERE
so the relative offset is calculated by how much the PC needs to be adjusted by in order to continue at 'HERE'. So the offset in this case will be negative.

My problem is that I have more than 127 bytes of code between 'HERE' and the branch instruction which is more than can be represented by an 8-bit signed integer which results in a compiler error.

What can I do about this? I'm surprised at this limitation, and I wonder why Freescale didn't use a 16-bit signed integer value for relative addressing offsets instead.

#### Papabravo

Joined Feb 24, 2006
15,700
The solution is
Rich (BB code):
HERE:
LDA   PORTA
.
.
.
BEQ  THERE
JMP   HERE
THERE:
I don't know why you should be surprised, most processors have a limited relative branch range. It is an 8-bit ALU, why should every relative branch have to be three bytes long to accomodate a 16 bit offset. One other curious thing is those other instructions: won't they change the value of the accumulator btween the reading of PORTA and the branch - just wondering.

#### JohnnyD

Joined Aug 29, 2006
79
Thanks for the answer, much appreciated!

I was only surprised because there are other modes such as indexed addressing which support the use of 16-bit addresses so I assumed that branching would support it as well. I guess I'm used to high-level languages where you can jump to anywhere you want in the program. This is the first program I've ever written in assembly language see.

BTW, the code I posted up was to illustrate my point, the actual code is completely different from that. Actually I might as well post up the whole code because I'm sure it could be simplified a lot using indexed addressing lookup-type instructions. I just don't know how lol.

The program reads a set of switches on portB which are arranged so I can use them to represent a binary number. The program then takes that number and finds the number of hundreds, tens and units in order to display them on a 3-digit 7-segment LED display. I haven't gotten round to writing the code to display the values on the LEDs yet. I have it all worked out though, that's not the bit I need help with. The only way I could think to work out the number of hundreds, tens and units was this:
Rich (BB code):
****************************************************************************
* LEDOUT SUBROUTINE                                                        *
*                                                                          *
* USES VALUE OF X TO UPDATE A 3-DIGIT 7-SEGMENT DISPLAY.                   *
* THE DISPLAY USES A BCD VALUE ON BITS 0-3 AND IS MULTIPLEXED USING BITS   *
* 4 AND 5 TO TURN ON ONE DIGIT AT A TIME.                                  *
****************************************************************************
LEDOUT  TXA                     ;TRANSFER CONTENTS OF X INTO A
CMP     #200            ;IS A >= 200?
BHS     HUND2
CMP     #100            ;IS A >= 100?
BHS     HUND1

CLR     HUNDS           ;SET VALUE OF HUNDREDS TO 0
BRA     TENUNIT

HUND2   LDX     #2
STX     HUNDS           ;SET VALUE OF HUNDREDS TO 2
SUB     #200            ;SUBTRACT 200 FROM A
BRA     TENUNIT

HUND1   LDX     #1
STX     HUNDS           ;SET VALUE OF HUNDREDS TO 1
SUB     #100
BRA     TENUNIT

LDX     #2              ;START COUNT AT 2. WHEN COUNT=2, DIGIT IS TENS
STX     COUNT           ;WHEN COUNT=1, DIGIT IS UNITS

TENUNIT CMP     #90             ;IS A >= 90?
BHS     DIGIT9
CMP     #80
BHS     DIGIT8
CMP     #70
BHS     DIGIT7
CMP     #60
BHS     DIGIT6
CMP     #50
BHS     DIGIT5
CMP     #40
BHS     DIGIT4
CMP     #30
BHS     DIGIT3
CMP     #20
BHS     DIGIT2
CMP     #10
BHS     DIGIT1

CLR     DIGIT
BRA     XTENUNI

DIGIT9  LDX     #9
STX     DIGIT
SUB     #90
BRA     XTENUNI
DIGIT8  LDX     #8
STX     DIGIT
SUB     #80
BRA     XTENUNI
DIGIT7  LDX     #7
STX     DIGIT
SUB     #70
BRA     XTENUNI
DIGIT6  LDX     #6
STX     DIGIT
SUB     #60
BRA     XTENUNI
DIGIT5  LDX     #5
STX     DIGIT
SUB     #50
BRA     XTENUNI
DIGIT4  LDX     #4
STX     DIGIT
SUB     #40
BRA     XTENUNI
DIGIT3  LDX     #3
STX     DIGIT
SUB     #30
BRA     XTENUNI
DIGIT2  LDX     #2
STX     DIGIT
SUB     #20
BRA     XTENUNI
DIGIT1  LDX     #1
STX     DIGIT
SUB     #10
BRA     XTENUNI

XTENUNI LDX     #2
CPX     COUNT
BEQ     TIMES10
LDX     DIGIT
STX     UNITS
BRA     XLOOP

TIMES10 LDX     #10             ;LOAD X WITH 10 TO BE MULTIPLIED WITH A
MUL                     ;LOWER BYTE OF RESULT WILL BE IN A
LDX     DIGIT
STX     TENS
BRA     XLOOP

XLOOP   DEC     COUNT
BNE     TENUNIT

XLED    RTS
The problem occurs on the second-to-last line where it branches back up to 'TENUNIT'.
I couldn't work out any other way of doing it, because the HC05 doesn't have a division instruction, it can only do addition, subtraction and multiplication.

Sorry, I know it's a lot of code to look at. If you want me to explain it in words instead then let me know.

Thanks a lot.