How to assemble the BREQ - Branch if equal - instruction

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

Hi, I'm trying to assemble the BREQ - Branch if equal - instruction

and I can not understand the logic very well.

 

The Microchip Studio shows a strange behavior, let me first attach

the AVR instruction description and syntax (taken from the Atmel

AVR instruction set manual).

 

AVR instruction description and syntax (taken from the Atmel AVR instruction set manual)

 

According to the description, the instruction takes an operand that

can be negative or positive. However, the assembler says that the

"Relative branch is out of reach" when the operand is negative,

as shown below:

 

BREQ -1 displays a "Relative branch out of reach" error in Microchip Studio

 

Furthermore, positive offsets can go beyond this limit:

 

BREQ 66 is valid, but the program only has 5 instructions and no includes

 

The program only has 5 instructions and it doesn't include any file.

Why is BREQ 66 valid?

All offsets between 0 and 66 are valid. If another NOP instruction

was added before BREQ, then the offset 67 would be valid.

 

This is the generated .hex file:

The generated hex file bytes: 0000 0000 F9F1 0000 0000

 

Cheers.

This topic has a solution.
Last Edited: Mon. Jan 3, 2022 - 06:46 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Normally you would use a label rather than a number and of course before that instruction you must have done some comparison to set the flags.

John Samperi

Ampertronics Pty. Ltd.

https://www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

You are making it hard for no reason.

 

BREQ just branches if the result was zero (due to any math operation, that affects the zero bit)

 

BREQ goes to where you specify, if it is within the branch range. 

 

ex:

cmp dog, cat    ...forms a subtraction , without storing a final result 

breq alarm      ...if register dog= register cat will go to alarm (if within the allowed range) 

 

Use labels, not numbers...if you use a number, you have to know the format of how the assembler expects a number to be provided   it might be PC-27 or something like that 

Numbers will lead to  major mistake headaches, when you miscount & wonder why the program is working strangely.

 

 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Mon. Jan 3, 2022 - 03:41 AM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm not making it hard for no reason, I'm writing an assembler...

If I generate the wrong bytes, then the program won't work.

 

I have +/- figured out how to assemble this instruction. I'm

going to write some examples for future reference and self-doc.

Note: I'm using NOPs to move the BREQ instruction up and

down. I could be using any other instruction (CMP for example).

 

The output using a label:

A file with a single label and a single BREQ instruction after it

The generated bytes -> F9F3

 

Reversing F9F3, because it is in little-endian, it becomes F3F9

F3F9 is 1111 0011 1111 1001 in binary.

 

The BREQ instruction opcode is defined as 1111 00kk kkkk k001:

BREQ instruction description taken from the AVR instruction set manual

That means the value of k is 1111111 in binary. This binary

number  represents  7F  in  hex  and 127  in  decimal.  The

instruction description says that k is represented in the two's

complement form.

 

To get a number's two's complement, all bits logical values

must be reversed and then added 1. Let's reverse the process:

 

(~address) + 1 = k

(~address) + 1 = 0111 1111

~address = 0111 1111 - 1

~address = 111 1110

address = 000 0001

 

In this example the output is positive 1. Why isn't it -1 (111111)?

Another possible result would be 1000 0001, which would be 129

in decimal and would be wrong. Let's move to the next one:

 

start label + 3 NOPs + BREQ to start

Output bytes -> 0000 0000 0000 E1F3

 

Applying the same logic:

E1F3 is in little-endian, reversing the bytes it becomes F3E1.

The binary value of F3E1 is 1111 0011 1110 0001. The value

of k is 1111100 in binary (or 124 in decimal).

 

(~address) + 1 = k

(~address) + 1 = 111 1100

~address = 111 1100 - 1

~address = 111 1011

address = 000 0100 (4 in decimal)

 

Or the address can be 1000 0100, considering it an 8-bit

number. 1000 0100 in decimal is 132, that means the first

value is probably the correct one. It's confusing that the

value is 4 instead of -4...

 

The last example - jumping forward:

 

NOP, BREQ end, NOP, end: NOP

Last generated bytes -> 0000 09F0 0000 0000

 

Repeating the process again:

09F0 becomes F009 = 1111 0000 0000 1001 in binary.

The value of k is 0000001 in binary.

 

(~address) + 1 = k

(~address) + 1 = 0000001

~address = 000 0001 - 1

~address = 000 0000

address = 111 1111, which is -1

 

First I thought k was an 8-bit number, but it isn't!

