News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

C/C++ vs Assembler

Started by Manos, May 04, 2013, 04:11:50 AM

Previous topic - Next topic

MichaelW

Quote from: dedndave on May 04, 2013, 10:34:25 PM
the assembler program is probably smaller than the hll one   :P

And if the C program was done in plain, straightforward C it was probably easier and faster to code and less likely to contain bugs/errors.
Well Microsoft, here's another nice mess you've gotten us into.

Manos

Quote from: anunitu on May 04, 2013, 11:27:21 PM
You do know Microsoft is not a religion right?..really one could say anything about MS and not be burned alive on a stack if motherboards.

A serious person never speak ironicaly for other persons, companies or works.
If someone does not like a company or a project, simply don't use this.
But some people behave sometimes like juniors in high school.
This forum is supposed to be about talking for programming, neither for speaking ironicaly nor for attackes.

Manos.

hutch--

Its basically the case that what you are familiar with will in part dictate what you program in. The last rewrite of my editor was completely in MASM and I saved more than 2 weeks in writing time over the earlier version. It is just on 200k of assembler code for the bare editor, then there is the code for the dedicated DLLs which is a mix of HLL and assembler, the scripting engine is almost exclusively assembler using the dynamic string of basic for technical reasons.

That none of it is all that big is because it IS written in assembler and much of the speed gain in writing better code was because it was written without the irritations of higher level languages. Its typically the case of being front end unfriendly but very back end friendly.

The main gain writing in C is portability but only if you are using fully portable libraries with no API code. Once you are committed to a specific operating system with Windows API functions, MASM code is just as fast to write as any higher level language that uses the same functions and it is free of the irritations and restrictions of higher level languages.

VC98 is antique junk and the assumptions from that era are no longer sound, even if they were back then, the odd bits of C the I compile these days is usually in VC2003 as it was both a better compiler and better linker with a greater range of libraries.

Antariy

First link in the signature field of this message.
Pure hardcore C++ written to be compilable for both 32 bit and 64 bit platforms without change of single line of code.
The question of the EXE file size in this case is a question of lazyness, and, yes, written in assembly with the same functionality it will not be anyhow much smaller. Aligned by section size EXE will not be smaller at all.

But yes, it is not the anyhow complex program, and, what is more important, it uses pretty linear logic which uses integer arithmetic.

There, in the field of the code which is easy "serializable", like simple integer math, control flow structures, calltables, jumptables and other similar stuff are, which do have equal translation from the HLL to the machine code, the C optimizing compiler-generated code is not slower and is not "bigger" than the best possible ASM code. But, still, FPU code, tricky and/or sophisticated integer code, SSE code and so on - is the kingdom of ASM.

Sometimes the question of "what language to use: C or ASM" is just a matter of design, development time for given particular project and of course lazyness :greensml:


Jochen, :t

anta40

Quote from: Manos on May 04, 2013, 06:27:15 PM
And a question: Why MASM, JWASM, POASM, NASM and Windows are written in C language ?

Probably this has something to do with the UNIX culture.
In the 1970s, those Bell Lab folks (Dennis Ritchie, Ken Thompson, et al) needed a language than asm to rewrite UNIX. Hence, C was born.
They used C not only for the UNIX kernel, but also for compiler, assembler, editor, etc.
And these UNIX systems have C compiler included, then C became widespreaded. Everybody started to write in C.

Now why are those things are written in C?

  • C is well known
  • C is portable
  • C provides a little higher abstraction than asm
  • C can be compiled into efficient machine code (given a smart compiler)
  • C is not that complicated (compared to C++, for example)

I think C is fine for doing system programming. I don't buy the old UNIX hackers mindset though, that is to write everything in C. If people asked me to write applications, I will choose languages "higher" than C, like Delphi or Java, for example.

Jibz

I've always found it odd to try to compare a HLL to assembly language -- since any HLL, interpreted or compiled, will in the end result in execution of assembly language instructions, it is obvious that no HLL can ever be faster than optimal assembly language.

What this fails to take into account, is of course that it requires considerable knowledge, skill, and usually time, to get even a near-optimal solution in assembly language. Also, once you have reached a near-optimal solution, even small changes in the specification, can result in large amounts of work to change the code to solve the new problem in a near-optimal way.

There are  few situations where the extra effort is worth it; usually inner loops in time critical code. Elsewhere, I believe spending a fraction of the time writing, debugging, and maintaining the code in a HLL makes more sense :t.
"A problem, properly stated, is a problem on it's way to being solved" -Buckminster Fuller
"Multithreading is just one damn thing after, before, or simultaneous with another" -Andrei Alexandrescu

