writing readable assembler code

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

I'm learning AVR since couple of years, and now I have come to that point, that I write codes long enough to be heavily readable with my recent coding style.

As I have learned everything myself about AVR-s and almost everything about analog and digital electronic and microcontrollers, I always feel like reinventing the wheel.

I'm asking you to post some tips to make an assembler code more readable and/or share a pice of code showing your coding/commenting style.
That would help me a lot.

Thanks

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

You have to search for yourself. You read other people's code and copy the styles that impress you. There is far more C code than ASM code in the public domain, but the same applies.

Trying to impose a style on ASM programmers is like walking into a den of wolves. They will all have their own opinions ( and favourite parts of your anatomy ).

You could make a start by looking at Application Note assembly code.

David.

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

If you already have your own C style, work from there. You can basically copy the naming and formatting conventions from your C style and add your own asm extensions (example: byte offsets in asm vs structs in C). It is not that important if others can read your code - *you* have to find your way through it.

I tend to post off-topic replies when I've noticed some interesting detail.
Feel free to stop me.

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

Quote:

make an assembler code more readable

For js: That is an oxymoron, isn't it--"readable assembler". :twisted:

Lee

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

I recommend using lots of documentation. ASM code should read like a pulp novel with the documentation being like paragraphs and the opcode instructions like the dialog.
I suggest using also the Speech-to-Text feature that is hidden in MS Vista and MS Office. Speaking a description of what a function does into a microphone and having the text appear before the code itself is a great way to do documentation. Just paste a block comment or a vertical row of semicolons in front of the text description to retain the code's ability to be assembled.

Try to make the code sections reusable by paying strict attention documenting the input and output data.

All these things make assembler more like C. This is not a bad idea because it greatly helps the programmer make the transition between ASM and C. The great advantage of C is that it allows the programmer to write more usable code in the same amount of time. The big disadvantage is that it is more difficult to troubleshoot and debug if the code doesn't work for some reason.

I believe that the ratio of AVR's ASM and C code will always be the same that it is now. The simpler and cheaper the CPU, the more likely that ASM will be used to program it.

The exception is the Microchip PIC processor. C is generally used (and expensive proprietary C compilers purchased) for the PIC because the PIC assembly language is so convoluted and difficult to work with.

Personally I use assembler for AVR development because I am finally comfortable with it. I find that I have to debug in the individual instruction sequence level using an ICE200 in-circuit-emulator (90S8535-mode posing as a Mega8) often. The extra level of abstraction that C provides would make debugging too difficult to work with for the code that I write. But I'm trying to get to the point where I'm fluent in both languages interchangably.

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

Split the program up in modules, and use .include if you have for example a databank or display drivers.

RES

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

Those comments of RES are very good.

- I tend to tab all my jumps ... like:

sbrc R16, 0
	bra Label1

- All return stuff is written in capital letters.
- instructions for debug only are not tabbed
- I start to use "hungary notation"
- all interrupt routines start with: ISR__
- ";[text]" comments cut the code into small slices
- a lot of ASCII drawing, like:

;====================================================
;			Init
;====================================================
; [general comments]
;==============
; init TMR0
;==============
.
.
.
;==============
; init TMR2
;==============
.
.
.
;====================================================
;		declaration of variable
;====================================================
.def ...
.
.
.
;====================================================
;		declaration of arrays
;====================================================
.
.
.

;	Cube Stack
;   ===========
;								This RingStack contains CL0a ... CL2b
; |4 B wide	  |				It is the interface between the Cube user and 
; |-------------|				ISR__Refresh_Cube. This way the user can push
; |		       | <--- WR_Ptr	his pictures into the stack without thinking
; |-------------|				about timing. The Stack is read periodically
; |	   Data	|				by ISR__RD_CubeS - which hands the read data
; |-------------|				over to ISR__Refresh_Cube. This ISR is called
; |	   Data	|				by a timer. 
; |-------------|
; |	   Data	| <--- RD_Ptr
;===========================================================================
;					   		  Read from Cube Stack
;===========================================================================
ISR__RD_CubeS:
;[PUSH]						;grab the Data from RingBuff and push to CL01a etc.
	PUSH ZL				
	PUSH ZH
	PUSH w
	PUSH u
;[delay the reading]		;SW PS for more dealy (better: use TMR cleverly)  
	lds w, postscaler		;load PostScaler
	inc w					  ;inc scaler
	sts postscaler, w		;save scaler (but keep value in w)
	lds u, postsc_compare ;load the postscaler-compare value to u
	cp w, u					;if equal display new picture
		BRLO no_OV
