How can I exam differences between a ASM and C++ program that perform same task - Page 1
Forum section: electronics / projects

author: shanecy
author_rank: Contributor
timestamp: February 06, 2015, 06:14:53 pm
content: THE PURPOSE OF MY CODE:I have two programs that both do the same thing except one is written in ASM and one is written in the Arduino IDE. The code is very simple. Its purpose is to create two pwm signals to be emitted off of their respected pins. One signal is 125Hz @25% and the other is 250Hz @25%. Through toggling a switch one of the signals is selected and passes through to two linear servos that are acting as a lift. In short one signal moves the lift up and the other signal moves it down. The hardware i'm using is the ATmega328P chipWHAT I'M TRYING TO DO AND ASKING GUIDANCE FOR:I'm presenting a class project and I would like to exam the code execution from a clock cycle perspective or I should say a "performance standpoint in general". I know the .lss file generated from my ASM code lists total memory used, clock cycles and more interesting notes but I'm unsure how to exam my arduino code. I also have a nice Lecroy Scope that I would love to hook up to a projector and scope my signals from two perspectives one being from the ASM program and the other being my Arduino program but I doubt there is going to be much to show.Any idea how I can exam my Arduino code more closely and possibly implement my scope into this presentation. Having a hard time here formulating my words on what I'm wanting. Basically, I would like to exam the differences between both programs more closely than just throwing up boring code side by side. No one wants to read assembly, so to me some how giving a more visual presentation seems like the way to go.I will be glad to post schematics and code if that is needed. However, right now i'm looking for some guidance/direction on how to achieve this. This probably wont help but i'm posting a pic that might help with giving you a visual perspective of the project. I have a video but can't seem to upload it.

author: DIPLover
author_rank: Regular Contributor
timestamp: February 06, 2015, 06:21:40 pm
content: Unfortunately, if you want to compare compiler output vs hand-coded assembly... you will have to look at assembly...You could select interesting portion of code where the compiler (or the asm programmer!) does really dumb things and compare them side by side.You could make nice pie-charts and graphs about instruction mix and code size and execution time...But ultimately, what you will need to compare are 2 assembly listings.

author: jancumps
author_rank: Unknown
timestamp: February 06, 2015, 06:37:38 pm
content: If your two programs do the same, they'll look perfectly the same on your scope.You could show the difference in resource use from statistics, as DIPLover suggests (memory consumed for code and variables size)The load will most likely be 100 % on both pieces of code, at it is a single threaded controller.

author: Rasz
author_rank: Super Contributor
timestamp: February 06, 2015, 06:50:02 pm
content: this might helpYou either need hardware debugger, or dissembler to do static code analysis.I fail to see how you can look at your example from a performance angle, if both programs are correct there will be same performance, unless you bump frequency to couple of mhz, or 16 channels.What you can do is compare algorithms, maybe one is counting clocks while the other is using timers/interrupts, you can compare implementation time and experience level requirements for both approaches, ease of debugging, code readability, etc.

author: dannyf
author_rank: Super Contributor
timestamp: February 06, 2015, 06:53:43 pm
content: Measuring clock cycles is fairly straight forward, even without a hardware debugger: you can have one pin doing something at beginning of a code piece and one pin (could be the same pin) doing something else at end of the code piece.Hook up your scope / logic analyzer and you are done.

author: diegosfb
author_rank: Contributor
timestamp: February 06, 2015, 07:30:28 pm
content: You can toggle some output upon task completion; and hook up your scope to that pin and measure exactly how much time it takes the us to perform that task in C vs. How much time it takes the us to perform that task in as.That way you can have a sense of speed performance.To check memory performance, most IDE's will let you create an info file along with the output files that will let you know how much memory has been used.Best Regards,

author: zapta
author_rank: Super Contributor
timestamp: February 06, 2015, 07:59:19 pm
content: A program that generates PWM signals using the hardware peripherals/timers is not a good choice for demonstrating performance differences between C and ASM. If this is your goal, you may want to choose a different problem that demonstrate better the differences (e.g. bit banging serial communication, etc).

author: eneuro
author_rank: Super Contributor
timestamp: February 06, 2015, 08:16:09 pm
content: Quote from: shanecy on February 06, 2015, 06:14:53 pmI used to put a few NOP instructions to mark interesting part to examine, than look into.lssand by openning MPU AVR datasheet registers descriptions and instruction set summary, not such a big deal to find how good machine code is generatednop()is declared like below in my C code:Code:// Delay in 1 clock#define nop() { __asm__ __volatile__ ("nop"); }Than C code like this:Code:nop();nop();for(;;) {// Switch AC Mosfets gate ON//ponoff2(GDTHPIN, GDTLPIN );pins= PORTB;pins &= ~(1<<GDTLPIN);pins |= (1<<GDTHPIN);PORTB= pins;delaydiv2((1.0/GDTFREQ/2.0) );can be found in assembler listing.lsseasyCode:a4: 00 00 nopa6: 00 00 nopa8: 95 e0 ldi r25, 0x05 ; 5aa: 88 b3 in r24, 0x18 ; 24ac: 8f 7e andi r24, 0xEF ; 239ae: 82 60 ori r24, 0x02 ; 2b0: 88 bb out 0x18, r24 ; 24b2: 89 2f mov r24, r25b4: 8a 95 dec r24b6: f1 f7 brne .-4 ; 0xb4 <main+0x40>Of course from AVR ATTiny85 datasheet,PORTBis0x18on ATTiny85, so I know exactly how much time this part of code will run on its 8MHz internal clock, so can compensate in custom delay functiondelaydiv2to get given switching frequency and its inline assembler code can be easy verified if neededCode:b2: 89 2f mov r24, r25b4: 8a 95 dec r24b6: f1 f7 brne .-4 ; 0xb4 <main+0x40>

