[comp.lang.c] Portable "asm"

pardo@june.cs.washington.edu (David Keppel) (02/22/88)

In article <915@PT.CS.CMU.EDU> edw@IUS1.CS.CMU.EDU (Eddie Wyatt) writes:
>>  - we should assume that compilers for this language are going to
>>    do a great deal of optimisation; in particular, they will optimise
>>    across entire compilations, not just single files.
>
>    Which brings up a question, what happens to the asm statement then.
>If you have the write you code such that you have no idea
>where variables are stored, how can you reliable use assemble statement
>that play with storage.  I think the conclusion will be trash asm.

I think not.  I think it will be to change the semantics of asm into a
varargs function (which may even have the register allocator at its
disposal?):

    void
dumb_function( doit_to )
    int		*splat;
{
    enum Labels { START = 1, LOOP, DONE };
    extern int	splodge;
    int		r1, r2;

    _reg_alloc(2);
    asm( START, "movl", ADDR, &splodge, REG, r1 = _register() );
    asm( 0, "clrl", REG, r2 = _register() );
    asm( LOOP, "tstl", REG, r2 );
    asm( 0, "bgeq" LAB, DONE );
    asm( 0, "addl", ADDR, sizeof( some_type ), REG, r1 );
    asm( 0, "subl", ADDR, sizeof( some_type ), ADDR, splat );
    asm( 0, "brb", LOOP );
    asm( DONE, NULL );
    _reg_unalloc();
    /* r1 is just thrown away ... */
}

Alternatively, the opcode could specify the format of the arguments that
it takes (much as printf works), but I think this is unnatural, since if
you had a bunch of typedefs, you couldn't just do:

#ifdef VAX
#define	ADD	"addl"
#else
#define ADD	"add"
#endif

(or something slightly less sick, but I hope this puts the idea across).

No, I haven't thought to closely about this, there may be some fatal flaw.
The worst thing is that this is almost portable ;->

	;-D on  (Well, C is just portable SNOBOL ;-)  Pardo

cik@l.cc.purdue.edu (Herman Rubin) (02/22/88)

In article <4257@june.cs.washington.edu>, pardo@june.cs.washington.edu (David Keppel) writes:
> In article <915@PT.CS.CMU.EDU> edw@IUS1.CS.CMU.EDU (Eddie Wyatt) writes:
> >>  - we should assume that compilers for this language are going to
> >>    do a great deal of optimisation; in particular, they will optimise
> >>    across entire compilations, not just single files.
> >
> >    Which brings up a question, what happens to the asm statement then.
> >If you have the write you code such that you have no idea
> >where variables are stored, how can you reliable use assemble statement
> >that play with storage.  I think the conclusion will be trash asm.

If we have the compiler replace names by locations (register and/or memory)
of the variables used, there is no more problem with global optimization
than before.  In fact, we should do this in C; it is not prohibited by the
language standards, and it certainly makes more sense to be able to write
assembler statements in which the location of the variable is inserted by
the compiler.

Most of the C compilers I know do not do this; it is at the least annoying
not to be able to write such things as

	asm("	addl	x,y,z");
	asm("	addwc	u,v,w");

