Have to write some AVR code and therefore have read the AVR Instruction Set manual and tried the assembler included in AVR studio. I think the used syntax is completely unusable, so I decided to write my own assembler. A very first version can be downloaded from: ftp://137.193.64.130/pub/assembler/adela.zip Maybe there are some AVR experts who can give some suggestions for an improvement or are even willing to do some testing. The used syntax: ******************************************************************* * Instruction set * ******************************************************************* add.b ri,rj ; i,j=0..31 ADD addc.b ri,rj ; i,j=0..31 ADC addq.w #imm6u,ri|rj ; j=24,26,28,30 i=k+1 ADIW and.b #imm8,rj ; j=16..31 ANDI and.b ri,rj ; i,j=0..31 AND asr.b #1,rj ; j=0..31 ASR bcc.b label ; C=0 BRCC bcs.b label ; C=1 BRCS beq.b label ; Z=1 BREQ bge.b label ; S=(N eor V) = 0 BRGE bhcc.b label ; H=0 BRHC bhcs.b label ; H=1 BRHS bhs.b label ; C=0 BRSH bic.b label ; I=0 BRID bis.b label ; I=1 BRIE blo.b label ; C=1 BRLO blt.b label ; S=(N eor V) = 1 BRLT bmi.b label ; N=1 BRMI bne.b label ; Z=0 BRNE bpl.b label ; N=0 BRPL btc.b label ; T=0 BRTC bts.b label ; T=1 BRTS bvc.b label ; V=0 BRVC bvs.b label ; V=1 BRVS br.w label RJMP bsr.w label RCALL cmp.b #imm8,rj ; j=16..31 CPI cmp.b ri,rj ; i,j=0..31 CP cmpc.b ri,rj ; i,j=0..31 CPC dec.b rj ; j=0..31 DEC eor.b ri,rj ; i,j=0..31 EOR fmuls.b ri,rj,r1|r0 ; i,j=16..23 FMULS fmulsu.b ri,rj,r1|r0 ; i,j=16..23 FMULSU fmulu.b ri,rj,r1|r0 ; i,j=16..23 FMUL halt BREAK inc.b rj ; j=0..31 INC jmp.l (*|r31|r30) EIJMP jmp.l label JMP jmp.w (r31|r30) IJMP jsr.l (*|r31|r30) EICALL jsr.l label CALL jsr.w (r31|r30) ICALL lsr.b #1,rj ; j=0..31 LSR move.b #imm8,rj ; j=16..31 LDI move.b ri,rj ; i,j=0..31 MOV move.b adr,rj ; j=0..31 LDS move.b ri,adr ; i=0..31 STS move.b (r27|r26),rj ; j=0..31 LD move.b imm6(r29|r28),rj ; j=0..31 LDD move.b imm6(r31|r30),rj ; j=0..31 LDD move.b ri, (r27|r26) ; i=0..31 ST move.b ri,imm6(r29|r28) ; i=0..31 STD move.b ri,imm6(r31|r30) ; i=0..31 STD move.b -(r27|r26),rj ; j=0..31 LD move.b -(r29|r28),rj ; j=0..31 LD move.b -(r31|r30),rj ; j=0..31 LD move.b ri,-(r27|r26) ; i=0..31 ST move.b ri,-(r29|r28) ; i=0..31 ST move.b ri,-(r31|r30) ; i=0..31 ST move.b (r27|r26)+,rj ; j=0..31 LD move.b (r29|r28)+,rj ; j=0..31 LD move.b (r31|r30)+,rj ; j=0..31 LD move.b ri,(r27|r26)+ ; i=0..31 ST move.b ri,(r29|r28)+ ; i=0..31 ST move.b ri,(r31|r30)+ ; i=0..31 ST move.b +(sp),rj ; j=0..31 POP move.b rj,(sp)- ; j=0..31 PUSH move.b ?adr6,rj ; adr6=0..63 j=0..31 IN move.b ri,?adr6 ; adr6=0..63 i=0..31 OUT move.bit rj[imm3],sr[6] ; j=0..31 BST move.bit sr[6],rj[imm3] ; j=0..31 BLD move.bit #0,sr[imm3] ; ITHSVNZC BCLR move.bit #1,sr[imm3] ; ITHSVNZC BSET move.bit #0,?adr5[imm3] ; adr5=0..31 CBI move.bit #1,?adr5[imm3] ; adr5=0..31 SBI move.w ri|rj,rk|rm ; j,m=0,2,..,30 i=j+1 k=m+1 MOVW movePM.b (r31|r30),r0 LPM movePM.b (r31|r30),rj ; j=0..31 LPM movePM.b (r31|r30)+,rj ; j=0..31 LPM movePM.b (*|r31|r30),r0 ELPM movePM.b (*|r31|r30),rj ; j=0..31 ELPM movePM.b (*|r31|r30)+,rj ; j=0..31 ELPM muls.b ri,rj,r1|r0 ; i,j=16..31 MULS mulsu.b ri,rj,r1|r0 ; i,j=16..23 MULSU mulu.b ri,rj,r1|r0 ; i,j=0..31 MUL neg.b rj ; j=0..31 NEG nop NOP not.b rj ; j=0..31 COM or.b #imm8,rj ; j=16..31 ORI or.b ri,rj ; i,j=0..31 OR prog SPM rocr.b #1,rj ; j=0..31 ROR rol.b #4,rj ; j=0..31 SWAP ror.b #4,rj ; j=0..31 SWAP rte RETI rts RET skipeq.b ri,rj ; i,j=0..31 CPSE skipeq.bit #0,?adr5[imm3] ; adr5=0..31 SBIC skipeq.bit #0,rj[imm3] ; j=0..31 SBRC skipeq.bit #1,?adr5[imm3] ; adr5=0..31 SBIS skipeq.bit #1,rj[imm3] ; j=0..31 SBRS sleep SLEEP sub.b #imm8,rj ; j=16..31 SUBI sub.b ri,rj ; i,j=0..31 SUB subc.b #imm8,rj ; j=16..31 SBCI subc.b ri,rj ; i,j=0..31 SBC subq.w #imm6u,ri|rj ; j=24,26,28,30 i=k+1 SBIW wdog_reset WDR BRBC -> branch Befehle CBR -> and.b CLR -> eor.b CLC,CLH,CLI,CLN,CLS,CLT,CLV,CLZ -> move.bit LSL -> add.b ROL -> addc.b SBR -> or.b SEC,SEH,SEI,SEN,SES,SET,SEV,SEZ -> move.bit SER -> or.b TST -> and.b ******************************************************************* * Opcode list * ******************************************************************* 0000 0000 0000 0000 nop 0000 0001 jjjj iiii move.w ri|rj,rk|rm ; j,m=0,2,..,30 i=j+1 k=m+1 0000 0010 jjjj iiii muls.b ri,rj,r1|r0 ; i,j=16..31 0000 0011 0jjj 0iii mulsu.b ri,rj,r1|r0 ; i,j=16..23 0000 0011 0jjj 1iii fmulu.b ri,rj,r1|r0 ; i,j=16..23 0000 0011 1jjj 0iii fmuls.b ri,rj,r1|r0 ; i,j=16..23 0000 0011 1jjj 1iii fmulsu.b ri,rj,r1|r0 ; i,j=16..23 0000 01ij jjjj iiii cmpc.b ri,rj ; i,j=0..31 0000 10ij jjjj iiii subc.b ri,rj ; i,j=0..31 0000 11ij jjjj iiii add.b ri,rj ; i,j=0..31 0001 00ij jjjj iiii skipeq.b ri,rj ; i,j=0..31 0001 01ij jjjj iiii cmp.b ri,rj ; i,j=0..31 0001 10ji jjjj iiii sub.b ri,rj ; i,j=0..31 0001 11ij jjjj iiii addc.b ri,rj ; i,j=0..31 0010 00ij jjjj iiii and.b ri,rj ; i,j=0..31 0010 01ij jjjj iiii eor.b ri,rj ; i,j=0..31 0010 10ji jjjj iiii or.b ri,rj ; i,j=0..31 0010 11ij jjjj iiii move.b ri,rj ; i,j=0..31 0011 #### jjjj #### cmp.b #imm8,rj ; j=16..31 0100 #### jjjj #### subc.b #imm8,rj ; j=16..31 0101 #### jjjj #### sub.b #imm8,rj ; j=16..31 0110 #### jjjj #### or.b #imm8,rj ; j=16..31 0111 #### jjjj #### and.b #imm8,rj ; j=16..31 10#0 ##0j jjjj 0### move.b imm6(r31|r30),rj ; j=0..31 10#0 ##0j jjjj 1### move.b imm6(r29|r28),rj ; j=0..31 10#0 ##1i iiii 0### move.b ri,imm6(r31|r30) ; i=0..31 10#0 ##1i iiii 1### move.b ri,imm6(r29|r28) ; i=0..31 1001 000j jjjj 0000 move.b adr,rj ; j=0..31 #### #### #### #### 1001 000j jjjj 0001 move.b (r31|r30)+,rj ; j=0..31 1001 000j jjjj 0010 move.b -(r31|r30),rj ; j=0..31 1001 000j jjjj 0100 movePM.b (r31|r30),rj ; j=0..31 1001 000j jjjj 0101 movePM.b (r31|r30)+,rj ; j=0..31 1001 000j jjjj 0110 movePM.b (*|r31|r30),rj ; j=0..31 1001 000j jjjj 0111 movePM.b (*|r31|r30)+,rj ; j=0..31 1001 000j jjjj 1001 move.b (r29|r28)+,rj ; j=0..31 1001 000j jjjj 1010 move.b -(r29|r28),rj ; j=0..31 1001 000j jjjj 1100 move.b (r27|r26),rj ; j=0..31 1001 000j jjjj 1101 move.b (r27|r26)+,rj ; j=0..31 1001 000j jjjj 1110 move.b -(r27|r26),rj ; j=0..31 1001 000j jjjj 1111 move.b +(sp),rj ; j=0..31 1001 001i iiii 0000 move.b ri,adr ; i=0..31 #### #### #### #### 1001 001i iiii 0001 move.b ri,(r31|r30)+ ; i=0..31 1001 001i iiii 0010 move.b ri,-(r31|r30) ; i=0..31 1001 001i iiii 1001 move.b ri,(r29|r28)+ ; i=0..31 1001 001i iiii 1100 move.b ri,(r27|r26) ; i=0..31 1001 001i iiii 1101 move.b ri,(r27|r26)+ ; i=0..31 1001 001i iiii 1010 move.b ri,-(r29|r28) ; i=0..31 1001 001i iiii 1110 move.b ri,-(r27|r26) ; i=0..31 1001 001j jjjj 1111 move.b rj,(sp)- ; j=0..31 1001 010j jjjj 0000 not.b rj ; j=0..31 1001 010j jjjj 0001 neg.b rj ; j=0..31 1001 010j jjjj 0010 rol.b #4,rj ; j=0..31 1001 010j jjjj 0010 ror.b #4,rj ; j=0..31 1001 010j jjjj 0011 inc.b rj ; j=0..31 1001 010j jjjj 0101 asr.b #1,rj ; j=0..31 1001 010j jjjj 0110 lsr.b #1,rj ; j=0..31 1001 010j jjjj 0111 rocr.b #1,rj ; j=0..31 1001 0100 0### 1000 move.bit #1,sr[imm3] ; ITHSVNZC 1001 0100 1### 1000 move.bit #0,sr[imm3] ; ITHSVNZC 1001 0101 0000 1000 rts 1001 0101 0001 1000 rte 1001 0101 1000 1000 sleep 1001 0101 1001 1000 halt 1001 0101 1010 1000 wdog_reset 1001 0101 1100 1000 movePM.b (r31|r30),r0 1001 0101 1101 1000 movePM.b (*|r31|r30),r0 1001 0101 1110 1000 prog 1001 0100 0000 1001 jmp.w (r31|r30) 1001 0101 0001 1001 jsr.l (*|r31|r30) 1001 0100 0001 1001 jmp.l (*|r31|r30) 1001 0101 0000 1001 jsr.w (r31|r30) 1001 010j jjjj 1010 dec.b rj ; j=0..31 1001 010# #### 110# jmp.l label #### #### #### #### 1001 010# #### 111# jsr.l label #### #### #### #### 1001 0110 ##jj #### addq.w #imm6u,ri|rj ; j=24,26,28,30 i=k+1 1001 0111 ##jj #### subq.w #imm6u,ri|rj ; j=24,26,28,30 i=k+1 1001 1000 jjjj j### move.bit #0,?adr5[imm3] ; adr5=0..31 1001 1001 jjjj j### skipeq.bit #0,?adr5[imm3] ; adr5=0..31 1001 1010 jjjj j### move.bit #1,?adr5[imm3] ; adr5=0..31 1001 1011 jjjj j### skipeq.bit #1,?adr5[imm3] ; adr5=0..31 1001 11ij jjjj iiii mulu.b ri,rj,r1|r0 ; i,j=0..31 1011 0##j jjjj #### move.b ?adr6,rj ; adr6=0..63 j=0..31 1011 1##i iiii #### move.b ri,?adr6 ; adr6=0..63 i=0..31 1100 #### #### #### br.w label 1101 #### #### #### bsr.w label 1110 #### jjjj #### move.b #imm8,rj ; j=16..31 1111 00## #### #000 bcs.b label ; C=1 1111 00## #### #000 blo.b label ; C=1 1111 00## #### #001 beq.b label ; Z=1 1111 00## #### #010 bmi.b label ; N=1 1111 00## #### #011 bvs.b label ; V=1 1111 00## #### #100 blt.b label ; S=(N eor V) = 1 1111 00## #### #101 bhcs.b label ; H=1 1111 00## #### #110 bts.b label ; T=1 1111 00## #### #111 bis.b label ; I=1 1111 01## #### #000 bcc.b label ; c=0 1111 01## #### #000 bhs.b label ; C=0 1111 01## #### #001 bne.b label ; Z=0 1111 01## #### #010 bpl.b label ; N=0 1111 01## #### #011 bvc.b label ; V=0 1111 01## #### #100 bge.b label ; S=(N eor V) = 0 1111 01## #### #101 bhcc.b label ; H=0 1111 01## #### #110 btc.b label ; T=0 1111 01## #### #111 bic.b label ; I=0 1111 100j jjjj 0### move.bit sr[6],rj[imm3] ; j=0..31 1111 101j jjjj 0### move.bit rj[imm3],sr[6] ; j=0..31 1111 110j jjjj 0### skipeq.bit #0,rj[imm3] ; j=0..31 1111 111j jjjj 0### skipeq.bit #1,rj[imm3] ; j=0..31 ******************************************************************* * example program for STK500 (Mega32) * ******************************************************************* ; connect port B to LED port_b_dir=$17 port_b_dat=$18 move.b #$ff,r16 move.b r16,?port_b_dir eor.b r0,r0 move.b #$7f,r16 move.b #$3f,r17 move.b #$1f,r18 move.b #$0f,r19 loop: move.b r16,?port_b_dat move.b #255,r20 _10: dec.b r20 bne.b _10 move.b r17,?port_b_dat move.b #128,r20 _20: dec.b r20 bne.b _20 move.b r18,?port_b_dat move.b #64,r20 _30: dec.b r20 bne.b _30 move.b r19,?port_b_dat move.b #32,r20 _40: dec.b r20 bne.b _40 dec.b r4 bne.b loop add.b r16,r16 addc.b r0,r16 add.b r17,r17 addc.b r0,r17 add.b r18,r18 addc.b r0,r18 add.b r19,r19 addc.b r0,r19 br.w loop
Atmel AVR assembler
Started by ●July 21, 2005
Reply by ●July 22, 20052005-07-22
"Herbert Kleebauer" <klee@unibwm.de> schreef in bericht news:42DFDF98.DC5D4AC9@unibwm.de...> Have to write some AVR code and therefore have read the > AVR Instruction Set manual and tried the assembler included > in AVR studio. I think the used syntax is completely > unusable, so I decided to write my own assembler. A very > first version can be downloaded from: > > ftp://137.193.64.130/pub/assembler/adela.zip > > Maybe there are some AVR experts who can give some suggestions > for an improvement or are even willing to do some testing.I fail to see what's so unusable about the AVR assembler syntax. Your effort resembles 68000 code. Writing a good assembler takes time, are you writing it from scratch? I think that's a complete wombat; better invest in learning the AVR syntax, which is really not that difficult and not unusual. Also nice for the one that has to maintain your code, long after you've left. Are you going to write an assembler for every uC or uP come across, redefining it's assembly language every time?
Reply by ●July 22, 20052005-07-22
Jeroen wrote:> "Herbert Kleebauer" <klee@unibwm.de> schreef in bericht> I fail to see what's so unusable about the AVR assembler syntax. Your effort > resembles 68000 code. Writing a good assembler takes time, are you writing > it from scratch? I think that's a complete wombat; better invest in learning > the AVR syntax, which is really not that difficult and not unusual.What makes an assembler a "good assembler"? I think a good assembler should allow you to write bug free code in a minimum of time. And to do this you don't need a powerful macro system or a high speed assembler or an integrated development system but you surely need a well designed instruction syntax. And to write a simple assembler (without a macro system and which is neither optimized for speed nor size) isn't a big deal. Yes, you have to spend a few hours to write the assembler, but this will save you much more time when you write and debug your assembler programs.> Also nice for the one that has to maintain your code, long after you've > left. Are you going to write an assembler for every uC or uP come across, > redefining it's assembly language every time?Not every uP I come across, but every uP I have to program in assembler and which uses an awful syntax like the Intel x86 or the Atmel AVR (I liked the PDP11 or 68k syntax).
Reply by ●July 22, 20052005-07-22
> What makes an assembler a "good assembler"? I think a good assembler > should allow you to write bug free code in a minimum of time. AndA good assembler should use the mnemonics and rules specified by the device manufacturer, where there is such a specification. It should assemble, with the minimum possible modification, code intended for other assemblers targeting the same part. An assembler that doesn't follow the device manufacturer's rules is a very low-level HLL, not an assembler.
Reply by ●July 22, 20052005-07-22
Herbert Kleebauer wrote:> Jeroen wrote: >... snip ...> >> Also nice for the one that has to maintain your code, long after >> you've left. Are you going to write an assembler for every uC or >> uP come across, redefining it's assembly language every time? > > Not every uP I come across, but every uP I have to program in > assembler and which uses an awful syntax like the Intel x86 or > the Atmel AVR (I liked the PDP11 or 68k syntax).And then every time you want to use some code from outside, or from the chip manufacturer, you have to laboriously transcribe it into your 'better' mnemnonics and syntax, without error. Similarly for the joker out there in either space or time who has to use your special code. I strongly advise letting the manufacturer set the assembly language. Even small deviations can have evil consequences, as I have found out in the past. -- Chuck F (cbfalconer@yahoo.com) (cbfalconer@worldnet.att.net) Available for consulting/temporary embedded and systems. <http://cbfalconer.home.att.net> USE worldnet address!
Reply by ●July 23, 20052005-07-23
CBFalconer wrote:> Herbert Kleebauer wrote:> >> Also nice for the one that has to maintain your code, long after > >> you've left. Are you going to write an assembler for every uC or > >> uP come across, redefining it's assembly language every time? > > > > Not every uP I come across, but every uP I have to program in > > assembler and which uses an awful syntax like the Intel x86 or > > the Atmel AVR (I liked the PDP11 or 68k syntax). > > And then every time you want to use some code from outside, or from > the chip manufacturer, you have to laboriously transcribe it into > your 'better' mnemnonics and syntax, without error. Similarly for > the joker out there in either space or time who has to use your > special code.That's the nice thing on assembly programming: you can assembly and disassembly it to convert the source to an different assembler. The AVR simulator has no problem to disassemble and simulate the code generated by my assembler. But it seems even Atmel is aware that they use a crazy syntax because any disassembled instruction gets an comment which explains what this instruction does. I prefer a syntax where you directly see what the instruction does without needing a comment.> I strongly advise letting the manufacturer set the assembly > language. Even small deviations can have evil consequences, as I > have found out in the past.When small deviations can have evil consequences, then most probably small deviations can also have positive consequences. Why not try to start an evolution to the better side?
Reply by ●July 23, 20052005-07-23
larwe@larwe.com wrote:> > > What makes an assembler a "good assembler"? I think a good assembler > > should allow you to write bug free code in a minimum of time. And > > A good assembler should use the mnemonics and rules specified by the > device manufacturer, where there is such a specification. It should > assemble, with the minimum possible modification, code intended for > other assemblers targeting the same part.Great logic. Let's use a bad design because we then at least are compatible to the other bad designs! Why not use a superior design so you are better than all this compatible bad designs?> An assembler that doesn't follow the device manufacturer's rules is a > very low-level HLL, not an assembler.I think this is a definition of an assembler which we hadn't here in a.l.a till now (and we had many different definitions). So, if the manufacturer decides to change his rules, then all the existing assemblers becomes a low-level HLL and some low-level HLL's (which already used the new rules of the manufacturer) becomes an assembler. A real consistent definition of an assembler.
Reply by ●July 23, 20052005-07-23
On Fri, 22 Jul 2005 22:38:11 +0200, Herbert Kleebauer <klee@unibwm.de> wrote:>Jeroen wrote: >> "Herbert Kleebauer" <klee@unibwm.de> schreef in bericht > > >> I fail to see what's so unusable about the AVR assembler syntax. Your effort >> resembles 68000 code. Writing a good assembler takes time, are you writing >> it from scratch? I think that's a complete wombat; better invest in learning >> the AVR syntax, which is really not that difficult and not unusual. > >What makes an assembler a "good assembler"? I think a good assembler >should allow you to write bug free code in a minimum of time. And >to do this you don't need a powerful macro system or a high speed >assembler or an integrated development system but you surely need >a well designed instruction syntax. And to write a simple assembler >(without a macro system and which is neither optimized for speed >nor size) isn't a big deal. Yes, you have to spend a few hours to >write the assembler, but this will save you much more time when >you write and debug your assembler programs. > >> Also nice for the one that has to maintain your code, long after you've >> left. Are you going to write an assembler for every uC or uP come across, >> redefining it's assembly language every time? > >Not every uP I come across, but every uP I have to program in >assembler and which uses an awful syntax like the Intel x86 or >the Atmel AVR (I liked the PDP11 or 68k syntax).If you really want to use a different assembler syntax, rather write software that translates your syntax into the manufacturer specified syntax. Keeping all the symbols as symbols and not translating them to numbers. You then can use a standard assembler for the device to generate your executable. Regards Anton Erasmus
Reply by ●July 23, 20052005-07-23
<larwe@larwe.com> wrote: | > What makes an assembler a "good assembler"? I think a good assembler | > should allow you to write bug free code in a minimum of time. And | A good assembler should use the mnemonics and rules specified by the | device manufacturer, where there is such a specification. It should | assemble, with the minimum possible modification, code intended for | other assemblers targeting the same part. | An assembler that doesn't follow the device manufacturer's rules is a | very low-level HLL, not an assembler. I can't agree, CPU/MC-producers actually don't care about sense-making mnemonics. And like Herbert, I also use 'my very own' syntax to at least try to cover all MC/CPU I ever worked on with one cross-compatible language. Of course, x86-coders are not familiar with Herbert's 68000 styled or my Zilog-styled syntax. Therefore I use it only personal and don't try to make it a public need. But Herbert's conversion is pure logical based, even I use hardware ordered register-numbers and have the size-casts in/at the operands. __ wolfgang
Reply by ●July 23, 20052005-07-23
Anton Erasmus wrote:> If you really want to use a different assembler syntax, rather write > software that translates your syntax into the manufacturer specified > syntax. Keeping all the symbols as symbols and not translating them to > numbers. You then can use a standard assembler for the device to > generate your executable.I can't see any advantage in generating an intermediate source file but a big disadvantage: for debugging you need a list file and it doesn't help if you get a list file from the "standard" assembler when you have written the source in a different syntax. But how are AVR programs debugged at all? Are there AVR versions which have support for hardware breakpoints or at least single step interrupts? The only alternative I see at the moment is, to add an assembler directive which automatically inserts a call to a debug routine after each instruction. But this would double the size of the code to debug.