author: BlueBill
author_rank: Regular Contributor
timestamp: February 06, 2015, 10:42:06 pm
content: Does the Atmega328p have dual channel hardware PWM? (I'm a PIC guy and most of their 28pin devices have dual PWM).If so it's just set it and go, zero cpu overhead.

author: Pjotr
author_rank: Frequent Contributor
timestamp: February 06, 2015, 11:08:07 pm
content: Using a peripheral pin as a HW flag is indeed a very effective way to time pieces of software. Set the bit at the start and clear it at the end of what you want to time. But in C you will not know how efficient the bit set and bit clear commands will be executed (number of CPU cycles). In assembler it is just a few cycles.I have coded a lot of time critical apps in assembler and this is also a good way to look at the variation due software decisions made within a routine: Conditional jumps/branches, calls and so on. Or to verify if an interrupt routine finishes in time if it is a high speed interrupt at say 50 KHz. Hook up a DSO to the HW pin/flag and set persistence to infinite and you get a nice view of the timing variation over longer time.

author: zapta
author_rank: Super Contributor
timestamp: February 07, 2015, 02:03:22 pm
content: Quote from: BlueBill on February 06, 2015, 10:42:06 pmIt has three counters with PWM. Two 8 bits and one 16 bits.

author: zapta
author_rank: Super Contributor
timestamp: February 07, 2015, 02:04:53 pm
content: Quote from: Pjotr on February 06, 2015, 11:08:07 pmI typically assume that it will be at least as fast as my assembly code ;-)

author: paulie
author_rank: Frequent Contributor
timestamp: February 07, 2015, 02:09:46 pm
content: Quote from: BlueBill on February 06, 2015, 10:42:06 pmActually the mega328 has 6 channels capable of generating somewhat independent PWM. Much more popular and lower cost mega8 has 3.

author: Pjotr
author_rank: Frequent Contributor
timestamp: February 07, 2015, 02:24:00 pm
content: Quote from: zapta on February 07, 2015, 02:04:53 pmOf coarse, the low level assembly C output ends up with the same bit set and bit clear instructions. But it depends on how it is implemented in C at assembly level. Is it just straight in-line code or done by a call? Did you looked at the assembly output of your compiler?

author: Stupid Beard
author_rank: Regular Contributor
timestamp: February 07, 2015, 02:40:07 pm
content: Quote from: Pjotr on February 06, 2015, 11:08:07 pmYou can look at the C compiler's asm output (or disassemble the binary) and just use the same code in the asm version to negate that issue. It doesn't matter how long it takes to change the pin, only that it's the same time on both versions of the code.

author: AndyC_772
author_rank: Super Contributor
timestamp: February 07, 2015, 02:52:57 pm
content: If you want to demonstrate how many instructions are required by certain parts of your code, then as mentioned above, just set a GPIO output at the start of the code and clear it at the end. By comparing the signals on a scope, you can get a very good idea of how efficient one program is relative to the other.For a class project, it might be interesting to consider how the two approaches might be compared in other ways, though. Clearly both are able to generate the same output with the same hardware, so it might be argued that it doesn't matter if one program is busy most of the time, while the other completes its task more quickly and spends the rest of the time executing NOPs or polling a timer.For example...- how long did each program take to write? What would this mean commercially, if your time costs a certain amount per hour, and the number of units being built is 10? Or 1000? Or 1000000?- what's the process for making changes? If, say, an additional output channel were needed, how much work would it be to add that capability in each case? (Fact: most development time is spent upgrading and maintaining software, not writing it from scratch).- what would happen if the microcontroller you're using were discontinued, and you had to port the project to another one from a different manufacturer?- do either of your programs have bugs in them? How do you know? How would you analyse each one to demonstrate that it produces the correct output under all conditions?

author: pol098
author_rank: Newbie
timestamp: February 07, 2015, 03:45:34 pm
content: Not actually answering the question at all, but some experience that people don't get these days, from 8086 computers, probably not even relevant:1. I needed to drive an RS232 printer from a computer with only a parallel port (there was no off-the-peg hardware to do this; and the printer worked fine with RS232 pulses between 0 and 5V, instead of -12 and +12). I wrote a program in assembly language; it worked at lower baud rates, but not at high speed. A scope told me that the pulse durations weren't right. So I took a manual of the cycles needed by all opcodes, and modified the program to take this fine detail into account; then it worked fine. Essentially, an instruction "take the Tx pin high" instead of being instantaneous actually spent a while setting up and executing the instruction; that needed to be taken into account. Perhaps a little less important with a 3,000MHz clock than at 4.77MHz.2. No hardware element this time, but I had a sort program written in high level language (Pascal) that needed more speed. I identified the critical inner loops, used a debugger to see the machine-language instructions, then rewrote that bit of code doing nothing differently, but getting rid of all the useless operations. I don't remember details, but not loading registers with values that were not actually used, maybe using registers instead of memory, and so on. It made ahugespeed improvement. If it's not obvious where the critical bits are, a profiler helps to find them.looking at the machine-code instructions.

author: jaxbird
author_rank: Frequent Contributor
timestamp: February 07, 2015, 04:07:33 pm
content: Late to the partyWithout reading all the replies, (you've probably already been told) The only way to compare C code to assembly is to compare the compiled C code assembly to your original assembly, easy as that.Simple code is easy to compare cycle by cycle, but even slightly complex code can be challenging to compare and you are better off adding some performance indicators, commonly just flipping a pin and hooking up a scope to measure.