assembly, easy way to check the value of two bytes

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

Hi Guys,

I haven't worked with assembly in a long time.

 

I am trying to determine the value of two bytes in assembly without long tedious compare routines.

Each byte is either 0xFF or 0x00. There are four outcomes from these two bytes:

 

1. both bytes = 0x00

2. both bytes = 0xFF

3. byte0 = 0x00, byte1 = 0xFF

4. byte0 = 0xFF, byte1 = 0x00

 

I have some code I ran in avrstudio but I am lost at how to do this easily in assembly.

I figured out by adding both bytes together, if they are both zero, the result is zero.

If they are both 0xFF, then the carry flag is set.

 

Here is where I am lost. The remaining two scenarios are #3 and #4 above.

I can't  add them together because the result will always be 0xFF.

 

I thought of eor'ing each byte with 0x00, then with 0xFF to find the result.

I can't help thinking there is an easier way to do this.

 

Anyone have any ideas? Please go easy on me.

.nolist
.include "tn2313def.inc"
.list

.def	byte0	= r16
.def	byte1	= r17
.def	temp	= r18
.def	temp1	= r19

;---------------------------------------------------------
.cseg
.org	0
;-------------------------------------------------------
Reset:
	rjmp	Start			;
;-------------------------------------------------------
Start:
	ldi	temp,LOW(RAMEND)	;
	out	SPL, temp     	;
	ldi	temp,HIGH(RAMEND)	;
	out	SPH, temp     	;

;uncomment only one pair below at one time
;to run in avrstudio
;
;	ldi	Byte0,0		;0x00,0x00
;	ldi	Byte1,0

	ldi	Byte0,0xFF	;0xFF,0x00
	ldi	Byte1,0

;	ldi	Byte0,0		;0x00,0xFF
;	ldi	Byte1,0xFF

;	ldi	Byte0,0xFF	;0xFF,0xFF
;	ldi	Byte1,0XFF
;---------------------------------------------------
	add	Byte0,Byte1
	breq	PCS_1		;both 00 if zero flag set
	brcs	PCS_2		;both FF if carry set

	cpi	Byte0,0xFF	;Byte1 is FF, Byte0 is 0
	breq	PCS_3		;

;here is where I am lost
	cpi	Byte1,0xFF
	breq	PCS_4		;Byte1 was 0

stop:
	rjmp	stop
;---------------------------------------------------
PCS_1:			;
;if we get here both bytes are 0
  	nop
	nop
	rjmp	stop

PCS_2:
;if we get here both bytes are 0xFF
  	nop
	nop
	rjmp	stop

PCS_3:
;if we get here byte0 is 0, byte 1 is 0xFF
   	nop
	nop
	rjmp	stop

PCS_4:
;if we get here byte0 is 0xFF and byte1 is 0
	nop
	nop
	rjmp	stop
;---------------------------------------------------
.exit

 

This topic has a solution.
Last Edited: Sun. Jan 29, 2017 - 12:12 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

the code below is working, just thinking there is a more efficient way to do this.

 

Anyone?

 

;
.def	byte0	= r16
.def	byte1	= r17
.def	temp	= r18
.def	temp1	= r19
;---------------------------------------------------------
.cseg
.org	0
;-------------------------------------------------------
Reset:
	rjmp	Start			;
;-------------------------------------------------------
Start:
	ldi	temp,LOW(RAMEND)	;
	out	SPL, temp     	;
	ldi	temp,HIGH(RAMEND)	;
	out	SPH, temp     	;

;uncomment only one pair below at one time
;in avr studio
;
;	ldi	Byte0,0		;0x00,0x00
;	ldi	Byte1,0

	ldi	Byte0,0xFF		;0xFF,0x00
	ldi	Byte1,0

;	ldi	Byte0,0		;0x00,0xFF 
;	ldi	Byte1,0xFF

;	ldi	Byte0,0xFF		;0xFF,0xFF
;	ldi	Byte1,0XFF
;---------------------------------------------------
	mov	temp,byte0	;save byte0
	mov	temp1,byte1	;save byte1

	add	byte0,byte1
	breq	PCS_1		;both 00 if zero flag set
	brcs	PCS_2		;both FF if carry set

	mov	byte0,temp	;restore byte0
	clr	temp1
	eor	byte0,temp1
	breq	PCS_3		;byte0 was 0 

	mov	byte1,temp1	;restore byte1
	clr	temp
	eor	byte1,temp
	breq	PCS_4		;byte1 was 0 