and have the compiler include those location for the variables.  (What I do
is to first compile as above and then edit, but it does not always work.)
We also should get rid of those quotes in the process; since asm is a reserved
operator, and its structure requires that what follows starts with ("
and ends with "), while the parentheses may be useful as separators, the
quotes are totally unnecessary (and have been known to cause errors).
-- 
Herman Rubin, Dept. of Statistics, Purdue Univ., West Lafayette IN47907
Phone: (317)494-6054
hrubin@l.cc.purdue.edu (ARPA or UUCP) or hrubin@purccvm.bitnet

henry@utzoo.uucp (Henry Spencer) (02/26/88)

> If we have the compiler replace names by locations (register and/or memory)
> of the variables used...

This does of course assume that all locations are addressable in all
instructions, which is emphatically not the case on many machines.

> We also should get rid of those quotes in the process...

What if I want to write asm("mov ')', r0")?  The quotes are a reasonable way
of keeping the syntax of the assembler entirely out of the compiler's own
syntax handling, which is a good thing, especially for portable compilers.
-- 
Those who do not understand Unix are |  Henry Spencer @ U of Toronto Zoology
condemned to reinvent it, poorly.    | {allegra,ihnp4,decvax,utai}!utzoo!henry

cik@l.cc.purdue.edu (Herman Rubin) (02/27/88)

In article <1988Feb25.203425.8925@utzoo.uucp>, henry@utzoo.uucp (Henry Spencer) writes:
> > If we have the compiler replace names by locations (register and/or memory)
> > of the variables used...
> 
> This does of course assume that all locations are addressable in all
> instructions, which is emphatically not the case on many machines.

This is another reason for the user to be able to force the compiler to put
things in registers.  The stupid compiler should not be able to force the 
user to use many instructions because it does not see the need for register
variables.  This applies also to such constructs as register pairs, triples,
etc.  Naturally, this would require some way of modifying the register number,
but so what?  This is simple, compared to the machinations that compilers 
now undertake.

Also, it is rash to assume that the programmer does not make mistakes.  If the
location types of the arguments do not work with the instruction, this is a
programming error; what are diagnostic and error messages for?

> > We also should get rid of those quotes in the process...
> 
> What if I want to write asm("mov ')', r0")?  The quotes are a reasonable way
> of keeping the syntax of the assembler entirely out of the compiler's own
> syntax handling, which is a good thing, especially for portable compilers.

Someone has posted an example where the failure was due to a " in the assembler
instruction.  It is just as easy, since C requires a ; to end a statement, to
tell the compiler that until it sees ); to continue processing for the
assembler, and to have some escape mechanism for inserting ); into the 
assembler statement.  Alternatively, if we get rid of the ;s as mandatory
terminators (which I think is a good idea), have an escape mechanism for
inserting ) in an assembler statement.  Is this worse than not being able
to put ", or even "), in an assembler statement?

-- 
Herman Rubin, Dept. of Statistics, Purdue Univ., West Lafayette IN47907
Phone: (317)494-6054
hrubin@l.cc.purdue.edu (ARPA or UUCP) or hrubin@purccvm.bitnet

franka@mmintl.UUCP (Frank Adams) (03/01/88)

Clearly, assembler statements should have been defined as:

#asm <statement>

instead of

asm("statement");

This is almost worth doing in C; I would certainly do it in D (assuming the
preprocessor is kept).
-- 

Frank Adams                           ihnp4!philabs!pwa-b!mmintl!franka
Ashton-Tate          52 Oakland Ave North         E. Hartford, CT 06108

gwyn@brl-smoke.ARPA (Doug Gwyn ) (03/03/88)

In article <2738@mmintl.UUCP> franka@mmintl.UUCP (Frank Adams) writes:
>Clearly, assembler statements should have been defined as:
>#asm <statement>
>instead of
>asm("statement");

A properly-designed system programming language should not have such
a feature at all.  (It is not guaranteed in C, either.)  The interface
between the optimized code produced for the HLL and the in-line
assembly code is quite problematic.  Also, the compiler should not be
forced to have an assembler built-in just to handle such stuff; many
compilers directly generate relocatable object code.

If there is some feature that might be worth having asm() for, for
example "rotate" instructions, then consider designing it into the
HLL.

cik@l.cc.purdue.edu (Herman Rubin) (03/03/88)

In article <7401@brl-smoke.ARPA>, gwyn@brl-smoke.ARPA (Doug Gwyn ) writes:
> In article <2738@mmintl.UUCP> franka@mmintl.UUCP (Frank Adams) writes:
> >Clearly, assembler statements should have been defined as:
> >#asm <statement>
> >instead of
> >asm("statement");
> 
> A properly-designed system programming language should not have such
> a feature at all.  (It is not guaranteed in C, either.)  

I agree with Frank on this, but I would even go farther--I would have the
asm on until turned off.  Those who believe that the language gurus can
_possibly_ anticipate how someone who understands the machine will want
to do things are either totalitarian, ignorant, or stupid.  Quite frequently
I come up with the observation that this feature can be used for something
which I, at least, did not know before.  In too many cases, I have seen that
the feature is a misfeature, that with essentially no cost much more could be
attained; this is not just true in programming.

