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.

hardware is still coded with machine/assembly language for efficiency, speed, etc.

Status
Not open for further replies.
1: Now I understand that when small file size and efficiency are highly desirable then the assembly is the way to go. But I still don't really get why the code in C takes more space and is slow when compared to a code in the assembly to do the same job. We can say that the C takes circuitous route to reach the destination while the assembly takes the shortest route available. But what's the reason for the C to take a longer route? How can we analogize it better?

C compiler has to "play everything safe" and it has to do this in very general level. This is a typical AVR-GCC generated interrupt routine (and explanation what happens during it):

Every AVR register that gets modified during the ISR is restored to its original value when the ISR exits. This is required, as the compiler can not make any assumptions on the time of execution of the interrupt. Therefore, it cannot optimize which registers require saving and which don't.

1. Program Counter (PC) is pushed to the stack. (This step is similar to normal function call)
• This is done by hardware
• Needed when returning from the ISR to the original program location

2. Execution jumps to the start of the ISR, interrupts are disabled.

3. Some registers are saved to the stack
This is done by a function entry code generated by the compiler:

PUSH R1 Push register on stack
PUSH R0 Push register on stack
IN R0,0x3F In from I/O location (0x3F = Status Register)
PUSH R0 Push register on stack
CLR R1 Clear Register (R1 must always be zero)
PUSH R24 Push register on stack
PUSH R25 Push register on stack
PUSH R26 Push register on stack
PUSH R27 Push register on stack
PUSH R30 Push register on stack
PUSH R31 Push register on stack
PUSH R28 Push register on stack
PUSH R29 Push register on stack

4. User written code is executed.

5. Previously saved registers are restored from the stack.
- Function exit code generated by the compiler:

POP R29 Pop register from stack
POP R28 Pop register from stack
POP R31 Pop register from stack
POP R30 Pop register from stack
POP R27 Pop register from stack
POP R26 Pop register from stack
POP R25 Pop register from stack
POP R24 Pop register from stack
POP R0 Pop register from stack
OUT 0x3F,R0 Out to I/O location (0x3F = Status Register)
POP R0 Pop register from stack
POP R1 Pop register from stack
RETI Interrupt return (Also enables interrupts)


6. The saved Program Counter is popped from the stack and the next instruction to be executed, is the address where this program counter points.

You can easily mix ASM and C, but you also have to be very careful with it.

If you are going to interface assembly routines with your C code, you need to know how GCC uses the registers. This section describes how registers are allocated and used by the compiler.

Register Use

r0: This can be used as a temporary register. If you assigned a value to this register and are calling code generated by the compiler, you’ll need to save r0, since the compiler may use it. Interrupt routines generated with the compiler save and restore this register.

r1: The compiler assumes that this register contains zero. If you use this register in your assembly code, be sure to clear it before returning to compiler generated code (use "clr r1"). Interrupt routines generated with the compiler save and restore this register, too.

r2–r17, r28, r29: These registers are used by the compiler for storage. If your assembly code is called by compiler generated code, you need to save and restore any of these registers that you use. (r29:r28 is the Y index register and is used for pointing to the function’s stack frame, if necessary.)

r18–r27, r30, r31: These registers are up for grabs. If you use any of these registers, you need to save its contents if you call any compiler generated code.

Function call conventions

Fixed Argument Lists: Function arguments are allocated left to right. They are assigned from r25 to r8, respectively. All arguments take up an even number of registers (so that the compiler can take advantage of the movw instruction on enhanced cores.) If more parameters are passed than will fit in the registers, the rest are passed on the stack. This should be avoided since the code takes a performance hit when using variables residing on the stack.

Variable Argument Lists: Parameters passed to functions that have a variable argument list (printf, scanf, etc.) are all passed on the stack. char parameters are extended to ints.

Return Values: 8-bit values are returned in r24. 16-bit values are returned in r25:r24. 32-bit values are returned in r25:r24:r23:r22. 64-bit values are returned in r25:r24:r23:r22:r21:r20:r19:r18.

Sorry for long post. The quotes are from my school project documentation. The assignment was to write "real time scheduler" for AVR microcontrollers using AVR-GCC compiler. Practically useless, but very educational.
 
