[comp.lang.c] C vs assembler, or, Here We Go Again

chris@mimsy.UUCP (04/19/87)

In article <658@edge.UUCP> doug@edge.UUCP (Doug Pardee) writes:
>A C program is no more readable to a C programmer than an assembler
>program is to an assembler programmer.  Ditto for maintainability.

Probably true; yet, as has been pointed out, `understandability'
appears to be a linear function of size as well, and equivalent C
and assembly programs tend to differ in size.  Usually the C code
is substantially shorter.  To put it another way, the C program
somehow represents a longer, and therefore less maintainable,
assembly program.

>I'd like to see some studies on this.

I cannot say why I think this, but I think the studies were on
FORTRAN and Algol.

>I'd believe it for languages like FORTRAN, COBOL, and Ada which prevent
>the programmer from making really stupid mistakes like not being able
>to tell a string literal from an array of characters,

(In C, a string literal *is* an array of characters; there is no point
in trying to tell the two apart.  In my experience, this has not been
a problem.)

>or arithmetic overflow/divide-by-zero/floating point overflow/underflow,

FORTRAN does not protect programmers from these:

	PROGRAM FOO
	REAL A, B
	A = 1E+35
	B = 1E-35
	A = A / B
	STOP
	END

breaks quite nicely.  (I have used neither COBOL nor Ada [sigh of
relief :-) ], and cannot say what they do or do not provide.)

>or the infamous "if (x=y)" type of stuff that C allows.

(Suitably smart versions of lint complain about these.)

>C is often used in applications where it is a poor fit,

True.

>Furthermore, C is more difficult to debug than assembler, because (like
>all other high-level languages) it is distanced from the machine.  To
>debug C you either need to know assembler, and to debug it at the assembler
>level, or you need a symbolic debugger.

Both of these assertions are ludicrous.  C is no more difficult to
debug than any other language.  Certainly, symbolic debuggers help.
I would not want to work without one: not in C, not in assembly.
If you mean to say that symbolic assembly debuggers are more common
than symbolic C debuggers, well, perhaps so.  But I will say that
any C programmer should spot the bug in the following immediately:

	f()
	{
		int a[10], i;

		for (i = 0; i <= 10; i++)
			a[i] = i;
		...
	}

>A lot of systems don't *have* symbolic debuggers, or the ones they
>have are not full-functioned.  And I haven't seen one yet that will
>allow a C programmer to make a patch to the code *in C*.

I dare say you have not looked hard enough.  They are rare, but (if
you will accept C interpreters) they do exist.

>I'm not saying that you personally (whoever you may be) are marginally
>competent.  I *am* saying that if you restrict yourself to the C
>programming job market, you will be competing with a lot of bozos
>who are willing to work for peanuts (hey, it beats flipping burgers
>for a living!).  And in return for this limited pay, you will get
>to maintain the programs those bozos wrote.  If you don't like it,
>the boss can dump you and hire another bozo; he's got 2 dozen
>resumes on file.  *That's* what I mean about BIC lighter programmers.

But I can often, after a moment of search, point into the middle
of a routine and say `there is the bug': and this distinguishes me
from your BIC lighter programmer.  The smart boss recognises this,
and pays more to or otherwise compensates the competent programmer.
Of course, this same competent programmer is more than likely fluent
in many computer languages, or able to pick them up quickly, and
hence need not restrict {him, her, it}self to C.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
UUCP:	seismo!mimsy!chris	ARPA/CSNet:	chris@mimsy.umd.edu

stuart@bms-at.UUCP (Stuart D. Gathman) (04/24/87)

While I have posted articles defending well written (macro) assembler
code as being just as compact and readable as 'C', I would now like to
explain the many advantages that 'C' provides over assembler.

1)	portability.  (Need I say more?)

2)	type checking.  I can make lots of nifty macros to handle specific
	data types, but the assembler could care less if I use DD (divide
	doubleword) on a word operand.

3)	scope rules.  In 'C' I can put in a block of code with its own
	variables guarranteed not to conflict with the rest of the program.
	With assembler, only seperately compiled modules provide private
	variables.

4)	expression syntax, especially pointer expressions.  Nothing beats
	p->b.t->x instead of sequences of move statements.  To be fair,
	I end up using lots of pointer variables in assembler for intermediate
	pointer results which tends to optimize the code as well as make it
	more readable.  Nevertheless . . .

