Someone Told Me: Is C an Assembly Language

C

clusardi2k

Years ago, someone told me once that C is assembly language. Is this true. Do you have any proof why or why not.

Thanks,
 
I

Ian Collins

Years ago, someone told me once that C is assembly language. Is this
true. Do you have any proof why or why not.

Read through all of the dozens (if not hundreds) of similar trolls for
your answer.
 
K

Keith Thompson

Years ago, someone told me once that C is assembly language. Is this
true. Do you have any proof why or why not.

No, C is not an assembly language.

Assembly language programs specify CPU instructions.
C programs specify behavior.
 
J

James Kuyper

Years ago, someone told me once that C is assembly language. Is this true. Do you have any proof why or why not.

The answer to this depends upon what you mean by "assembly language".
Wiktionary says "(computing) A programming language in which the source
code of programs is composed of mnemonic instructions, each of which
corresponds directly to a machine instruction for a particular processor."

This definition is completely consistent with every use I'd ever seen of
the term until quite recently, including all three assembly languages
I've programmed in. It does not fit C at all. C is not oriented to a
particular processor, and does not specify the machine instructions to
be generate. It only specifies what the machine instructions must do; it
is perfectly legal for a C compiler to generate any sequence of machine
instructions that produces the specified result, and what the C standard
fails to mandate allows a great many alternative ways of translating any
particular C program into machine instructions.

However, the last time I ever programmed in assembly language was two
decades ago. I've recently been informed that the distinction between
modern assembly languages and higher level languages has become so fuzzy
as to have pretty much completely disappeared. The person who said this
claimed that modern assembly languages no longer implement a one-to-one
relationship between assembly language instructions and machine language
instructions, but are free to choose from a wide variety of possible
translations. Also, he claimed that modern assembly languages are no
longer restricted to a particular processor, that the same assembly code
can be used to generate different machine code on different platforms,
even if they have significantly different architectures. On the basis of
that claim, he asserted that, since the same was true of C, C could
therefore be classified as an assembly language. To me, it would seem
more reasonable to say that the languages he described (if he was
describing them correctly) were now high level languages, and no longer
assembly languages.
 
K

Keith Thompson

James Kuyper said:
The answer to this depends upon what you mean by "assembly language".
Wiktionary says "(computing) A programming language in which the source
code of programs is composed of mnemonic instructions, each of which
corresponds directly to a machine instruction for a particular processor."

This definition is completely consistent with every use I'd ever seen of
the term until quite recently, including all three assembly languages
I've programmed in. It does not fit C at all. C is not oriented to a
particular processor, and does not specify the machine instructions to
be generate. It only specifies what the machine instructions must do; it
is perfectly legal for a C compiler to generate any sequence of machine
instructions that produces the specified result, and what the C standard
fails to mandate allows a great many alternative ways of translating any
particular C program into machine instructions.

However, the last time I ever programmed in assembly language was two
decades ago. I've recently been informed that the distinction between
modern assembly languages and higher level languages has become so fuzzy
as to have pretty much completely disappeared. The person who said this
claimed that modern assembly languages no longer implement a one-to-one
relationship between assembly language instructions and machine language
instructions, but are free to choose from a wide variety of possible
translations. Also, he claimed that modern assembly languages are no
longer restricted to a particular processor, that the same assembly code
can be used to generate different machine code on different platforms,
even if they have significantly different architectures. On the basis of
that claim, he asserted that, since the same was true of C, C could
therefore be classified as an assembly language. To me, it would seem
more reasonable to say that the languages he described (if he was
describing them correctly) were now high level languages, and no longer
assembly languages.

I remember that discussion, but not all the details of it. As I
recall, the person making that claim, when repeatedly pressed for
concrete examples, backed away from it.

Still, the Wiktionary definition ignores the macro processing
available in many assemblers.

My definition, given elsethread, is that an assembly language program
specifies a sequence of CPU instructions; it needn't necessarily
do so on a one line to one instruction basis.
 
G

glen herrmannsfeldt

The answer to this depends upon what you mean by "assembly language".
Wiktionary says "(computing) A programming language in which the
source code of programs is composed of mnemonic instructions,
each of which corresponds directly to a machine instruction for a
particular processor."