stop:
	rjmp	stop
;---------------------------------------------------
PCS_1:			;
;if we get here both bytes are 0
  	nop
	nop
	rjmp	stop

PCS_2:			
;if we get here both bytes are 0xFF
  	nop
	nop
	rjmp	stop

PCS_3:
;if we get here byte0 is 0, byte 1 is 0xFF
   	nop
	nop
	rjmp	stop

PCS_4:
;if we get here byte0 is 0xFF and byte1 is 0
	nop
	nop
	rjmp	stop
;---------------------------------------------------
.exit

 

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

You haven't told us all the "rules".  ;)  From the code shown, you want to preserve the values of the original regiaters?  How many additional registers can be used?  What is the primary judging criterion?  Size?  Speed?

 

The straightforward way preserves the original values, and uses no additional registers:

 

-- Test one of the values.  Split into the two cases depending on 0 or not.  Repeat at the split.

 

Now, that might be TST/BRxx/RJMP combinations.  Perhaps a bit better:

 

-- Test a bit in one of the values with SBRS/C.  That essentially saves TST instructions.

 

Or, test each value and add an offset to a cleared destination register.  The end value tells the tale.

 

 

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

Yes we need more info but something like this

cpi r16,0x00
brne L1
cpi r17,0x00
brne "both 00"
;code for r16==0 r17==0xff

L1:
cpi r17,0x00
brne ""r16==0xff r17==0
;code both 0xff

But there could be other ways that are better for you, the best part of the code I show is that it don't use extra registers and your source don't change either.

Last Edited: Sat. Jan 28, 2017 - 11:39 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well this is the best way I know how to do this, I can't think of a more efficient way, but there are probably those who can!!

 

.nolist
.include "tn2313def.inc"
.list
;
.def	test0	= r16
.def	test1	= r17
.def	temp	= r18
;---------------------------------------------------------
.cseg
.org	0
;-------------------------------------------------------
Reset:
	rjmp	Start		;
;-------------------------------------------------------
Start:
	ldi	temp,LOW(RAMEND);
	out	SPL, temp     	;

;uncomment only one pair below at one time
;in avr studio
;
	ldi	test0,0		;0x00,0x00
	ldi	test1,0		;

;	ldi	test0,0xFF	;0xFF,0x00
;	ldi	test1,0		;

;	ldi	test0,0		;0x00,0xFF
;	ldi	test1,0xFF	;

;	ldi	test0,0xFF	;0xFF,0xFF
;	ldi	test1,0XFF
;---------------------------------------------------
try:
	tst	test0
	brne	try1
	tst	test1		;test0 = 0xFF

	breq PCS_1		;test0 = 0x00,test1 = 0x00
	rjmp	PCS_3		;test0 = 0, test1 = 0xFF

;we are here because test0 = 0xFF
try1:
 	tst	test1		;check test1
	brne	PCS_2		;both are 0xFF
	rjmp	PCS_4		;test0 = 0xFF, test1 =0x00

stop:

	rjmp	stop
;---------------------------------------------------
PCS_1:			;
;if we get here both bytes are 0
  	nop
	nop
	rjmp	stop

PCS_2:
;if we get here both bytes are 0xFF
  	nop
	nop
	rjmp	stop

PCS_3:
;if we get here test0 is 0, test1 is 0xFF
   	nop
	nop
	rjmp	stop

PCS_4:
;if we get here test0 is 0xFF and test1 is 0
	nop
	nop
	rjmp	stop
;---------------------------------------------------
.exit

 

Last Edited: Sun. Jan 29, 2017 - 12:09 AM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What a wonderful tool avrstudio is. It's FREE. Not much free these days.

 

Thanks guys, that code is good enough for me.

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

newbie123 wrote:
Well this is the best way I know how to do this, I can't think of a more efficient way, but there are probably those who can!!

But you didn't answer the queries on the "rules".

 

theusch wrote:
From the code shown, you want to preserve the values of the original regiaters? How many additional registers can be used? What is the primary judging criterion? Size? Speed?

And I thought of another -- what is the goal?  Is it to identify which case it is?  Or is it to carry out code for each case?

 

 

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

newbie123 wrote:

What a wonderful tool avrstudio is. It's FREE. Not much free these days.

 

Thanks guys, that code is good enough for me.

 

OK, but now I have optimized it anyway.

 

try:
	cp	test0, test1
	brcs	PCS_3
	brmi	PCS_4

	tst	test0
	breq	PCS_1
	rjmp	PCS_2