jj2007

#21
Quote from: Jibz on May 05, 2013, 07:00:18 AMit requires considerable knowledge, skill, and usually time, to get even a near-optimal solution in assembly language.

Yes it requires an effort, once, to get a library function working, but so what? Over years, we had a lot of fun picking a CRT function, e.g. strcmp, and giving it a thorough beating, see here. And why is a factor five faster than CRT only "near-optimal"?

Now that may be an extreme example, but over time we have seen many CRT functions been replaced by assembler equivalents that did the job in less than half the time.

So much for speed and innermost loops. But what about a real life app? Does it really take longer to write invoke CreateWindowEx instead of CreateWindowEx();, with three extra chars that will ruin your fingers over the years?

Sure it will take more time if you mean "pure" assembler - Hutch maintains a nice demo at \Masm32\examples\exampl07\slickhuh

But only masochists use pure assembler, reasonable coders use macros mixed with pure assembler. For example, loading a text file from disk and shuffling it into a string array costs me one line. One.

Handling arrays, whether "double" aka REAL8 or REAL4 or any integer size, can be easier with assembly macros than with most HLLs including C/C++

qWord has written a marvelous simple math library that makes arithmetics as easy as in any other HLL.

We have rejecting and non-rejecting loops, C and Basic-style for loops.
We have a Switch/Case macro, and it has a lot more power than its C equivalent.
We have several macros for SEH, e.g. mine - but almost nobody uses them. Because we control our code so tightly that we would not allow a release version throwing exceptions.

Which brings me to my last point: Quality. HLL must be better, right? That's theory, practice is that assembler forces the coder to reflect thoroughly on each and every line, and that produces better quality than code that relies on "my compiler knows how to do that".

Of course, C/C++ is everywhere, and most of the big commercial apps are written in that language. That is why I am not impressed, I see too much bullshit produced from apparently huge teams of programmers in respected big software companies. MS Word forgetting to redraw, for example. And every time I shut my puter down instead of hibernating it, on reboot Adobe pops up and solemnly swears that this time the known security and performance problems are finally solved. IMHO they will be solved when Adobe goes back to BASIC.

[edit: fixed a garbled phrase]

hutch--

I am a moderate here, I am of the view that Microsoft have it right in providing BOTH CL.EXE and ML.EXE with a compatible object module format so that you can link them both together so you can get the best (or worst) of both worlds in an application. What I am not a fan of is inline assembler in an optimising compiler as it makes a mess of both capacities, to this extent one of the few things I approve of in 64 bit code is the removal of inline assembler so that you MUST write a separate module for assembler code.

Now having cast my eye over a lot of C and assembler code in my time, one thing you CAN garrantee is that badly written code in either performs badly, equally well written code in either performs well enough in most instances and an appropriate level of competence in both is necessary to perform any sensible comparison.

Then there is the readability issue and I have seen enough of both to say that much of both is unreadable, with bad assembler it looks something like an assembler dump and while I am practiced at reading this stuff, it is no joy to work on. With badly written C I have seen some of the most appalling messes with the author trying to be profound in bundling a whole heap of functions together and non-symetrical brace indentation and to read or fix it you have to carefully pick it apart and re-edit it to make sense of it.

My own C code is still written 1990 K&R style so I can read it but I write very little C these days, that what I have MASM for. In a forum of this type where there are a large number of people literate in multiple languages, a topic of this type is little better than noise as most members know the difference and use the tool of their choice for the task they have in mind.

For folks who are happy t use mixed languages there are viable options using both.

C + asm
asm + C
asm
C

It easy enough to write a separate module in C and then link it into a MASM app as well as the other way around. I remember some years ago finding this massive collection of sort algos written in C so I compiled each one into a module and tested them in a MASM test piece. The few that were any good I converted directly to MASM, mainly for the practice of optimising the C code to get a bit more pace out of it.

Antariy

I will second Hutch's proposal.




(a bit kidding now)

try {
Jochen, I agree with all sentences of your speech,
}
except {
Quote from: jj2007 on May 05, 2013, 08:58:54 AM
We have several macros for SEH, e.g. mine - but almost nobody uses them. Because we control our code so tightly that we would not allow a release version throwing exceptions.
}