Well, if you include macros, then that hasn't been strictly true
for many years now.
This definition is completely consistent with every use I'd ever seen of
the term until quite recently, including all three assembly languages
I've programmed in. It does not fit C at all. C is not oriented to a
particular processor, and does not specify the machine instructions to
be generate. It only specifies what the machine instructions must do; it
is perfectly legal for a C compiler to generate any sequence of machine
instructions that produces the specified result, and what the C standard
fails to mandate allows a great many alternative ways of translating any
particular C program into machine instructions.

That is true. However, if you allow conversions between pointers
and integers, then you can do many operations that would otherwise
need to be done in assembly language. Conveniently, doing that tends
to make the C code machine dependent.
However, the last time I ever programmed in assembly language was two
decades ago. I've recently been informed that the distinction between
modern assembly languages and higher level languages has become so fuzzy
as to have pretty much completely disappeared. The person who said this
claimed that modern assembly languages no longer implement a one-to-one
relationship between assembly language instructions and machine language
instructions, but are free to choose from a wide variety of possible
translations. Also, he claimed that modern assembly languages are no
longer restricted to a particular processor, that the same assembly code
can be used to generate different machine code on different platforms,
even if they have significantly different architectures. On the basis of
that claim, he asserted that, since the same was true of C, C could
therefore be classified as an assembly language. To me, it would seem
more reasonable to say that the languages he described (if he was
describing them correctly) were now high level languages, and no longer
assembly languages.

I haven't actually used it, but there is an assembler for the
descendants of OS/360 that IBM calls "High Level Assembler."

For many years, people have been writing macros to help users by making
assembly lanugage look more like a high level language. For example,
macros to generate IF/THEN/ELSE structures or DO/WHILE. Macros that
keep track of nesting level and such. And assemblers have supplied more
and more complicated macro processing facilities, including the
evaluation of expressions, and conditional assembly based on those
expressions.

Even some small deviations from the strict definition have been needed
for some time. Some systems use different branch instructions for near
addresses from not so near. It is convenient to allow the assembler to
select the appropriate instruction when the offset is known.

Some C compilers allow for inline assembly code. That is, you can
mix C statements and assembly instructions in the same program.
That tends to work, as in enough cases one can predict the instructions
that the compiler will generate well enough that registers and symbolic
addresses are consistent.

I was some time ago writing in Dynamic C (that is the name of the
compiler) for the Rabbit (descendant of the Z80) processor. It is very
easy to switch between assembler and C, and there are few enough
registers that you always know what is where. You can, for example,
easily write a C for loop where the loop body contains assembler
instructions. Trust the C compiler to do the loop right, and code
exactly what you need inside the loop. C variables can be referenced
in the usual way as symbolic names in the assembler.

The real answer is that, no, C is not assembler but often it is close
enough that it can be used that way.

-- glen
 
G

glen herrmannsfeldt

To see what can actually be done in the range between high level
languages and assembly language, consider PL/360.

PL/360 was designed by Niklaus Wirth around 1968. It has a structure
similar to PL/I, but in operation, it is more like a S/360 assembler.

It allows one to forget about some of the complications of writing
machine instructions in symbolic form, but not all of them.

R1:=R2;

copies the value from machine register 2 to machine register 1,
easy enough.

R2:=R2+R2;

doubles the value in register 2.

R2:=R2+R2+R2;

quadruples the value in register 2. Surprised?

LR R2,R2
AR R2,R2
AR R2,R2

note that unlike most high-level languages, the whole expression is not
evaluated before changing the left side of the assignment operator.

But then C programmers know that sometimes you have to be careful about
when variables get updated, too.

-- glen
 
C

clusardi2k

So trying to sum all this up, the question of whether or not C is an assembly language is currently no!

Am I correct in my "no" assumption, or is it a more appropriate answer to say yet to be determined via a mutually agreed apon definition.

Is this question just an academic one.

Thanks,
 
B

BartC

So trying to sum all this up, the question of whether or not C is an
assembly language is currently no!

Am I correct in my "no" assumption, or is it a more appropriate answer to
say yet to be determined via a mutually agreed apon definition.

You wouldn't be far wrong in saying 'no'.

Try some actual C compilers, see if there is an option to generate assembly
code (for example, the -S option with gcc). Then look at this output, and
see if it bears any resemblance to the original source.

This assembly output is what people are trying to avoid by writing C code
instead.
 
J

James Kuyper

On 04/02/2013 09:06 PM, Keith Thompson wrote:
....
I remember that discussion, but not all the details of it. As I
recall, the person making that claim, when repeatedly pressed for
concrete examples, backed away from it.

