Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

How do I write this simple routing in assembly?

Status
Not open for further replies.

AceOfHearts

New Member
Hi,

Basically, my microcontroller is receiving a serial byte, then i have to compare the byte to see if it is between certain ranges. For example,

If the received byte is between 1-20 do this action
if between 20-40 do that action
40-60
and so forth say upto 200.

This sounds simple to do in theory and I know in C one could just ues 'if' statements to do it....but Im stuck here as I am using assembly and I can seem to find a a way other than comparing the bye 200 times with each number, first with 1, then with 2, 3 4, etc.....that's laborious coding.

Im sure theres another way thats easier? I will appreciate help from any good assembly programmer out there.

Many thanks.
 
Last edited:
Hi,

Basically, my microcontroller is receiving a serial byte, then i have to compare the byte to see if it is between certain ranges. For example,

If the received byte is between 1-20 do this action
if between 20-40 do that action
40-60
and so forth say upto 200.

This sounds simple to do in theory and I know in C one could just ues 'if' statements to do it....but Im stuck here as I am using assembly and I can seem to find a a way other than comparing the bye 200 times with each number, first with 1, then with 2, 3 4, etc.....that's laborious coding.

Im sure theres another way thats easier? I will appreciate help from any good assembly programmer out there.

Many thanks.
hi,
Have you considered just subtracting the 'steps' from the input and testing for Zero/Carry.??
 
Most C compilers produce really horrible assembler code, so perhaps not too good an idea?.
Not near so terrible as the C compiler I learned on in the early 80's. The code it produced was completely un-followable, no matter how determined you were. Gigantic stack frames of spaghetti. :D And the output code was HUGE and ran correspondingly slowly. Soured me on C for many years. I thought they were all like that.

But now I look at code produced by BoostC and it's quite good. Readable and not so bad at all. It's obviously compiler generated, as it isn't as tight as a decent assembly programmer would do, but it's not too bad.
 
I normally add negative numbers as the subtract instructions are a little confusing.
Code:
		addlw	0x100-.21	;add -21
		btfss	STATUS,C
		goto	Was0to20
		addlw	0x100-.20	;add -20
		btfss	STATUS,C
		goto	Was21to40
Note that the first addition is 21 because 0-20 contains 21 numbers.

Mike.
 
For a particular value...

I normally add negative numbers as the subtract instructions are a little confusing.
Code:
        addlw    0x100-.21    ;add -21
        btfss    STATUS,C
        goto    Was0to20
        addlw    0x100-.20    ;add -20
        btfss    STATUS,C
        goto    Was21to40
Note that the first addition is 21 because 0-20 contains 21 numbers.

Mike.

Hola Mike,

What if I have six ranges as:

0 -> 20
21 -> 40
41 -> 60
61 -> 103
104 -> 230
231 -> 255

I can not see clearly what could be the sortest code to use.

Could you please elaborate?

Gracias
 
Hola Mike,

What if I have six ranges as:

0 -> 20
21 -> 40
41 -> 60
61 -> 103
104 -> 230
231 -> 255

Presumably you haven't checked the PICList as I suggested?.

The comparisons section makes it easy to do what you want which is essentially:

If X < 21 then goto something
If X < 41 then goto something else

etc.

So you're looking for the comparison test 'less than' - the last one needs no test, and runs if all the previous ones fail.
 
Hola Mike,

What if I have six ranges as:

0 -> 20
21 -> 40
41 -> 60
61 -> 103
104 -> 230
231 -> 255

I can not see clearly what could be the sortest code to use.

Could you please elaborate?

Gracias
First test for less than 21, then test for less than 41, then test for less than 61, and on and on...

Mike
 
Hola Mike,

What if I have six ranges as:

0 -> 20
21 -> 40
41 -> 60
61 -> 103
104 -> 230
231 -> 255

I can not see clearly what could be the sortest code to use.

Could you please elaborate?

Gracias

I thought it was fairly obvious that you just repeat the code for as many comparisons as you require.:confused:

Mike.
 
I meant to say that you should reference Mike's (Pommie's) fine example.

If it helps, here's an example from a Ham radio device I developed which compares a 16 bit value to an array of 16 bit values in eeprom;