I maintain that anyone who understands whatever computer is being programmed
for will, without effort, see situations in which the HLL concepts (any HLL)
are not the right way to do things.  This should be encouraged; progress in
programming should no be based on "thou shalt not do this because
	
	It can be done thusly (but not necessarily efficiently).

	It can get you into trouble.

	Why would anyone want to do this?"
-- 
Herman Rubin, Dept. of Statistics, Purdue Univ., West Lafayette IN47907
Phone: (317)494-6054
hrubin@l.cc.purdue.edu (ARPA or UUCP) or hrubin@purccvm.bitnet

henry@utzoo.uucp (Henry Spencer) (03/04/88)

> ... It is just as easy, since C requires a ; to end a statement, to
> tell the compiler that until it sees ); to continue processing for the
> assembler, and to have some escape mechanism for inserting ); into the 
> assembler statement...

Have you never heard of string escapes?  (If they don't work in asm()s
despite the resemblance to strings, speak to your compiler implementor
about this bug.)  Why re-invent the wheel?

Actually, my number one suggestion for D would be to avoid asm() entirely.
My C compiler doesn't support it; oddly enough, I have never missed it.
(It helps that Dennis Ritchie knew how to generate good local code.)
-- 
Those who do not understand Unix are |  Henry Spencer @ U of Toronto Zoology
condemned to reinvent it, poorly.    | {allegra,ihnp4,decvax,utai}!utzoo!henry

tanner@ki4pv.uucp (Dr. T. Andrews) (03/04/88)

Portable "asm".  Right.  All the world isn't a 68K, but all machines
have the same instruction set and registers.

Now, if I were implementing an "asm" construct, I'd probably do
something cheesy like
#asm
	Assembly code here.  Syntax as proper for local assembler.
	Be sure to enclose the "#asm" block within local #ifdef or
	be prepared for a surprise when you try to port.  May not
	be available on the compiler for the next machine you need.
#endasm

The local pre-processor (if not part of CC) needs to know how to pass
the "#asm" and "#endasm", of course.  Put it on the same list as the
thing that passes "#line" constructs.
-- 
{allegra clyde!codas decvax!ucf-cs ihnp4!codas killer}!ki4pv!tanner

daveb@geac.UUCP (David Collier-Brown) (03/04/88)

In article <7401@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>)
writes:
[re a discussion of "asm" in C]
| A properly-designed system programming language should not have such
| a feature at all.  (It is not guaranteed in C, either.)  The interface
| between the optimized code produced for the HLL and the in-line
| assembly code is quite problematic.  Also, the compiler should not be
| forced to have an assembler built-in just to handle such stuff...

    The interfaces are hard, but within state-of-practice (I hate the
idea of assembler escapes for other reasons).

    As an example, in Honeywell's experimental ADAsil (an incomplete
implementation of Ada[tm]), one could specify the interface to
either a procedure or instruction, and whether its was to be placed
inline or not.  The compiler, having been informed about the
restrictions on parameters via a pragma, arranged to do any register
allocations and transfers required to execute the code.
    Specifically, one coded system calls by producing an object file
containing the instruction (a trap), and placing the restrictions,
the request to put it in-line and the requirements in pragmas
preceding the call.  The compiler would then insert the instruction,
and make sure the registers were used properly around the
instruction.

  Yes, its hard.  But it was claimed to have been harder to write
the pragma interpreter to find out what to do than to write the
optimizer code to do it.

--dave c-b
ps: Corrections re difficulty and exact details welcome: this was some
    years ago! (Ada is old?)

-- 
 David Collier-Brown.                 {mnetor yunexus utgpu}!geac!daveb
 Geac Computers International Inc.,   |  Computer Science loses its
 350 Steelcase Road,Markham, Ontario, |  memory (if not its mind) 
 CANADA, L3R 1B3 (416) 475-0525 x3279 |  every 6 months.

boemker@hpfcdc.HP.COM (Tim Boemker) (03/08/88)

Since the interface between C and in-line asm seems to be so
problematic (not to mention non-portable), why not write
those routines that should be written in assembly in assembly?

(Please don't tell me about needing just a rotate here or there
for performance; reconsider the original partitioning of the task
and find an alternative that separates the high-level part and
the low-level part.)

(Yes, I have written separately compiled assembly routines, and
I have repartitioned tasks to find an aesthetically appealing,
efficient alternative.)

Tim Boemker