And the sign bit shouldn't be flipped apparently.

 

A program with a single BREQ 64 instruction compiles.

Or any program with a single BREQ k instruction where

k >= 0 && k <= 64. The reason may be because in the

Microchip Assembler must be in the two's complement

form. This also explains why NOP NOP BREQ -1 NOP NOP

doesn't compile.

 

(~address) + 1 = k

(~address) + 1 = -1

~address = -2 = 000 0010

address = 111 1101 = 125 in decimal (out of range)

 

The problem is solved by now, thanks for the patience 😂.

Last Edited: Mon. Jan 3, 2022 - 07:46 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That means the value of k is 1111111 in binary. This binary

number  represents  7F  in  hex  and 127  in  decimal.  The

instruction description says that k is represented in the two's

complement form.

0x7F *is* -1, for a 7-bit 2s complement number.

You take 1, complement the bits to get 0b11111111110, and add 1, giving 0b11111111111...

 

In this example the output is positive 1. Why isn't it -1 (111111)?

Because you took -1 to start with, and then did the twos complement thing, giving (- (-1)) = 1.

It doesn't really matter how many bits you do the math with; you just truncate to the desired size when you're done (an advantage of twos complement!)

 

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

Go on.  If you are writing an Assembler you must understand how to to write simple ASM programs.

 

PC:    breq  label

 

Where PC represents the current Program Counter.   You evaluate expr = (label - PC)

expr will be positive for a forward jump and negative for a backward jump.

 

The instruction manual explains the limits for expr.

 

Different CPUs have different limits e.g. number of bits.

Different rules for the initial expression evaluation e.g. some may subtract PC and some may use (PC+1)

 

Life is more complicated when you assemble BREQ expression where expression is an absolute value rather than an address label.

And even more complex when the expression contains unknown external components from separate compilation units.

 

David.

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

I already mentioned -1 is probably not the proper format.

You have to use the format required by the assembler

It is not the AVR instructions per se, it is what the assembler requires you to  state

 

for example, it might require all jumps will be entered using only the following format:

 

gojump  **<name> *$$PX      ex:  gojump **alert *$$PX  would then be a valid entry into the assembler, to create some avr instruction(s)

 

One format known to work is simply to add the needed label, such as:

 

BREQ my_alert

 

Just use that & you will have no issue!

 

Have you thoroughly studied your assembler's guide (not the AVR instructions)

That will give you tips if you are writing your own assembler (why would you do so?)

 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Mon. Jan 3, 2022 - 07:44 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@westfw Got it, thanks 😄!

@david.prentice Thank you,

I've already implemented labels yesterday... The problem

was that the BREQ instruction operand must be in two's

complement form... First I thought k was an offset between

-64 and 63, that's why the unit tests weren't passing 🙁.

 

@avrcandies Thanks! I'm only writing it for fun and to

learn more...

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

First I thought k was an offset between -64 and 63

"k", in the INSTRUCTION, is an offset between -64 and 63.

In the standard assembler, the operand for the BRanch opcodes is an expression representing a program location.  Usually this is a label, an expression involving a label, or the special value PC, which has the value of the PC at the current instruction point (or perhaps the next instruction.)

loop: breq target
      brcs target+2
      rjmp PC-1  ; one instruction infinite loop.
target:
      brmi loop
      clr r1     ; target+1
      clr r2     ; target+1
      

The Gnu Assembler uses "." instead of "PC", but is otherwise similar.

 

It looks to me like the relevant manuals do a really poor job of explaining the difference! (but similar behavior is extremely common in assemblers for ... pretty much every CPU, ever.)

 

 

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

If you know ASM from other micros, I will warn you about the AVR's handling of Z on instructions like SBC (where carry is involved) here Z depends of the state of Z before the instruction.

,this make multi byte compare easy but as a beginner it's a pain.

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

I'm writing an assembler...

WHY???? 25 years late. wink

John Samperi

Ampertronics Pty. Ltd.

https://www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

I'm writing an assembler...

The AVR needs a good linking assembler (yes, there is likely already one out there)...so perhaps that can be one of your goals.

After that, you can write a desperately needed AVR BASIC update (with all the newest peripherals) in assembler.

Give $$BillG$$ a run for the gold!

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

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

avrcandies wrote:
yes, there is likely already one out there
so that would be avr-as then ;-) 

 

When open source solutions like avra and avr-as already exist I do wonder how a new assembler will deliver that "must-have" USP?