That discussion was so fresh in my memory that I was surprised to find
it occurred nearly two years ago. "He" was Rui Maciel, and the thread
Subject: was "for your languages". Rui never backed down from his claim,
he just failed to respond to requests for concrete examples.

My own understanding is that the purpose of an assembly language is to
provide a convenient mechanism for specifying the precise sequence of
machine language instructions to be generated, which is therefore
inherently platform dependent. Macros are merely a convenient way of
packaging specification of a large number of instructions into one
piece. An assembler that produces a different sequence of machine
instructions from the one specified, is defective. Assembly code
intended for one platform cannot be usefully ported to a radically
different platform, precisely because, by "radically different", I mean
a platform for which a wildly different sequence of machine code
instructions would be needed to generate the same desired behavior.

One of the key purposes for higher level languages like C is to avoid
having to specify the precise sequence of machine language instructions.
Instead, C code specifies only the desired behavior, and leaves it up
to the implementation to decide which machine language instructions to
generate. The same C code can be used to generate many different
sequences of machine code, without rendering the implementation
non-conforming, so long as all of those sequences implement the
specified behavior. C compilers for wildly different platforms will
produce wildly different sequences of machine language instructions,
that implement the same behavior - producing that result is precisely
one of the purposes for designing higher level languages like C.

Rui claimed (but never provided a concrete example) that in modern
usage, "macro assembly language" is used to refer to things that I would
call a "high level language", and that things that I would consider it
proper to call "assembly languages" had become obsolete so long ago that
had never existed during his career. He pointed out that typical C
implementations deterministically generate specific sequences of machine
language instructions when given a specific C program as input, and
therefore concluded it was appropriate to call C an assembly language,
despite the fact that different C compilers had different deterministic
mappings, without ceasing to be conforming. Also, the determinism of the
process was merely a convenience, and is not required of a conforming
implementation of C - that didn't faze him, either.
 
G

glen herrmannsfeldt

James Kuyper said:
On 04/02/2013 09:06 PM, Keith Thompson wrote:
That discussion was so fresh in my memory that I was surprised to find
it occurred nearly two years ago. "He" was Rui Maciel, and the thread
Subject: was "for your languages". Rui never backed down from his claim,
he just failed to respond to requests for concrete examples.
My own understanding is that the purpose of an assembly language is to
provide a convenient mechanism for specifying the precise sequence of
machine language instructions to be generated, which is therefore
inherently platform dependent.

Yes, but why do you want to do that? Years (decades) ago it was for
speed or size (or both), but those reasons are now long gone for
most systems. Maybe still true for some embedded systems, though.
Macros are merely a convenient way of
packaging specification of a large number of instructions into one
piece. An assembler that produces a different sequence of machine
instructions from the one specified, is defective. Assembly code
intended for one platform cannot be usefully ported to a radically
different platform, precisely because, by "radically different", I mean
a platform for which a wildly different sequence of machine code
instructions would be needed to generate the same desired behavior.

But it is hard to get a wildly different system into the market.

There is in another newsgroup a discussion on Itanium. That is wildly
different, and close to impossible to write assembly code for.
Even more than RISC, it is designed for compiler generated code.
One of the key purposes for higher level languages like C is to avoid
having to specify the precise sequence of machine language instructions.
Instead, C code specifies only the desired behavior, and leaves it up
to the implementation to decide which machine language instructions to
generate. The same C code can be used to generate many different
sequences of machine code, without rendering the implementation
non-conforming, so long as all of those sequences implement the
specified behavior. C compilers for wildly different platforms will
produce wildly different sequences of machine language instructions,
that implement the same behavior - producing that result is precisely
one of the purposes for designing higher level languages like C.

And with not so much extra work, one can write much of the machine
dependent code in C, too. With memory mapped I/O, you can write low
level I/O routines in C. With a little help from the compiler, even
interrupt routines.
Rui claimed (but never provided a concrete example) that in modern
usage, "macro assembly language" is used to refer to things that I would
call a "high level language", and that things that I would consider it
proper to call "assembly languages" had become obsolete so long ago that
had never existed during his career.

For many years, it was assumed that operating systems and compilers
would be in assembler. Seems to me that C was a big part in changing
that assumption.
He pointed out that typical C
implementations deterministically generate specific sequences of machine
language instructions when given a specific C program as input, and
therefore concluded it was appropriate to call C an assembly language,
despite the fact that different C compilers had different deterministic
mappings, without ceasing to be conforming. Also, the determinism of the
process was merely a convenience, and is not required of a conforming
implementation of C - that didn't faze him, either.