Last edited:
Last edited:
Hi
1: Now I understand that when small file size and efficiency are highly desirable then the assembly is the way to go. But I still don't really get why the code in C takes more space and is slow when compared to a code in the assembly to do the same job. We can say that the C takes circuitous route to reach the destination while the assembly takes the shortest route available. But what's the reason for the C to take a longer route? How can we analogize it better?

In assembly the writer can do many different things to save code and execution time. For instance, if a programming for a PIC like a 16F688 where some memory is in banks, but some is accessed on any bank, the compiler will have to set the banks in most if not all subroutines, and probably set the banks again after the return. In assembly the programme may know what the bank will be left at when the subroutine is called, and not have to change the banks.

If a bit of code needs to be run a number of times, assembler can do that very efficiently with something like this
Code:
    movlw    0x10
    movwf    countreg
loop_start
    [code to run several times]
    decfsz     countreg, f
    goto       loop_start

Now in C, you write
Code:
  int x = 0;  
  while ( x < 10 ) { 
      [code to run several times]
    x++;
  }

The C compiler will test x the first time through and have a way of avoiding the code to be run even on the first time. So there will be two goto statements in the resulting assembly language. There is also the question of whether x is actually needed inside the loop.

Of course, optimisers vary so some will be clever than others, and will take shortcuts when they can.
 
Hello PG1995,

Think of it this way for your first question. People that code in assembly, are in tune with the actual guts of the microcontroller or microprocessor.
People that program with hll are taking programs that are already written for the programmer (libraries) and put these in an orderly fashion to produce a program
for there task.

So with hll it is "modular programming" (high level) just putting blocks of code that someone wrote together not needing to know the architure of the device(s).

Here is an example of a assembly program for a sleep mode, external interrupt INT0 with a written ISR, with a explaination.



;*******************************************
;new project testing int0
;*******************************************

.include "tn2313def.inc"


rjmp RESET ;reset handler
rjmp int0 ; this is the external interrupt handler
RESET:
.def temp=r16
.def temp1=r17
.def temp2=r18
.def temp3=r19
.def temp4=r20
.def temp5=r21

ldi r16,low(ramend)
out spl,r16 ;set up stack
rjmp start
nop
reti
start: ldi temp,$00
out ddrb,temp1 ;set portb input
out ddrd,temp1 ;set portd input

;***********************************
;power down mode
;***********************************

sei ;enable global interrupts

ldi temp1,$13 ;ready to set up mcucr reg
out mcucr,temp1 ;power down mode, portd pin 2, rising edge

ldi temp2,$40 ;ready to enable int0 in global interrupt register
out gimsk,temp2 ;int0 enabled

ldi temp4,$33 ;setting up to enable sleep mode keeping power down mode and rising edge
out mcucr,temp4 ;13h pluse 20h = 33h, 13h is from above of mcrcr
sleep ;put the microcontroller in sleep mode
;wait for pd2 to go high (rising edge) When pd2 goes high the flag register in the gimsk will go
;high, jumped out of sleep mode, the next clk it will jump to INT0, the next clk it will jmp to
;program counter 6 (pc6), reti, for instance INT1 would jmp to program counter 7
;(pc7) next clk(s) your address where it jump to int0 will pop of the stack and return you to
;back to whereyou were, the instruction after sleep, out mcucr. This where your ISR starts.
out mcucr,temp1 ;set of register to disable sleep mode temp1=13h
ldi temp2,$00 ;ready to clear interrupt int0
out gimsk,temp2 ;clear enable interrupt register (gimsk)
loop: rjmp loop ;countinue on with regular programming.


Now with this simple program, you have total control of what is going on and you can make this a call routine that can be used over and over as
you need it.
Basically you have written your own "library".

With hll, when you use a program for your interrupt's it has all interrupts included, so no matter what interrupts you use they are there in the library, thus the overhead, (size of your program). In addtion with the included program (library) it must go through the whole program of the library (include file) which will slow
down programming.

Hope this will help a bit to understand the difference in programming with asm and hll.

jlpelect5
 
1.) C is designed to allow it's core libraries to be re-written to run on virtually any known micro controller or processor. This requires a level of abstraction from assembly as the architecture of different chips can vary wildley, that's why the extra work is required, more efficient C can be had by recoding the compiler itself and optimizing IT but there is no inherent fix.

