Implementing Switch statements for the 8051

Hello Everyone, I am basically implementing the equivelent to a switch statement in C for my 8051 in assembly. There are multiple ways to implement a switch statement in assembly, however, I keep cornering myself into a statement like the following:

MOV A,CASE_LOCATION CJNE A,#CASE1_CONST,TRY_CASE2 LJMP CASE1

TRY_CASE2: CJNE A,#CASE2_CONST,TRY_CASE3 LJMP CASE2

and so on. The readability of this statement is bad, so I have devised a case statement of this nature

MOV A,CASE_LOCATION MOV R0,A ; Multiply A by 3 because LJMP is 3 bytes long RL A ADD A,R0 MOV DPTR,#CASE_TABLE JMP @A+DPTR

CASE_TABLE: LJMP CASE1 LJMP CASE2 LJMP CASE3

I am an not 100% sure this is correct, however, this thread is not to belabor the correctness of this switch statement syntax, but to discover the "best" way to implement a switch statement in 8051. I know finding the "best" switch statement is subjective but what are some ways people are doing implementing switch statements in 8051 assembly?

Thanks, Lloyd Rochester

formatting link

Reply to
nfirtaps
Loading thread data ...

On 2 Jan 2007 15:26:40 -0800, "nfirtaps" wrote in comp.arch.embedded:

What you show above only works if the possible switch values are contiguous, with no gaps. This may not be entirely correct, because I am doing it from memory at home, and I've mostly avoided 8051 assembly language for 10 years or so, but something like this:

switch_table: db num_cases db first_case dw first_address db second_case dw second_address

; and so on..l

db last_case dw last_address dw default_address

Then I have a subroutine, called with dp pointing to switch_table, and the comparison value in another register, and it goes something like this in pseudo code, because I don't remember 8051 assembly mnemonics very well:

read first byte (case count) from code memory via dp into a move case count to another register increment dp (point to first case value)

loop: read byte from code memory into a via dp increment dp compare a with compare value register

go_go: if equal: read code memory @dp into a push a increment dp read code memory @dp into a push a return else: (compare not equal) increment dp increment dp decrement case count if case count not 0: jump to loop else: (case count is 0) jump to go_go

This was a modification of a routine I originally developed for the Z80 about a quarter century ago. There can be any number of cases, and a default. The cases don't have to be consecutive values, and don't have to be in any particular order, allowing you to put the most commonly used ones earlier in the table. It overcomes the inability of the 8051 to (easily) execute code out of RAM by pushing the address to jump to onto the stack, so a return instruction actually performs the jump.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
Reply to
Jack Klein

Using the SesAsm51 assembler you may do it this way:

MOV A, CASE_LOC CJE A, #CASE1_CNST, CASE1 CJE A, #CASE2_CNST, CASE2 CJE A, #CASE3_CNST, CASE3 ... JMP DEFAULT

Jorgen

Reply to
Schjaer

... snip code ...

On the 8080/z80 I used to do roughly the following:

; call ath entry in table hl. ; a,f,h,l (disturbed)

execix: add a; double, word address add l mov l,a mvi a,0; don't disturb carry adc h mov h,a pchl; can be push h | ret. much slower.

main code fragment, a holds index needed: lxi h,tbl call execix ....

tbl: dw case0 dw case1 ... maxtbl equ ($ - tbl) / 2

--
Chuck F (cbfalconer at maineline dot net)
   Available for consulting/temporary embedded and systems.
Reply to
CBFalconer

[...] you mentioned the "sequence of tests", and the "jump table" approach. Some of the more important ones you didn't mention are the decision tree and the hash-mapped jump table.

There's no such thing. As with most, if not all, truly interesting questions the answer is: "It depends." Here it depends on the exact set of cases you want to switch() among. Short, tight sequences demand different strategies than a set of 200 numbers more-or-less randomly spread across the range of an unsigned 16-bit integers.

In other words the only answer you should remember is that no single answer is correct for this question. You have to know a selection of different answers to apply in different situations. It's called a "tool chest" because there's more than one tool in it.

Reply to
Hans-Bernhard Bröker

This is pretty much the standard jump table method of doing a switch table. If you look at the output of most C compilers for the 8051 you will see they produce pretty much the same code as this for a switch statement.

ian

Reply to
Ian Bell

; carry for bad call

execix: cmp m rc; out of range. inx h

jc errorhandler; optional

; Maximum 128 entries. 0 through 127. tbl: db maxtbl

Minor correction to 8080 code to detect argument out of range. We could also detect excessive maxtbl value at assembly time with a pseudo op here. The code could nest cases.

--
Chuck F (cbfalconer at maineline dot net)
   Available for consulting/temporary embedded and systems.
Reply to
CBFalconer

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.