- Moving from assembly code to C
- Posted by Mark on October 5th, 2003
Any experiences with "refactoring" assembly code to C or C++?
A different target CPU (due to obsolescence and future upgrades is the
primary motivation)
This is an embedded application.
thanks for any ideas
- Posted by Thad Smith on October 5th, 2003
Mark wrote:
I would treat the assembly code as defining the functionality and as a
suggestion of _one_ way to organize the code and data. Then I would
start a clean design in your target language, organizing the code and
data in the way that is clear and makes sense, keeping in mind the
possible upgrades.
Thad
- Posted by Paul Burke on October 6th, 2003
Mark wrote:
function call with a call to an equivalent C function, e.g.
LDAA #'a'
CALL PRINT
would become
putch('a');
Then wrtie functions for everything not in the library.
Assuming of course that the assembler is written in such a helpful manner...
But as someone else has pointed out, the right way in the long term is
to rewrite the lot starting from the functionality.
Paul Burke
- Posted by Vladimir Vassilevsky on October 8th, 2003
Mark wrote:
The quick and dirty way is to translate the assembly code to C/C++
literally by replacing every assembly instruction with a macro.
The good way would be to rethink the whole project and rewrite it in
C/C++ from scratch.
Vladimir Vassilevsky
DSP and Mixed Signal Design Consultant
http://www.abvolt.com
- Posted by Kevin D. Quitt on October 9th, 2003
You've got the source?! Wow. All I ever get is "Here's the ROM and they don't
make that processor any more."
--
_
Kevin D. Quitt 91387-4454 Kevin@Quitt.net
96.37% of all statistics are made up
- Posted by CBarn24050 on October 9th, 2003
i would think carefully before doing that. Most processors have very similar op
codes, it should be quite easy to report, if a little tedious. C is all the
rage these days but it has serious drawbacks on small processors.
- Posted by Mohit Sindhwani on October 11th, 2003
cbarn24050@aol.com (CBarn24050) wrote in message news:<20031009192846.11947.00000461@mb-m03.aol.com>...
I don't want to start a language war here, because embedded systems
are all about managing compromises and divergent views of doing the
same thing.
I, personally, am a strong supporter of judiciously using C, even for
small (8-bit) microcontrollers. In my opinion, if you have a
reasonably good compiler, you can write C code that would produce very
efficient assembly.
I find C attractive mostly due to the fact that it is far more
readable (even 5 years later), easier to maintain, easier to test and
easier to port to new platforms, if the needs should ever arise.
One of the reasons C is bad for embedded systems is that there are way
too many C programmers who work all loops using "int counter;" An
integer is 16 bits even on an 8-bit platform and every time you do
"counter++;" you invoke multi-precision arithmetic on the target!
Such things don't happen in assembly because you are already thinking
at the micro-level and do the equivalent of an "int counter" is
painful.
In my opinion, if this is the first time you are targetting this
platform in C, take some time to experiment with various C constructs
on it. Get a compiler that produces intermediate assembly output that
you see.
This way:
- you know what's expensive to do in C
- you can see how different contructs in C produce different assembly
outputs (for example, loops counting up & down produce different sizes
of code)
- you have a reference implementation to optimize in assembly if you
need to
I'll end by giving two examples that I find useful when trading off C
versus assembly. Both are for the 8051 platform using the Keil
compiler.
**** EXAMPLE 1 ****
....
05 for (i = 0; i < 10; i++)
06 {
07 /* body of the loop */
08 }
....
produces the following assembly:
***
; SOURCE LINE # 5
CLR A
MOV R7,A
?C0001:
; SOURCE LINE # 7
--- the body of the loop --
; SOURCE LINE # 8
INC R7
CJNE R7,#0AH,?C0001
***
Loop setup: 4 instructions
On the other hand, re-ordering it to do a down-counting loop:
10 for (i = 10; i > 0; i--)
11 {
12 /* body of the loop */
13 }
produces:
?C0002:
; SOURCE LINE # 10
MOV R7,#0AH
?C0004:
; SOURCE LINE # 11
; SOURCE LINE # 12
--- the body of the loop ---
; SOURCE LINE # 13
DJNZ R7,?C0004
Loop setup: 2 intructions!
I don't think you can get more efficient than this (without going into
rotating bits through the carry for signalling a count of 8) and this
is written in C!!
**** EXAMPLE 2 ****
At the same time, C is particularly bad at higher precision
arithmetic. I won't post the code here, but take a look at the amount
of work you need to do to find if your addition produces a carry:
http://www.ddj.com/documents/s=1045/ddj9208c/9208c.htm
In assembly, this would quickly translate into the opcode for
Add-With-Carry.
Anyway, in my opinion, it makes sense to code a good deal of yor
apoplication in C and then find the bottlenecks and ease them out
either by writing in assembly or improving the C. This way, you are
likely to get a quicker time to completion, more confidence in your
implementation and at an affordable overhead cost.
Best of Luck!
Cheers
Mohit.
--
Join the Infineon TriCore Users Group Mailing List.
Details - http://www.chipes.ntu.edu.sg/tricore/
- Posted by Tauno Voipio on October 11th, 2003
"Mike Harding" <mike_harding1@nixspamhotmail.com> wrote in message
news:4pbfovkb069iggqj89hnr0sk1m2evsmgr1@4ax.com...
--- clip clip ---
I had - and got positively surprised how much it helped.
The conversion was from Intel 80C188 with Borland C to Atmel AT91R40008
(ARM7TDMI) with the GNU toolset. The controller (the Linet network
controller <http://www.linet-network.com/>) had about 50 kilobytes of code
and the conversion took about a week. A surprise was also that the ARM/Thumb
code was pretty near of the same length as the Intel code.
Strongly agreed. There's no way to make good embedded code without looking
at the assembly code - though the assembly code of the modern RISC CPU's is
a PITA.
Tauno Voipio
tauno voipio @ iki fi
- Posted by Tauno Voipio on October 11th, 2003
"Mike Harding" <mike_harding1@nixspamhotmail.com> wrote in message
news:j9ifov41ju33qb7m92lhv8urjn5af2omiu@4ax.com...
Not very often indeed.
Now there seems to be a burst of replacements to the 80186 family chips. For
my customers, the recommended replacement is the AT91 series, so there has
been a couple of the conversions and a dozen more in sight. The Linet
conversion was the first and it was also kind of a pilot project which
encouraged to do the others.
Still, the percentage is not very high - maybe 5 to 10 % of the long-lived
designs. Pretty often there will be also other changes to the device
architecture, so it's not a simple port anymore.
Tauno Voipio
tauno voipio @ iki fi
- Posted by Ian Bell on October 11th, 2003
Mohit Sindhwani wrote:
Unfortunately that's a very big IF.
Ian
- Posted by Mohit Sindhwani on October 11th, 2003
"Tauno Voipio" <tauno.voipio@iki.fi.NOSPAM.invalid> wrote in message news:<VJOhb.74$vE1.71@read3.inet.fi>...
Hi Tauno
I take your point on the RISC CPU assembly being tough to read... but
there are two important points here.
[1] RISC instruction sets tend to be more regular in what they do and
I often get the feeling that the compiler does actually do most of the
work and resonably well most of the time. CISC and CISC-like embedded
processors have special instructions (like the DJNZ in the example I
gave) that can affect the quality of the implementation and are, in my
opinion, the more important reason to scan the assembly outputs.
[2] The other point, and this can be argued, is that if you're usin
RISC processors, you *probably* can afford the overheads of (at least)
C, so reading the PITA-assembly is probably less crucial.
That's all
Cheers
Mohit.
- Posted by Tauno Voipio on October 11th, 2003
"Mohit Sindhwani" <emsindhwani@yahoo.com.sg> wrote in message
news:fe83e076.0310110804.1912ff50@posting.google.c om...
Yes - those conversions contained two pieces of obligatory assembly language
coding:
- hardware startup
- the core pieces of the multi-thread kernel.
In practice, the conversion involved rewriting the assembly pieces, but most
of C could just be moved, despite of the different CPU architecture sizes
(8/16 bits vs 32 bits).
Don't understand me that I did not read the generated assembly code - I'll
keep doing it despite of the RISC peculiarities. The ARM is actually pretty
assembler-friendly compared to e.g. Sparc or MIPS.
Tauno Voipio
tauno voipio @ iki fi
- Posted by Bill Davy on October 13th, 2003
"Mohit Sindhwani" <emsindhwani@yahoo.com.sg> wrote in message
news:fe83e076.0310102143.ac60e79@posting.google.co m...
http://www.microapl.co.uk/asm2c/ is a professional Asm to C tool. I've not
used it.
- Posted by Dave Hansen on October 13th, 2003
On Sat, 11 Oct 2003 19:14:00 +1000, Mike Harding
<mike_harding1@nixspamhotmail.com> wrote:
[...re: Portability of C...]
You don't have to port an entire application to benefit from
portability. The most obvious example I have is a simple serial
communications protocol that was originally written for an 80186. I
later ported that to PM 80386, an 80960, and an 8051.
Of course the UART handling codes were all different, and each
application had its own interface code between the protocol and the
application. But the protocol code itself required no changes at all
until we put it on the 8051 (there were several routines with formal
parameters named "data", which was a reserved word in the 8051
compiler).
Later I had to port to another 8051 platform, and because of limited
memory had to locate the buffers in a particular area of memory
(idata, IIRC). That didn't take long either, though it did require
some source level changes...
Regards,
-=Dave
--
Change is inevitable, progress is not.