2.) Optimized means that the C compiler has been thoughtfully coded to take the most advantage of every possible instruction the chip has in the most direct way possible. Embedded C is little more than C that has additional libraries that allow code that looks very similar to ASM on that particular chip to be written. However additional functions have to be added that are not standard to core C libraries, almost no programming on a micro controller or embedded system uses a stock ANSI C compiler, they're are always additions.

3.) Misra is a standard for automotive applications. If you refer to C without any specifications ANSI C is what is implied as that is the primary standard for C compilers most everything else is based off of that. The standards are all formalized ways of describing syntax required libraries and program behavior and there are literally thousands of different varieties of C, technically they're all different languages, but as long as ANSI C standards are adhered to code portability isn't usually a problem.
 
Hello Sceadwian,

From what you are saying, would it be correct to assume that the libraries in a hll programming enviroment are getting even bigger to accomodate
all situations of different hardware designs, which would increase the overhead.

To me that increases the potential to cause problems in program flow especially if there is a timing issue or there needs to be an addition to the program
(new feature).

All I am saying is that if you are going to get into programming, use asm and avoid everybody's ideas of trying to put every possible combination of a routine
into a "include routine" (library), then spend most of your time trying to debug your program when it doesn't work.

I have worked along side of C programmers and they spend more time debugging there programs than they do programming.

jlpelect5
 
jlpelect5 said:
From what you are saying, would it be correct to assume that the libraries in a hll programming enviroment are getting even bigger to accomodate
all situations of different hardware designs, which would increase the overhead.
Exactly so, you said it better than I.

jlpelect5 said:
To me that increases the potential to cause problems in program flow especially if there is a timing issue or there needs to be an addition to the program
(new feature).
Again, yes I couldn't agree more.

jlpelect5 said:
All I am saying is that if you are going to get into programming, use asm and avoid everybody's ideas of trying to put every possible combination of a routine
into a "include routine" (library), then spend most of your time trying to debug your program when it doesn't work.
Once again you're saying exactly what I intended. This is the only way that one can become a good programmer, there is no other way.

This is not to say the HLL's are bad, but after a certain degree of abstraction the fluff becomes dead weight if no one does any trimming.

I have to state this as fact, but I do understand what 3v0 is stating when it comes to a production environment being the root of why things have come to this. Using the bloated HLL languages massively complex API layers and trees of abstraction and dependencies you can pump out a LOT of crap. Given that Moores law causes hardware ability to expand faster than we can cope with as programmers there are some very intriguing effects to simplifying things in that miniaturization becomes possible. You can make it small and powerful and efficient, but you can't use any of the old code.

This is specifically why IOS and Android have exploded to the degree they have in recent years.

It is important to note two things. Multi core RISC chips and specialized CISC type graphics units are overtaking conventional computing methods like a tempest. The old single core single instruction set methods are falling by the wayside. The seas will be choppy for more than a number of years though, there are going to be game changers to come I'm sure.

At some point you run out of resources and the C programmers go "You can't do that with this" And the ASM programmers will always be there to make them look like idiots.

Given the... sheer vertical wall of computing power available to a programmer nowdays the only limiting factor as to what we can do with it is to program it right! This is why so many distributed computing programs have spawned off in recent years, there's so much wasted power available no one know how to harness it all!
 
Last edited:
From what you are saying, would it be correct to assume that the libraries in a hll programming enviroment are getting even bigger to accomodate
all situations of different hardware designs, which would increase the overhead.

No, it is the job of the compiler to know the hardware and optimize for it. There really is no big third party software libraries in embedded C.

I have worked along side of C programmers and they spend more time debugging there programs than they do programming.

That is because they are implementing more complicated stuff than ASM programmers. They are also spending less time on programming and more time on testing. That only shows how efficient C is.
 
misterT said:
No, it is the job of the compiler to know the hardware and optimize for it. There really is no big third party software libraries in embedded C.
What about API's? The DLL becomes an extension of C it's not longer compiler based. It's native C talking to something else... more senseless layers of abstraction to make the code farmers able to churn out a product. This is not efficient, it's convenient!

misterT said:
That is because they are implementing more complicated stuff than ASM programmers. They are also spending less time on programming and more time on testing. That only shows how efficient C is.
How do you define efficiency? This statement makes absolutely no rational sense from any definition of efficient use of system resources that I'm aware of!