I'll say that it mostly means that "almost nobody" writes the code which really needs these things nor bothers with any other exception handling than showing own message about exception and exiting, avoiding final "Send all your data crash report to the moon you know where" OS' dialog.
Really, there are much tasks which may require handling of planned exceptions, and that would not be a flaw in the program design nor the flaw of programmer's competency, it will instead be part of design, the right feature.
As a simple example - catching an In-page I/O exception (C0000006H) when one is reading the huge sparse memory-mapped file from the disk where there is no much free space to hold that file if it would have been not sparse.

jj2007

Quote from: Antariy on May 05, 2013, 12:43:24 PM
Quote from: jj2007 on May 05, 2013, 08:58:54 AM
We have several macros for SEH, e.g. mine - but almost nobody uses them. Because we control our code so tightly that we would not allow a release version throwing exceptions.

As a simple example - catching an In-page I/O exception (C0000006H) when one is reading the huge sparse memory-mapped file from the disk where there is no much free space to hold that file if it would have been not sparse.

Alex,

You are right, of course SEH has its legit uses. Thanks for the example.

But in 99% of all cases you can live without SEH, or limit it to a subproc. The OS calls them exceptions because they should be exceptional events.

However, it seems to be extremely widespread in C/C++ programming to a) install an SEH right at the beginning and b) deliberately raise exceptions for little errors that could have been avoided by simple error checking, or fixed in more benign ways.

Somebody will surely pop up with a good theory why computer science requires that there must be a mov fs:[0], esp at line 7 of the disassembly, but a) all of my BASIC compilers could live comfortably without SEH and b) my suspicion is that users of products of certain respected big software companies didn't like those ugly message boxes, so the marketing department asked for SEH... ;-)

Antariy

Jochen, now I agree with you totally :biggrin:

Manos

I tested three functions that do the same work, using MASM.

1). The Win API lstrlen
2). The Hutch's library StrLen
3). The strlen of MSVCRT.LIB that I have in my System, (WinXP).

Follow are the source and the results:

includelib \MSVCRT.LIB
strlen PROTO C pstr:DWORD

LOCAL dwTime:DWORD

invoke GetTickCount
      mov dwTime, eax
      push esi
      xor esi, esi
      TestLoop:
         ;   invoke lstrlen, addr szText
         ;   invoke StrLen, addr szText   
      invoke strlen, addr szText
      inc esi
      cmp esi, 10000000
      jb TestLoop
   
   pop esi   
      
   invoke GetTickCount
   sub eax, dwTime
   PrintDec eax


Results:
lstrlen 328 ticks
StrLen 94 ticks
strlen 94 ticks


Manos.



jj2007

Ok, once more...

Intel(R) Celeron(R) M CPU        420  @ 1.60GHz (SSE3)
loop overhead is approx. 17/10 cycles

2510    cycles for 10 * lstrlen
972     cycles for 10 * StrLen
1450    cycles for 10 * crt_strlen
371     cycles for 10 * Len

2512    cycles for 10 * lstrlen
972     cycles for 10 * StrLen
1515    cycles for 10 * crt_strlen
371     cycles for 10 * Len

2510    cycles for 10 * lstrlen
971     cycles for 10 * StrLen
1405    cycles for 10 * crt_strlen
371     cycles for 10 * Len

Gunther

Jochen,

you gave the right answer. :t All these HLL vs Assembly discussion (I've seen a lot over the years) are a bit fruitless. Here are my results:

Quote
Intel(R) Core(TM) i7-3770 CPU @ 3.40GHz (SSE4)
loop overhead is approx. 28/10 cycles

1940   cycles for 10 * lstrlen
544   cycles for 10 * StrLen
1367   cycles for 10 * crt_strlen
169   cycles for 10 * Len

1987   cycles for 10 * lstrlen
570   cycles for 10 * StrLen
784   cycles for 10 * crt_strlen
172   cycles for 10 * Len

2558   cycles for 10 * lstrlen
557   cycles for 10 * StrLen
1367   cycles for 10 * crt_strlen
174   cycles for 10 * Len

100   = eax lstrlen
100   = eax StrLen
100   = eax crt_strlen
100   = eax Len

--- ok ---

Gunther
You have to know the facts before you can distort them.

Manos

Quote from: Gunther on May 05, 2013, 10:34:28 PM
Jochen,

you gave the right answer. :t All these HLL vs Assembly discussion (I've seen a lot over the years) are a bit fruitless. Here are my results:

--- ok ---

Which crt_strlen you used ?

Manos.