;[Postscaler Overflow]
	clr w					;reset the counter
	sts postscaler, 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I comment the crap out of my assembler code. Meaning that for just about every line of code I write, I add a comment at the end of the line explaining what I am using the code for. Since comments are free and not assembled I could care less if my source code file is 500meg(exaggerated) as long as it assembles into a .hex that fits into the chip.

js and I are probably the last of the freaks that still use assembler, but I do concede that the same rule applies to 'C' programming that comments are free so use them as much as possible.....saves you a headache later in debugging and if you sell the code, the buyer will know what is going on if they decide to modify it later.

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

theusch wrote:
Quote:

make an assembler code more readable

For js: That is an oxymoron, isn't it--"readable assembler". :twisted:

Lee

It's easy to make assembler code more readable: Convert it to C. :wink:

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

It's not allways true that C code is more readable than asm. With ASM it can be difficult, but there are usually no hidden or conditional difines that can add a lot of complexity to c code. It also gets tricky for exact timings or other tricky parts. With ASM there is a natural limit how bad it can get.

For many tasks using C is a good idea to get more readable code. But you have to use some self imposed rules too, just like in writing ASM code. If things can be done in C use C, if you really need ASM consider mixing C and ASM, allthoug this can add some extra comlexity. Sometimes having the C code can be a first step to write the ASM file.

I personly don't like to have to much comments in the ASM file. To may full lines of comments just make it difficult to find the code. I usually have a seperate text file for the longer discription parts.
Important informations are the subroutines with the information on register use.

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

That extra file is definatly a good idea. I'll use it :)

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

One thing I can contribute is to make labels as descriptive as you can.

Once upon a time one was limited to 4, 6 or 8 chars, so the label were very cryptic. Modern assemblers can use up to 255 chars therefore the label can describe what the routine is meant to do. ie: enable_pwm: disable_pwm: do_pwm_intensity: USART0_INIT: RTC_format_time: etc.

Of course I second the "lots of comment" idea and definetely the multifile projects. Start building up libraries of code that you can use over and over without even thinking about what the code does, like USART, TWI, math and so on.

And finally there is nothing more pityfull than some high and mighty C programmer that cannot debug his C code because he doe not understand assembler. :wink:

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

I agree with all of the above. I tend to comment the heck out of my assembly code (no so much now - mostly C). I recently had to modify some large project I worked on 10+ years ago. Boy, did some of my coding seem really strange. However, the comments made it possible to understand what was being done and allow me to modify the code. I must say that I think I started doing lots of comments sine I ALWAYS had to fix hardware problems in software which required some weird techniques!

Randy

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

I will just add :
Make headers for functions that include what/where input/output is
and what change. I prefere to make a calc for max time this can take as well

Don't use macros before you have made your own style (and even then only if you need speed use a lot of small functions that is well defined).

And like every program don't start writing code before you have defined what you want to do !!!

Jens

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

To "define what I want to do" I often write it in (pseudo) C.

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

"Talk" to yourself in your comments. Also, as you talk to yourself, write comments as if you were describing "why" you are doing this section of code to someone else, not necessary "what" you are doing. Describe the purpose.

Anyone, including yourself, can see what your are doing. But after a while, if you don't describe why, you nor anyone else will be able to tell why it was done without a lot of pain.

Write comments for logical blocks of code (even line can be a logical block), but you don't need, nor should you comment every line.

My commenting style is identical for any language that I write (mostly C, assembly, and VB). Don't fall into a trap thinking that C, or any other language, is self commenting or descriptive enough by itself.

Some "ASCII art" is ok for commenting, but don't get too carried away with it. It can eat up a lot of time trying to get the right characters. It's better for more detailed timing and state diagrams to have a seperate document with multiple pages for timing diagrams, state diagrams, flowcharts, etc. Personally, I use VISO.