If your goal is to write code that does something C works fantastically given the exponential increase in computing power. ASM given the same resources can do exponentially more regardless of complexity, this can be proven in the code simplification of modern mobile operating systems. Simplifying makes this more efficient, you can't make things more complex and efficient at the same time within a limited number of resources at least.
 
Last edited:
What about API's? The DLL becomes an extension of C it's not longer compiler based. It's native C talking to something else... more senseless layers of abstraction to make the code farmers able to churn out a product. This is not efficient, it's convenient!
There is no DLLs in embedded C world. Only in windows.. and those libraries are compiled to machine language. You do not know what you are talking about when you say "It's native C talking to something else". Do you code ASM for windows?

How do you define efficiency? This statement makes absolutely no rational sense from any definition of efficient use of system resources that I'm aware of!
If your goal is to write code that does something C works fantastically given the exponential increase in computing power. ASM given the same resources can do exponentially more regardless of complexity, this can be proven in the code simplification of modern mobile operating systems. Simplifying makes this more efficient, you can't make things more complex and efficient at the same time within a limited number of resources at least.

Production efficency of course.

Switching from ASM to C does not increase the running time of a program exponentially (linearly at most). Bad algorithm design can make that kind of hit (exponential) to any program. With C it is very fast to get things running so that you have very good results to show your client, then you can take some time to profile your code and algorithms and start re-designing for efficiency.. starting from the biggest bottleneck.
 
Last edited:
There is no DLLs in embedded C world. Only in windows.. and those libraries are compiled to machine language. You do not know what you are talking about when you say "It's native C talking to something else". Do you code ASM for windows?
You must have missed the demo scene links I posted earlier that are ASM programs coded for windows. Please refer to the 64k entry I posted earlier. They used windows based PC's using DirectX the code that generates everything you see and hear is written is pure ASM and is slightly less thant 64kb in size, though it takes up the full 64k because of file system restrictions.

MisterT, you're cross posting unrelated concepts.
 
Last edited:
You must have missed the demo scene links I posted earlier that are ASM programs coded for windows. Please refer to the 64k entries I posted.

Yeah.. those are nice. Nothing to do with windows and DLLs though.
 
mistert.... They're 64K ASM programs written that use Windows and DLL's. They show what can be done with tight efficient coding and procedural textures given a limited set of coding allowed. You could do 100 times better, with 1000 times more code in C. Some of the less restricted ASM categories show this.
These groups, and often times kids can show up the most proficient programming groups on earth, they just can't produce billion dollars code that can be fed off to the sheeple for consumption, but they can do anything with a limited set of resources.

Again, the IOS and Android reboot to current consumer based technology is game changing, not because it adds more layers of abstraction but because it simplifies on existing hardware and technology. People are buying this stuff by the boatload. This is a boon for efficiency awareness, it won't be much but it is just what the current computing paradigm needs.
 
Last edited:
mistert.... They're 64K ASM programs written that use Windows and DLL's. They show what can be done with tight efficient coding and procedural textures given a limited set of coding allowed.

Yeah, sorry.. I mixed that with the oldskool demos (C64, Amiga, MOD).

We should have a competition. A tetris on 8x16 dot matrix display. C programmers vs. ASM. Can be either 8 bit AVR or PIC.
 
Last edited:
Wouldn't be a contest if you had a good C programmer and a good ASM programmer working it, ASM would win hands down, no contest. You want a time crunch? Figure hours worked vs result. A C programmer can give you a faster output of reproducible results. An ASM program will get there slower, but will surpass C given enough time, and given the same resources C can never make up that ground.

This thread has been earmarked as some as what is proper in a commercial output situation, which I don't even consider.

Faster is better, smaller is better, because then you have less things to do regardless of what you're using. Power is lower, waste is lower. Anything done right in ASM vs the same thing done in C is ALWAYS better in ASM.

This is not to say that higher level languages don't have their place. But ASM will always put them in their place.

Super genius machine language programmers that have high degrees in compression could do better.

It's always energy in, energy out. The world is rife with examples of things that can be done simpler and better with even a higher profit margin, just gotta find the right entry point and be able to produce a product.
 
Last edited:
I just want to toss this out.

