From: ctm@ardi.com (Clifford T. Matthews)
Subject: Re: The need for an assembler
Organization: ARDI
Date: Fri, 4 Sep 92 07:53:01 GMT

Dear Folks,

This is not the example that I e-mailed cjl.  What I e-mailed him
was basically the last line in "foo.h".  I didn't realize that he'd
get so excited about the possibility for overflow (after all, if
someone asked me how to write the C code to add five to an int
called "x", I'd answer "x += 5;", without thinking to tell the
person who asked the question that theres a chance that by adding
five to x, he or she would encounter overflow; I assume a certain
level of intelligence/knowledge in my audience, sometimes I
overestimate though).

Anyway, this version has a little check to make sure that you don't
use the "INRANGE" macro where it is inappropriate.  If you do,
you'll get an error message at link time (assuming you never define
the function with the long name).

I've added some comments to the assembler output, just to point
out some interesting things about what gcc produces.  I've never
said that this example shows anything other than cjl's challenge
about range testing has been answered correctly, and he still
refuses to admit it.  I personally don't see any point to continue
the discussion with cjl, because he repeatedly makes claims that
are so far off base that it's clear that either he doesn't know
what he's talking about or he does and is just baiting the rest of
us, but either way, there's not much point to continue.  I suspect he'll
have some off-the-wall objections to the example produced below, but
pointing out the error in those will be left as an excercise for
the reader.

cjl declined to answer any of the points I raised in my last two
posts, but that's OK.  I don't think it's likely that I'll convince
him of anything, and you, the gentle reader, have seen enough to make
up your own mind.  Normally I wouldn't have posted to the net at all,
but I was really floored to see cjl post saying that no one had sent
him a legit solution when I most definitely had.

		See you in the funny papers,
		
		--Cliff

iclone% cat foo.h
/*
 * The following define will return 0 or 1 depending on whether the argument
 * int x is between ints lower and upper inclusive.
 *
 * If you happen to choose values of lower and upper that result in overflow,
 * you lose, and will be told so at link time.
 *
 * This code requires twos-complement int representation.
 *
 * Yahoo!
 *
 */

#define INRANGE(x, lower, upper)                                        \
((upper - lower < 0) ?                                                  \
    danger_will_robinson_you_need_assemblerman_post_to_a_f_computers()  \
:                                                                       \
    (unsigned) (x - lower) <= (upper - lower))
iclone% cat foo.c
#include "foo.h"

some_func()
{
    int x;

    x = 3;

    if (INRANGE(x, -4, 10))
        printf("x ( =3 ) is between -4 and 10\n");

    x = somefunctiondefinedelsewhere();

    if (INRANGE(x, -4, 10))
        printf("x ( =? ) is between -4 and 10\n");
    
    if (INRANGE(x, 0, 40))
        printf("x ( =? ) is between 0 and 40\n");
}
iclone% gcc -O -fomit-frame-pointer -S foo.c
iclone% cat foo.s
#NO_APP
.text
LC0:
        .ascii "x ( =3 ) is between -4 and 10\12\0"
LC1:
        .ascii "x ( =? ) is between -4 and 10\12\0"
LC2:
        .ascii "x ( =? ) is between 0 and 40\12\0"
        .even
.globl _some_func
_some_func:
        moveml #0x1020,sp@-
        pea LC0
        lea _printf,a2	// gcc saves printf's address for future reuse
        jbsr a2@	// BTW: since 3 is in range, and gcc knows x is 3
        addqw #4,sp	// gcc calls printf the first time with *no check*
        jbsr _somefunctiondefinedelsewhere
        movel d0,d3
        addql #4,d0
        moveq #14,d1	// gcc does a moveq followed by a cmpl, instead
        cmpl d0,d1	// of a cmpl #, because it's quicker (I wouldn't
        jcs L3		// have done this)
        pea LC1
        jbsr a2@
        addqw #4,sp
L3:
        moveq #40,d1	// since the lower bound is 0, gcc doesn't bother
        cmpl d3,d1	// doing the subtract (which was actually done with
        jcs L4		// an add above (x + 4) is the same as (x - -4))
        pea LC2
        jbsr _printf
        addqw #4,sp
L4:
        moveml sp@+,#0x408
        rts
	
// NOTE:  We've reached the end of the assembly that foo.c produced, with no
//	  reference to the undefined function "danger_will_robinson...", hence
//	  this module will link properl, because it doesn't attempt to use
//	  INRANGE with bad arguments
	
iclone% cat foo1.c
#include "foo.h"

some_func()
{
    int x;

    x = somefunctiondefinedelsewhere();

    if (INRANGE(x, -2000000000, 2000000000))
        printf("x ( =3 ) is between -2000000000 and 2000000000\n");
}
iclone% gcc -O -fomit-frame-pointer -S foo1.c
iclone% cat foo1.s
#NO_APP
.text
LC0:
        .ascii "x ( =3 ) is between -2000000000 and 2000000000\12\0"
        .even
.globl _some_func
_some_func:
        jbsr _somefunctiondefinedelsewhere
        jbsr _danger_will_robinson_you_need_assemblerman_post_to_a_f_computers
        tstl d0
        jeq L2
        pea LC0
        jbsr _printf
        addqw #4,sp
L2:
        rts

// NOTE: because of overflow, we now have a reference to a function that we
//	 haven't defined.  This will prevent our code from linking and will
//	 clue the user of INRANGE in to the fact that he or she should post
//	 to alt.folklore.computers to learn about computers and stuff.  I
//	 know that's where I get *my* information.
Newsgroups: alt.folklore.computers