A code snippet is attached to show the style that I prefer. This is "C", but I apply it equally to all languages.

    //**************************************************
    // We have been off for greater than 300 seconds.
    // Calculate index into lookup table for log value
    // 32 = (1/0.03125). Value 0.03125 is the incremental
    // value of each index in log table. First, subtract
    // 300 seconds from time. We have already calculated
    // cooling for the first 300 seconds.
    //**************************************************

    time = time - 300;

    //****************************************************
    // We must prevent a table index overflow. This may
    // happen on long time values (although unlikely).
    // Check the result of the following formula. If
    // result is greater than 127, then the actual thermal
    // value is very near zero anyway. Force zero into
    // thermal model values.
    //****************************************************

    temp_long = (time * 32)/CoolingTau;
    if (temp_long > 127)
        {
        VC1 = 0;
        VC2 = 0;
        VC3 = 0;
        return;
        }

    //**********************************************
    // Result was <= 127. This will create an index
    // that will fit into the log table.
    // Typecast to 8 bit value.
    //**********************************************

    temp = (unsigned char)(temp_long);

    //***************************************************
    // We must clamp t_VC3 value to 100% or less.
    // The logtable math may overflow if values
    // much greater than 100% are feed into it.
    // Absolute maximum t_VC3 is 540927.
    // 540927 x 3970 (max logtable) = 0x7FFFF27E (signed)
    //***************************************************

    if (t_VC3 > ThermalTripLevelLong)
        t_VC3 = ThermalTripLevelLong;


    //**************************************************
    // Calculate new thermal model values. Get log value
    // from table and multiply by t_VC3.  VC1,2,3 will
    // all be equal upon exit.
    //**************************************************

    ptr_log = &logtable[0] + temp;
    VC3 = (t_VC3 * (unsigned long)*ptr_log)/4096;   //4096 is logtable scale
    VC2 = VC3;
    VC1 = VC3;
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I find it helpful to document in the comment block at the beginning of the asm subroutine the following in addition to a overall description of the purpose of the routine.

1) the expected inputs, i.e. the values that should be in certain registers and/or global vars

2) the outputs produced, i.e. what values will be in what registers when the routine finishes

3) what registers the routine modifies

If the routine is callable from C, I also add the corresponding C prototype.

Also, I find it preferable to not use specific register references in the code. Rather, I define at the top of the routine names for the registers that will be used. This not only makes the code easier to follow (based on the descriptiveness of the identifiers) but it makes it easier to maintain if a register usage needs to be changed because the change only needs to be done in one place.

Don Kinzer
ZBasic Microcontrollers
http://www.zbasic.net

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

There are two tools I use. One is file and function headers (which MUST be kept up-to-date):

/*
 ******************************************************************
 *
 *    DESCRIPTION:
 *
 *    AUTHOR:
 *
 *    HISTORY:
 *
 ******************************************************************
 */

/***************************************************************************/
/********************************************************** include files **/

/***************************************************************************/
/****************************************************** local definitions **/

/***************************************************************************/
/***************************************************** external functions **/

/***************************************************************************/
/******************************************************* public functions **/

/***************************************************************************/
/***************************************************** internal functions **/

/***************************************************************************/
/********************************************************** external data **/

/***************************************************************************/
/************************************************************ public data **/

/***************************************************************************/
/*********************************************************** private data **/


/*
********************************************************************
**
**  Function:
**
**  Description:
**
**  Parameters:
**
**  Returns:
**
**  Calls:
**
**  Called By:
**
**  Variables:
**
**  Notes:
**
********************************************************************
*/

/*
    ALL CAPS = const
    MixedCase = AsmLabel
    Mixed_Case_With_Underscore = Variable
     G|L|S|R       Global / Local / Static / Register
     S|U|N|T       Signed / Unsigned / uNion / sTructure
     L|S|I|C|B|b   Long / Short / Int / Char / Byte / bit
     A|P           Array / Pointer

     lf|pf	   Local / Public function followed by return value (lfc is a local function returning a char)
*/