Code:
;
;  Memory 00 contains the target radio CI-V address in byte
;  number 0 (a value of 00 = "any radio")
;
;  Memory 01 through 15 contain CI-V "Frequency-To-BCD" data
;  MegaHertz, KiloHertz (x10), and a BCD band data byte
;
;  When a frequency record is received from the target radio
;  over the CI-V bus its 16-bit frequency (MHz and KHz x10)
;  is compared to the 16-bit frequency value in our memories
;
;
        org     h'2100'         ; 3-byte memories in eeprom

        de      0x00,0x00,0x00  ; target radio CI-V address
        de      0x03,0x40,0x01  ; 160m 00.000-03.399 (0001)
        de      0x05,0x00,0x02  ;  80m 03.400-04.999 (0010)
        de      0x06,0x90,0x02  ;  60m 05.000-06.899 (0010)
        de      0x10,0x00,0x03  ;  40m 06.900-09.999 (0011)
        de      0x13,0x90,0x04  ;  30m 10.000-13.899 (0100)
        de      0x17,0x97,0x05  ;  20m 13.900-17.969 (0101)
        de      0x20,0x90,0x06  ;  17m 17.970-20.899 (0110)
        de      0x24,0x79,0x07  ;  15m 29.900-24.789 (0111)
        de      0x27,0x90,0x08  ;  12m 24.790-27.899 (1000)
        de      0x49,0x90,0x09  ;  10m 27.900-49.899 (1001)
        de      0x60,0x10,0x0A  ;   6m 49.900-60.099 (1010)
        de      0x00,0x00,0x0B  ;
        de      0x00,0x00,0x0C  ;
        de      0x00,0x00,0x0D  ;
        de      0x00,0x00,0x0E  ;
EOMEM   equ     $-2100h
Code:
;
;  match 16-bit CI-V frequency (CIVMHZ and CIVKHZ) to a frequency
;  range in the data/eeprom "memories".  we have a range match
;  when the CI-V frequency is less than the "memory" frequency.
;
EVAL    movlw   h'03'           ; skip memory 00                  |B0
        movwf   ESR             ; index eeprom memory 01          |B0
EVTST   call    RD_EE           ; get MEMMHZ value                |B0
        incf    ESR,f           ;                                 |B0
        subwf   CIV_MHZ,W       ; subtract CIVMHZ value           |B0
        bnc     BANDTST         ; branch if CIVMHZ < MEMMHZ       |B0
        bnz     EVNXT           ; branch if CIVMHZ > MEMMHZ       |B0
        call    RD_EE           ; CIVMHZ = MEMMHZ, get MEMKHZ     |B0
        subwf   CIV_KHZ,W       ; subtract CIVKHZ value           |B0
        bnc     BANDTST         ; branch if CIVKHZ < MEMKHZ       |B0
EVNXT   incf    ESR,f           ; next memory address             |B0
        incf    ESR,f           ;                                 |B0
        movf    ESR,W           ;                                 |B0
        xorlw   EOMEM           ; last memory?                    |B0
        bnz     EVTST           ; no, evaluate another, else      |B0
        goto    NewRec          ; start over                      |B0
 
Hi guys,

thanks for the replies.

I have found a way (but almost there)

firstly, im using 8051. The accumulator A contains the value I want to compare.

I use register R0 to compare A. I increment R0 by 1 and then check again with A. R0 increments by 1 after each comparison up to 20 (or whatever the range is). Therefore after each increment, R0 is also compared (woth the value 20) to see if it has reached 20.

Here is the code which doesnt work for a particular reason:

Note, R0 is set to 0 at first.

Code:
CHECK_AGAIN:   CJNE A, R0, PASS     ;check if A is the same as R0
                                                              ;if not jump to PASS
              ACALL T1      ;do this action T1, whatever it is if A = R0.

PASS:      CJNE R0, #20, OK      ;check if R0 has reached 20 if not jump to OK
              SJMP NEXT_RANGE     ;jump to the nxt routine to check next range

OK:         INC R0      ;If R0 is still not 20, increment by 1
              SJMP CHECK_AGAIN       ;compare A with the new R0 value

Logically the above seems fine. But the error in the code is this bit:

Code:
CJNE A, R0, PASS

I think its because I cant compare with the register R0. Either ive got the wrong syntax, or it doesnt allow checking with a register.

Note the following works where Im comparing directly wit decimal 20:

Code:
CJNE R0, #20, OK

Any help to get over the small problem in my code is appreciated as this is the only think holding me back now. :)

regards.
 
So many intelligent microcontroller programmers here and no one seems to know how to compare two registers in a microcontroller...anyway, Im gonna get in touch with my supervisor and see if he can help. I will let you guys know if I find anything. :)

peace.
 
So many intelligent microcontroller programmers here and no one seems to know how to compare two registers in a microcontroller...anyway, Im gonna get in touch with my supervisor and see if he can help. I will let you guys know if I find anything. :)

We gave you loads of help, then you decided to tell us you were using an antique micro-controller :D - only the people here from India etc. tend to use such old devices.

You could easily find your answers using google though.
 
Last edited:
The process of subtracting a number and then testing the carry flag is pretty much universal for this requirement. Changing the code above to use SUBB A,#data and JC address should be fairly straight forward.

Mike.
 
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top