Well, as often noted here, C only produces machine independent results
if one follows the rules carefully. It is not at all hard to write C
code that is dependent on the underlying representation of integers,
such as twos complement, or the endianness. For a long time now,
compilers have been about as good as good assembly coders are generating
fast and compact code. Most of the assembly code that I have written in
recent years is the two instruction program for RDTSC (read time stamp
counter) in IA32. (Conveniently the result goes in the right registers
for a function result on most IA32 systems.) So far, I don't know any
C compilers that will do it.

-- glen
 
G

glen herrmannsfeldt

So trying to sum all this up, the question of whether or not C
is an assembly language is currently no!

I would say so, but mostly in the same sense that, in Calculus
when you do a limit you get closer and closer but never actually
get there. There are very few things that need to be done, and can't
be done in C, but there are still some.

Now, interestingly, as I understand it in some of the IBM mainframe
systems there are things that can be done in C, but not in assembler.
Not related to machine instructions, but in information passed onto
the linker.
Am I correct in my "no" assumption, or is it a more appropriate
answer to say yet to be determined via a mutually agreed apon
definition.

It might be that for some machines that it is easier to write the C
compiler than the assembler. Or, as above, features are added earlier
to a C compiler than to an assembler. If that happens often enough,
then the answer in some cases could be yes.
Is this question just an academic one.

-- glen
 
J

Johannes Bauer

I would say so, but mostly in the same sense that, in Calculus
when you do a limit you get closer and closer but never actually
get there. There are very few things that need to be done, and can't
be done in C, but there are still some.

C is a Turing complete language. It is as powerful as the assembly code
language that lies beneath it. Thus all tasks can be achieved in both
languages.
Now, interestingly, as I understand it in some of the IBM mainframe
systems there are things that can be done in C, but not in assembler.
Not related to machine instructions, but in information passed onto
the linker.

That's like saying "some things can't be done in assembly language, like
writing a business letter in Word format". It doesn't make sense.
"Information passed onto the linker" is just some arbitrary container
constraint with no relevance to the actual power of the language itself.
It might be that for some machines that it is easier to write the C
compiler than the assembler. Or, as above, features are added earlier
to a C compiler than to an assembler. If that happens often enough,
then the answer in some cases could be yes.

You can invent a machine that magically "executes" C-code as its native
language, sure. It would be a completely pointless acedemic exercise,
but, yes, this could be done. Such a machine would essentially "compile"
code at runtime (i.e. parse and transform into smaller pieces,
"assembly" instructions).

However, all machines that we see today execute some form of machine
language which has a 1:1 mapping onto assembly language. It's only a
*representation* that is easy for humans to read, i.e. it says "nop"
instead of "0x90" and it says "int3" instead of "0xcc". That's why it's
absolutely trivial to write an assembler, but very much harder to write
a compiler.

Best regards,
Johannes

--
Zumindest nicht ?ffentlich!
Ah, der neueste und bis heute genialste Streich unsere gro?en
Kosmologen: Die Geheim-Vorhersage.
- Karl Kaos ?ber R?diger Thomas in dsa <[email protected]>
 
K

Keith Thompson

So trying to sum all this up, the question of whether or not C is an
assembly language is currently no!

Am I correct in my "no" assumption, or is it a more appropriate answer
to say yet to be determined via a mutually agreed apon definition.

Is this question just an academic one.

I know of no reasonable definition of the phrase "assembly language" for
which C qualifies. There are any number of possible definitions of
concepts of which C might be an example, but "assembly language" is not
a reasonable name for any such concept.

C is in some sense "closer" to assembly language than many other
programming languages, and is often used in contexts for which an
assembly language might be useful.

The question is really about the definition of the phrase "assembly
language", not about what C is.
 
L

Les Cargill

glen said:
I would say so, but mostly in the same sense that, in Calculus
when you do a limit you get closer and closer but never actually
get there. There are very few things that need to be done, and can't
be done in C, but there are still some.

Now, interestingly, as I understand it in some of the IBM mainframe
systems there are things that can be done in C, but not in assembler.
Not related to machine instructions, but in information passed onto
the linker.


If it's just info passed to the linker, I bet there's a way
to do it in assembler, too.
 
J

James Kuyper

Yes, but why do you want to do that? ...