Lets look a very simple, and useless, program for the PIC16F88 compiled with hi-tech c lite. Clearly everything in this program is either the overhead needed to setup the uC or bloat.

Code:
#include<htc.h>

__CONFIG(FOSC_INTOSCIO & WDTE_OFF & PWRTE_OFF & LVP_OFF & BOREN_OFF & DEBUG_OFF);
__CONFIG(IESO_OFF & FCMEN_OFF);

unsigned char i;
void main (void)  // simple
{
}

Now lets look at what it generated.
Code:
Memory Summary:
    Program space       used     7h (     7) of  1000h words   (  0.2%)
    Data space           used     2h (     2) of   170h bytes   (  0.5%)
    EEPROM space       used     0h (     0) of   100h bytes   (  0.0%)

Listing
84:                clrf status
   7FD    0183     CLRF 0x3
85:                ljmp _main	;jump to C main() function
   7FE    118A     BCF 0xa, 0x3
---  E:\Users\webmaster\Dropbox\Lock\lock\lock.X\simple.c  ---------------------------------------
1:                 #include<htc.h>
2:                 
3:                 __CONFIG(FOSC_INTOSCIO & WDTE_OFF & PWRTE_OFF & LVP_OFF & BOREN_OFF & DEBUG_OFF);
4:                 __CONFIG(IESO_OFF & FCMEN_OFF);
5:                 
6:                 //unsigned char i;
7:                 void main (void)  // simple
8:                 {
9:                 }
   7FB    118A     BCF 0xa, 0x3

If you guys really want to go into this we can look at code that is a bit more complex. We would see that an ASM programmer could improve it but not to the extent some people are suggesting.
 
Wouldn't be a contest if you had a good C programmer and a good ASM programmer working it, ASM would win hands down, no contest. You want a time crunch? Figure hours worked vs result. A C programmer can give you a faster output of reproducible results. An ASM program will get there slower, but will surpass C given enough time, and given the same resources C can never make up that ground.

How many ASM programmers out of 10 can do that (tetris game) in a weekend? Or even in a week.. or at all? I have no trouble finding a C programmer that can program a tetris game in one workday.
 
Last edited:
Yeah.. those are nice. Nothing to do with windows and DLLs though.

Yes, The mind boggles sometimes when simple concepts are just glossed over by some.

How do you get across to people you can write a complete complex embedded program in a HLL compiler like C18 without using one standard library if you wanted by not using the run-time library (not easy but possible). You could access every memory location or function on a PIC chip without using the Microchip app libraries if needed and create a completely new API or interface method if you wanted.

Example from the C18 manual:

Code:
To execute application-specific code immediately after a device reset but before any
other code generated by the compiler is executed, edit the desired start-up file and add
the code to the beginning of the _entry() function.
To customize the start-up files if using Non-Extended mode:
1. Go to the c:\mcc18\src\traditional\startup directory, where
c:\mcc18 is the directory where the compiler is installed.
2. Edit either c018.c, c018i.c or c018iz.c to add any customized start-up code
desired.
3. Compile the updated start-up file to generate either c018.o, c018i.o or
c018iz.o.
4. Copy the start-up module to c:\mcc18\lib, where c:\mcc18 is the directory
where the compiler is installed.
 
To the Ineffable All,

I own the 5th edition of a book called Programming Windows, by the Windows programming guru, Charles Petzold. For teaching purposes, this book contains many "C" programs. I have translated most of those programs into Masm, which is the Microsoft offering of Assembler. If anyone is interested, I could post the original C symbolic and executable of a program written by the guru himself, along with my Masm version so as to show how they compare codewise. I know this is not a speed contest, and it is for Windows, not a microcontroller. But doing a side by side comparision of the code might give those interested a taste of what is it like. For the most part, I have not tried to improve on his programming algorithms for each program, but instead, just translated everything line by line. It might be interesting to some folks.

Ratch
 
Hello misterT, nsaspook,

You guys are insisting that hll is the way to go where i disagree.
Let's face it, all hll programming languages are built and derived from assembly language.

misterT, from your previous post, you even said that you have to resorte to assmebly language
in your hll programming to get the job done.

If you have started with assembly in the first place, you would not have to back track to the
language that created the hll in the first place.

I Remain
jlpelect5
 
Status
Not open for further replies.

Latest threads

Back
Top