J
James Kuyper
(snip, I wrote)
Yes, but when those appear I write a C callable routine to
do just that function and nothing else.
Yes, that is precisely what I was talking about.
(snip, I wrote)
Yes, but when those appear I write a C callable routine to
do just that function and nothing else.
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.
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.
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.
If it's just info passed to the linker, I bet there's a way
to do it in assembler, too.
OK ... interesting challenge. I will make a try. Do not laugh.
/// will_imul_overflow.h
#include <limits.h>
#if LONG_MAX > INT_MAX
# define DOUBLE_INT long
#elif LLONG_MAX > INT_MAX
# define DOUBLE_INT long long
#else
# error "sorry, seems that will_imul_overflow can't be ported here."
#endif
inline int will_imul_overflow( int a, int b )
{
DOUBLE_INT product = (DOUBLE_INT)a * b;
return product < INT_MIN || product > INT_MAX;
}
#undef DOUBLE_INT
Öö Tiib said:OK ... interesting challenge. I will make a try. Do not laugh.
/// will_imul_overflow.h
#include <limits.h>
#if LONG_MAX > INT_MAX
# define DOUBLE_INT long
#elif LLONG_MAX > INT_MAX
# define DOUBLE_INT long long
#else
# error "sorry, seems that will_imul_overflow can't be ported here."
#endif
inline int will_imul_overflow( int a, int b )
{
DOUBLE_INT product = (DOUBLE_INT)a * b;
return product < INT_MIN || product > INT_MAX;
}
#undef DOUBLE_INT
where above gives correct result is perhaps harder?The counter-challenge to write it in assembler for all platforms >
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.
My point is that for a given assembly language, you can likely solve
the problem by performing the multiplication and then checking
some bits, or by some similar mechanism. C doesn't make such
mechanisms visible.
You could do some complicated mathemetical checks in pure C that
would tell you whether a multiplication *will* overflow before you
actually perform it, but such checks are going to be substantially
more expensive than what's available in assembly code.
(I frankly find it a bit disturbing that so many C programmers aren't
bothered by the inability to detect overflows.)
[...]
(I frankly find it a bit disturbing that so many C programmers aren't
bothered by the inability to detect overflows.)
In any case, TeX requires a system with at least 32 it integers, which
portable C doesn't.
Eric Sosman said:[...]
(I frankly find it a bit disturbing that so many C programmers aren't
bothered by the inability to detect overflows.)
In my formative years I wrote code (not in C) for machines
that ABENDed a program on integer over- and underflow. To this
day I often think C programs would be better if C didn't hide
behind "integer overflow is undefined" and instead said "integer
overflow is a capital offense, and you will rue it! SIGBANG!!!"
When I'm elected Almighty Arbiter of Automata, that's how
it'll be. Just you wait.
While you could obviously do the check in some fashion in all assembly
languages, not all ISAs include double width multiplication (or
overflow detection on multiplies).
So it may not actually be easier in assembler than in C on
some platforms.
?? Tiib said:OK ... interesting challenge. I will make a try. Do not laugh.
/// will_imul_overflow.h
#include <limits.h>
#if LONG_MAX > INT_MAX
# define DOUBLE_INT long
#elif LLONG_MAX > INT_MAX
# define DOUBLE_INT long long
#else
# error "sorry, seems that will_imul_overflow can't be ported here."
#endif
inline int will_imul_overflow( int a, int b )
{
DOUBLE_INT product = (DOUBLE_INT)a * b;
return product < INT_MIN || product > INT_MAX;
}
#undef DOUBLE_INT
Les Cargill said:[snip]
Perhaps
inline int will_imul_overflow( int a, int b )
{
const int prod = a * b;
const int nb = prod / a ;
return ( b != nb );
}
Supporting unsigned may require a little more effort.
Eric said:[...]
(I frankly find it a bit disturbing that so many C programmers aren't
bothered by the inability to detect overflows.)
In my formative years I wrote code (not in C) for machines
that ABENDed a program on integer over- and underflow. To this
day I often think C programs would be better if C didn't hide
behind "integer overflow is undefined" and instead said "integer
overflow is a capital offense, and you will rue it! SIGBANG!!!"
Keith said:Les Cargill said:[snip]On Wednesday, 3 April 2013 20:43:52 UTC+3, Keith Thompson wrote:
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.
Perhaps
inline int will_imul_overflow( int a, int b )
{
const int prod = a * b;
const int nb = prod / a ;
return ( b != nb );
}
If the multiplication overflows, the behavior is undefined.
Supporting unsigned may require a little more effort.
[...]
While I don't happen to know of such a limitation, it could well
exist, I've not encountered it, and haven't gone looking.
But the linker and assembler (and compilers) are independent programs,
just because the current assembler doesn't provide a way to use some
feature of the current linker, while an HLL does, says little about to
capabilities of either assemblers or HLLs in general.
As a non-mainframe example, MS's linker supports LTCG, and there are
certain object module entries that pertain to that (namely object
modules entries that contain the internal representation of the parsed
program, and a link to the executable compiler back end that can
process those), that cannot be generated by the assembler. In that
case a linker feature (LTCG) is not really relevant to an assembler.
A mainframe example is when C started getting popular on the
mainframe, it needed a linker enhancement to support external
identifies longer than eight characters.
Originally there was a
pre-link step that would mangle long names into short names, and then
pass the result to the traditional linker. Eventually the linker was
replaced with the binder, which supported the extended format
directly. The assembler also eventually grew long name support, but
not at the same time as the original pre-link+linker process.
But not hopelessly so...
On Wed, 03 Apr 2013 10:56:35 -0400, James Kuyper
I don't disagree, but there's nothing to prevent assemblers from
providing higher level facilities as well (macros, block structure
statements, data structures, etc.). Use of those may not be
appropriate in every situation, but may help in many, particularly in
the many non-critical bits of code.
Of course that pretty much requires that we consider an HLL that
supports inline assembler (as do most C compilers), to be an
assembler. ...
... And while such a compiler might not be a very good
assembler, I can't really see how a compiler that supports:
int main()
{
__asm{
...10,000 lines of assembler...
}
return 0;
}
isn't an assembler, no matter what else it might be.
So assemblers and HLLs are perfectly capable of intruding into each
others turf, and trying to draw a bright line is impossible.
Les Cargill said:Keith said:Les Cargill said:On Wednesday, 3 April 2013 20:43:52 UTC+3, Keith Thompson wrote:
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. [snip]
Perhaps
inline int will_imul_overflow( int a, int b )
{
const int prod = a * b;
const int nb = prod / a ;
return ( b != nb );
}
If the multiplication overflows, the behavior is undefined.
But not hopelessly so...
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.