I don't. The people who do want to do that are are people who think,
correctly or incorrectly, that they know precisely which sequence of
machine language instructions they want generated, and therefore don't
want to rely upon a compiler for a higher level language that might
produce a different sequence. I've been in that situation before, but
not very often, and not at any time in the last couple of decades.

People who are very concerned with micro-optimization show up in this
newsgroup all the time, and seem disappointed by the fact that C is NOT
a high-level assembly language that they can use to force precisely
their desired sequence of machine code to be generated. This suggests to
me that the desire to control such things hasn't disappeared, though it
might be the case that the desire has become less well justified in
recent decades.
... Years (decades) ago it was for
speed or size (or both), but those reasons are now long gone for
most systems. Maybe still true for some embedded systems, though.

Other reasons, which you might also dismiss as "long gone", include
wanting to access hardware features for which the higher level language
you would otherwise want to use doesn't provide a hook. When a higher
level language does provide such a hook, it's often implemented in
assembly language (or at least, that was true back when I did write
assembly language), so it's still assembly language in the end.
 
K

Keith Thompson

James Kuyper said:
On 04/02/2013 09:06 PM, Keith Thompson wrote:
...

That discussion was so fresh in my memory that I was surprised to find
it occurred nearly two years ago. "He" was Rui Maciel, and the thread
Subject: was "for your languages". Rui never backed down from his claim,
he just failed to respond to requests for concrete examples.

In a later thread (May 2012), subject "How would you design C's
replacement?", I restated my contention about the difference between
assembly language and non-assembly language. He agreed with me --
which seemed to me to be a complete contradiction of his previous
claims.

Message-ID: <[email protected]>
https://groups.google.com/group/com...c?dmode=source&output=gplain&noredirect&pli=1

I wrote:
I disagree. In my opinion (and I'm not 100% certain that this is
standard terminology), the distinction between an assembly language
and a non-assembly language is fairly unambiguous. As I said
upthread, an assembly language program specifies CPU instructions; a
program in a non-assembly language, including C, specifies run-time
behavior.

He replied:
I don't believe you are wrong; quite the opposite, in fact. The
only issue I have is that if we consider that assembly code with
macros is also assembly code, as is assembly code which calls
routines stored in a library, then we accept that at least a certain
amount of abstraction, one which takes us away from specifying
instructions and leads us to specify run-time behaviour, is also
compatible with the concept of an assembly language. This is the
grey territory I was referring to.

[snip]
 
K

Keith Thompson

glen herrmannsfeldt said:
Yes, but why do you want to do that? Years (decades) ago it was for
speed or size (or both), but those reasons are now long gone for
most systems. Maybe still true for some embedded systems, though.

There's a wide range of embedded systems these days. Some that
I've worked on are programmed in C, C++, and Java -- but then
they're running a full operating system. For smaller systems,
say ones running on 8051 processors, I suspect assembly language
is still appropriate.

And many compilers generate assembly language which is then assembled to
machine code. (Others generate machine code directly.)

Finally, there are still some things that are difficult to specify in C,
such as handling CPU condition flags. Try writing *portable* C code
that tells you whether multiplying two given int values will overflow.

[...]
 
K

Keith Thompson

glen herrmannsfeldt said:
I would say so, but mostly in the same sense that, in Calculus
when you do a limit you get closer and closer but never actually
get there. There are very few things that need to be done, and can't
be done in C, but there are still some.

Now, interestingly, as I understand it in some of the IBM mainframe
systems there are things that can be done in C, but not in assembler.
Not related to machine instructions, but in information passed onto
the linker.


It might be that for some machines that it is easier to write the C
compiler than the assembler. Or, as above, features are added earlier
to a C compiler than to an assembler. If that happens often enough,
then the answer in some cases could be yes.

You seem to be suggesting that the definition of "assembly language" is
related to how it's used.

IMHO, even if C happens to be the lowest level language available on a
given platform, a language in which you can do things you can't (easily)
do in any other way, that doesn't make it an assembly language.
 
G

glen herrmannsfeldt

(snip, I wrote)
Other reasons, which you might also dismiss as "long gone", include
wanting to access hardware features for which the higher level language
you would otherwise want to use doesn't provide a hook. When a higher
level language does provide such a hook, it's often implemented in
assembly language (or at least, that was true back when I did write
assembly language), so it's still assembly language in the end.

Yes, but when those appear I write a C callable routine to
do just that function and nothing else.

-- glen
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top