edw@IUS1.CS.CMU.EDU (Eddie Wyatt) (03/11/88)

> Since the interface between C and in-line asm seems to be so
> problematic (not to mention non-portable), why not write
> those routines that should be written in assembly in assembly?

To which the obvious reply is speed - functions invocation can be 
RELATIVELY expensive.  The time taken to invoke a subroutine may
out way any gains that the asm statement made. Disclaimer - I don't use
asm - don't plan on it either.



-- 

Eddie Wyatt 				e-mail: edw@ius1.cs.cmu.edu

boemker@hpfcdc.HP.COM (Tim Boemker) (03/12/88)

> To which the obvious reply is speed - functions invocation can be 
> RELATIVELY expensive.  The time taken to invoke a subroutine may
> out way any gains that the asm statement made. Disclaimer - I don't use
> asm - don't plan on it either.

"Relatively": true.  But if a routine is relatively large (powerful), it
is called relatively infrequently.

mcdonald@uxe.cso.uiuc.edu (03/12/88)

/* Written  4:42 pm  Mar  7, 1988 by boemker@hpfcdc.HP.COM in uxe.cso.uiuc.edu:comp.lang.c */
/* ---------- "Re: Portable "asm" (Was: The D Prog" ---------- */
Since the interface between C and in-line asm seems to be so
problematic (not to mention non-portable), why not write
those routines that should be written in assembly in assembly?

(Please don't tell me about needing just a rotate here or there
for performance; reconsider the original partitioning of the task
and find an alternative that separates the high-level part and
the low-level part.)

(Yes, I have written separately compiled assembly routines, and
I have repartitioned tasks to find an aesthetically appealing,
efficient alternative.)

Tim Boemker
/* End of text from uxe.cso.uiuc.edu:comp.lang.c */

I agree that having an "asm" statement is C is sufficiently unesthetic
that trying to get it into ANSI C is not a worthwhile crusade. What I
do consider worthwhile is for compiler vendors to have some way to do it.
Requiring subroutines for assembly defeats a major part of its
usefulness, which is efficiency. Most certainly, one can get that speed
by coding big hunks in assembler. But sometimes, I need just one or
two instructions in assembler. For example, on an IBM PC one frequently
needs to issue INT instructions, with certain values in registers, or
to issue INP or OUP instructions. Both major C compilers for the PC,
Turbo and Microsoft 5.00 DO have a mechanism for doing this. Microsoft
has some inline functions for common things, and , as the ultimate ability,
it will emit complete, legal, MASM code whcih you can diddle to your
hearts content. Turbo seems to HAVE "asm", though I haven't used it 
myself. If all compiler vendors were so nice, there would be no discussion.

john@uw-nsr.UUCP (John Sambrook) (03/15/88)

In article <1092@PT.CS.CMU.EDU> edw@IUS1.CS.CMU.EDU (Eddie Wyatt) writes:
>> [someone else]
>> Since the interface between C and in-line asm seems to be so
>> problematic (not to mention non-portable), why not write
>> those routines that should be written in assembly in assembly?
>
>To which the obvious reply is speed - functions invocation can be 
>RELATIVELY expensive.  The time taken to invoke a subroutine may
>out way any gains that the asm statement made. Disclaimer - I don't use
>asm - don't plan on it either.

If performance is critical write the whole subroutine in assembler,
not just the innermost loop.  Of course, those people who have 
"subroutines" that span 10+ pages will whine about it being "too
much work."

Further, consider that on many systems the conventions for inter-
language calling are spelled out in the system documentation and 
users are advised to conform to the standard.  Vendors agree not to
change the standard indiscriminately.  However, the code generated
by a given compiler is under no such obligation and likely to change 
whenever a new revision of the C compiler is installed.  

Maybe other people have different priorities than I do.  I'd 
consider it a tremendous waste of time to run around fixing programs
that quit working just because I installed a new version of the 
C compiler.

"If it looks like a hack, feels like a hack, smells like a hack ...
it's a hack."

Is anyone else wondering if Herman Rubin and Doug Pardee are related?  :-)

-- 
John Sambrook                        Internet: john@nsr.bioeng.washington.edu
University of Washington RC-05           UUCP: uw-nsr!john
Seattle, Washington  98195               Dial: (206) 548-4386