; TASK / ISR
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
; NAME:              (Who)
;
; PURPOSE:           (Why)
;
; FREQUENCY:         (How often)
;
; EXECUTION TIME:    (How Long)
;
; SEQUENCING:
;	Condition for START:
;
;	Condition for STOP:
;
;	Condition for BLOCK: (Identify agents responsible for blocking;
;			       if it never terminates, say so)
;
; PRIORITY:          
;
; PARAMETERS:        
;
; VARIABLES:         
;
; CALLS:             
;             
; RETURNS:           
;             
; I/O:               - Top level input/ouutput
;
; BLOCKING TIME:     (How long it uses a shared resource
;
; OTHER EXECUTIVE SERVICES USED: (OS calls)
;
; NOTES:
;
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 

; SHARED RESOURCE
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
; NAME:              (Who)
;
; PURPOSE:           (Why)
;
; SYNCHRONIZATION METHOD:
;
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 

The other is a tool called Leo ( http://sourceforge.net/projects/... ) It is hard for me to explain, but until you've seen 30+ lines of "what-commented" assembler "Leo-ized" into

get_from_fsaQ:

<< If the FSA Address <> 0, Then >>
	<< Load the FSA Address, LED Number & State, and System Relay Number >>
<< End If >>
<< Bubble the Buffer >>
<< Decrement the Message Counter >>
<< Get going >>
	RET

it is difficult to believe.

Leo is written in Python, and is available on Windows & Mac & Linux, and it is pretty much language-agnostic. Its roots are in Literate Programming, nut it has gone far beyond what LP promised. And no, I am not associated with Leo other than as a pleased user.

--Rich

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

I forgot my most important thingy: Flowcharts, Baby!^^

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

Here's the page that has the source for my robot project: http://homepage.ntlworld.com/sea...

Basically, apart from commenting the code, I find that it helps to define absolutely everything to meaningful names, including the registers.

Sean.

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

Picking good names is tough sometimes but definatly worth the effort. Today I worked with an ASM programm written by my boss 10 years ago
. It's only like 200 lines but he used names like: CNT, ADRESS and ADR and no comments. A flowchart got me going.

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

jgmdesign wrote:
js and I are probably the last of the freaks that still use assembler
I'm still very much a newbie around here, but so far, I've written everything in Assembler. I figure that once I've gained a greater grasp of the hardware, instruction set, and AVRStudio, I'll move on to C. I guess I'm just too much of an engineer, and tend to spend way too much time trying to cut out one or two lines of code...

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

Quote:
I'm still very much a newbie around here, but so far, I've written everything in Assembler. I figure that once I've gained a greater grasp of the hardware, instruction set, and AVRStudio, I'll move on to C. I guess I'm just too much of an engineer, and tend to spend way too much time trying to cut out one or two lines of code...

If I was you I would jump in to the 'C' language, or as it has been called "THE DARK SIDE" now. I have beencoding in one form of assembler or another for dozens of micros and as hard as I tr cannot understand 'C' for the life of me. I can interpret it to some degree, but I guess I am too far gone.

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

Quote:
but I guess I am too far gone.
Aren't listening to your president?? :shock: You CAN learn C, yes you can!!

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

Quote:
Aren't listening to your president?? You CAN learn C, yes you can!!

NO, he chants about change, I would like to see some change in my pocket...... do not get me started on that BS, let's just keep to topic.

OP,
Use what is comfortable for you and screw the rest who don't. If you go the 'C' route, you will have wealth of help here, if you stick with assembler, then you have js, an myself, along with the snickers of "THE DARK LORDS"

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

Even if you write youre code in 'C' you should still know about ASM. Even if its only to check on the compiler oder your understanding of C. For small tasks and realy time critical parts, ASM can be easier.
In my opinion prgramming in ASM is also a good excercise to get used to a good style for programming. This helps to write better programms in high level languages as well.
Its just that in ASM one realises the usefullness of upfront planing, a good names converntion ond so allready with quite small projekts. In high level languages you can get away without it a little further, but not all the way.

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

ASM really helps me to understand how my micro works. Dunno if you go that deep with C. I'll switch to high level as soon as I see a need to do so.

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

In my opinion, the "right" way to learn how computers work is to start with digital electronics, then learn assembler, then learn a low-level language like C, then go further up. That's the way to understand how each layer relates to the layer below. Without that, when you run into a problem, you have a much tougher time tracking down how to deal with it.

So many people start with high-level languages, which give you such an abstract view of the machine that it's difficult to trace what is really happening.

Sean.

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

I stopped at C... every time I try one of the alleged higher level languages I find I bounce off it; they seem almost never to match their syntax to the problem I have. Horses for courses, I suppose; I'm an old fogey with a dozen machine codes under my belt.

But I'd agree that assembler is probably helpful - though certainly not essential - and then C if you intend to program AVRs. Though my first AVR program was in BASIC - which I hated because it was limited even as a basic. Learning assembler became a priority!

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

Comments, comments comments, that is a very important part of readable assembly or any other code.
Just go back to ASM code from 6 months or a year ago and try to recall why you did that LSL or some other instruction , been there done that.
The actual 'pretty' code list is that everything should line up in the same columns for labels,op code instructions, and the operands. Of course, that is just the visible listings and suites the eye more than anything else. Then there are the actual techniques of implementing your code.
I think the best way is to just start writing assembler, after all you can do that in Studio and simulate , then start looking at other listings, the better way to learn from other experienced programmers.

I'll believe corporations
are people when Texas executes one.

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

If speed isn't all that counts I often sacrifice some to make the code more readable.

[edit]
Like today:
I had to set some Bits in PortA and B to select one of three 7seg. I've put the 3 lines into a subroutine and call it. "call LeftDisplay" pretty readable :)

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

Quote:
I stopped at C...
Many people stop at A... :mrgreen:

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

Some already even stop at B...

RES

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

... or suffer from MUMPS

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

I think many programmers just skip B and just go from A.. to C. Once you read the description of the B (not Basic) programming language you know why.

By the way, MUPS looks a little like Rexx.

Back to topic:
It helps to check on the ASM programming style if you look at some of your old (e.g. more than 3 months) ASM files and try to understand them. For the beginning try it with a few files from other peoples.