Despite this, our people can still turn out a full featured  data
entry  program using assembler in only 15 minutes as opposed to 2
hrs for 'C'.  The difference is that  our  'C'  library  has  not
evolved  to  the  extent  that  the  assembler  library has.  (An
assembler data entry program consists of some  table  definitions
via macros and some subroutine hooks to implement deviations from
standard features.)
-- 
Stuart D. Gathman	<..!seismo!dgis!bms-at!stuart>

greg@utcsri.UUCP (04/27/87)

In article <382@bms-at.UUCP> stuart@bms-at.UUCP (Stuart D. Gathman) writes:
>hrs for 'C'.  The difference is that  our  'C'  library  has  not
>evolved  to  the  extent  that  the  assembler  library has.  (An
>assembler data entry program consists of some  table  definitions
>via macros and some subroutine hooks to implement deviations from
>standard features.)

>Stuart D. Gathman	<..!seismo!dgis!bms-at!stuart>

So could a 'C' data entry program (especially if ANSI decides to allow
proper compile-time initialization of unions). Few languages allow you
to create tables of pointers to functions, e.g., and many languages
(most notably standard Pascal) do not allow any kind of table to be created
at compile time.

Stuart's application is just right for one of what Brian Kernighan calls
'little languages'. It would read a special description language and
produce the tables as output. Of course this is not always worth doing,
and the macros may be good enough.

-- 
----------------------------------------------------------------------
Greg Smith     University of Toronto      UUCP: ..utzoo!utcsri!greg
Have vAX, will hack...

jda@mas1.UUCP (James Allen) (05/01/87)

My $0.02 for the Assembly vs C discussion--

First penny)
	Some control flow techniques -- in particular coroutine
linkage -- are inconvenient in C but achieved elegantly in assembly.
(see JSR_return_address_in_register discussion in another
newsgroup.) To avoid a proliferation of global variables
and/or "gotos" I have seen multitasking:

	pipe (questions), pipe (answers);
	if (fork ())
		get_questions ();
	else
		get_answers ();

used where an assembly language programmer would have invented
coroutines even if he'd never heard of them.  Admittedly
the multitasking design may be more readable; the point is
that the assembly-level option is not readily available in C.
(Ada is better here, although facilities like longjmp extend the
range of control flow techniques of C.)

Second Penny)
	I recently implemented a 68000 OS in C.  The amount of assembly
coding was insignificant.  One interesting anecdote:

	#define	DSK_SEL	*(char *)0xf12345  /* WRITE but dont READ */
		DSK_SEL = 0;

caused a parity error and had to be replaced with
		temp = 0; DSK_SEL = temp;

The code generated was CLR.B and MOV.B respectively.  Can anyone
elucidate?  Notice that here the assembly language programmer might
well have fallen into the same trap as the C compiler.

James D. Allen

doug@edge.UUCP (Doug Pardee) (05/06/87)

> 	#define	DSK_SEL	*(char *)0xf12345  /* WRITE but dont READ */
> 		DSK_SEL = 0;
> 
> caused a parity error and had to be replaced with
> 		temp = 0; DSK_SEL = temp;
> 
> The code generated was CLR.B and MOV.B respectively.  Can anyone
> elucidate?  Notice that here the assembly language programmer might
> well have fallen into the same trap as the C compiler.

The assembly language programmer who isn't too experienced on the 68000 might
indeed have fallen into the same trap.  Those who have spent a few months
working with the little bugger are aware of the note hidden at the bottom of
the page which describes the CLR instruction:
  Note:  A memory destination is read before it is written to.

And those very experienced in 68000 assembly don't use CLR much anyway; for
data registers MOVEQ is faster for double-word and EOR.x is faster for word
and byte.  For memory operands, a simple MOVE.x #0,loc is as fast or faster
for all operand sizes, addressing modes, and chips.  The CLR does take more
code space, though.  Oh, and to clear an address register, SUBA.L An,An.

How about we move any further discussion of assembly stuff to comp.lang.misc,
and leave this group for C?
-- 
Doug Pardee -- Edge Computer Corp., Scottsdale, AZ -- ...!ihnp4!mot!edge!doug