473,842 Members | 1,773 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Making Fatal Hidden Assumptions

We often find hidden, and totally unnecessary, assumptions being
made in code. The following leans heavily on one particular
example, which happens to be in C. However similar things can (and
do) occur in any language.

These assumptions are generally made because of familiarity with
the language. As a non-code example, consider the idea that the
faulty code is written by blackguards bent on foulling the
language. The term blackguards is not in favor these days, and for
good reason. However, the older you are, the more likely you are
to have used it since childhood, and to use it again, barring
specific thought on the subject. The same type of thing applies to
writing code.

I hope, with this little monograph, to encourage people to examine
some hidden assumptions they are making in their code. As ever, in
dealing with C, the reference standard is the ISO C standard.
Versions can be found in text and pdf format, by searching for N869
and N1124. [1] The latter does not have a text version, but is
more up-to-date.

We will always have innocent appearing code with these kinds of
assumptions built-in. However it would be wise to annotate such
code to make the assumptions explicit, which can avoid a great deal
of agony when the code is reused under other systems.

In the following example, the code is as downloaded from the
referenced URL, and the comments are entirely mine, including the
'every 5' linenumber references.

/* Making fatal hidden assumptions */
/* Paul Hsiehs version of strlen.
http://www.azillionmonkeys.com/qed/asmexample.html

Some sneaky hidden assumptions here:
1. p = s - 1 is valid. Not guaranteed. Careless coding.
2. cast (int) p is meaningful. Not guaranteed.
3. Use of 2's complement arithmetic.
4. ints have no trap representations or hidden bits.
5. 4 == sizeof(int) && 8 == CHAR_BIT.
6. size_t is actually int.
7. sizeof(int) is a power of 2.
8. int alignment depends on a zeroed bit field.

Since strlen is normally supplied by the system, the system
designer can guarantee all but item 1. Otherwise this is
not portable. Item 1 can probably be beaten by suitable
code reorganization to avoid the initial p = s - 1. This
is a serious bug which, for example, can cause segfaults
on many systems. It is most likely to foul when (int)s
has the value 0, and is meaningful.

He fails to make the valid assumption: 1 == sizeof(char).
*/

#define hasNulByte(x) ((x - 0x01010101) & ~x & 0x80808080)
#define SW (sizeof (int) / sizeof (char))

int xstrlen (const char *s) {
const char *p; /* 5 */
int d;

p = s - 1;
do {
p++; /* 10 */
if ((((int) p) & (SW - 1)) == 0) {
do {
d = *((int *) p);
p += SW;
} while (!hasNulByte (d)); /* 15 */
p -= SW;
}
} while (*p != 0);
return p - s;
} /* 20 */

Let us start with line 1! The constants appear to require that
sizeof(int) be 4, and that CHAR_BIT be precisely 8. I haven't
really looked too closely, and it is possible that the ~x term
allows for larger sizeof(int), but nothing allows for larger
CHAR_BIT. A further hidden assumption is that there are no trap
values in the representation of an int. Its functioning is
doubtful when sizeof(int) is less that 4. At the least it will
force promotion to long, which will seriously affect the speed.

This is an ingenious and speedy way of detecting a zero byte within
an int, provided the preconditions are met. There is nothing wrong
with it, PROVIDED we know when it is valid.

In line 2 we have the confusing use of sizeof(char), which is 1 by
definition. This just serves to obscure the fact that SW is
actually sizeof(int) later. No hidden assumptions have been made
here, but the usage helps to conceal later assumptions.

Line 4. Since this is intended to replace the systems strlen()
function, it would seem advantageous to use the appropriate
signature for the function. In particular strlen returns a size_t,
not an int. size_t is always unsigned.

In line 8 we come to a biggie. The standard specifically does not
guarantee the action of a pointer below an object. The only real
purpose of this statement is to compensate for the initial
increment in line 10. This can be avoided by rearrangement of the
code, which will then let the routine function where the
assumptions are valid. This is the only real error in the code
that I see.

In line 11 we have several hidden assumptions. The first is that
the cast of a pointer to an int is valid. This is never
guaranteed. A pointer can be much larger than an int, and may have
all sorts of non-integer like information embedded, such as segment
id. If sizeof(int) is less than 4 the validity of this is even
less likely.

Then we come to the purpose of the statement, which is to discover
if the pointer is suitably aligned for an int. It does this by
bit-anding with SW-1, which is the concealed sizeof(int)-1. This
won't be very useful if sizeof(int) is, say, 3 or any other
non-poweroftwo. In addition, it assumes that an aligned pointer
will have those bits zero. While this last is very likely in
todays systems, it is still an assumption. The system designer is
entitled to assume this, but user code is not.

Line 13 again uses the unwarranted cast of a pointer to an int.
This enables the use of the already suspicious macro hasNulByte in
line 15.

If all these assumptions are correct, line 19 finally calculates a
pointer difference (which is valid, and of type size_t or ssize_t,
but will always fit into a size_t). It then does a concealed cast
of this into an int, which could cause undefined or implementation
defined behaviour if the value exceeds what will fit into an int.
This one is also unnecessary, since it is trivial to define the
return type as size_t and guarantee success.

I haven't even mentioned the assumption of 2's complement
arithmetic, which I believe to be embedded in the hasNulByte
macro. I haven't bothered to think this out.

Would you believe that so many hidden assumptions can be embedded
in such innocent looking code? The sneaky thing is that the code
appears trivially correct at first glance. This is the stuff that
Heisenbugs are made of. Yet use of such code is fairly safe if we
are aware of those hidden assumptions.

I have cross-posted this without setting follow-ups, because I
believe that discussion will be valid in all the newsgroups posted.

[1] The draft C standards can be found at:
<http://www.open-std.org/jtc1/sc22/wg14/www/docs/>

--
"If you want to post a followup via groups.google.c om, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell. org/google/>
Also see <http://www.safalra.com/special/googlegroupsrep ly/>

Mar 6 '06
351 13183
On Thu, 16 Mar 2006 -0500, CBFalconer <cb********@yah oo.com> wrote:
RSoIsCaIrLiI oA wrote:
... snip ...
is there someone out there that read this?
am i plonked from all NGs?


You temporarily got off my list due to some changes in newsreader
software. At the first sign of more ridiculous obfuscating macros
you go right back on it. Meanwhile I am not likely to pay much
attention to anything you say.


are you in US too?
Mar 16 '06 #221
On Thu, 16 Mar 2006 14:45:47 +0100, "Michael Jørgensen"
<cc******@vip.c ybercity.dk> wrote:

"Paul Keinanen" <ke******@sci.f i> wrote in message
news:8i******* *************** **********@4ax. com...
where p == s will ever be false after (p = s-1; p++).

If s is stored in 16 bit mode in ES:DX with DX=0, then p=s-1 would
need to decrement ES by one and store 000F in DX.


I don't think this is what happens. Instead I think DX will wrap to FFFF,
and ES will remain unchanged.


If p=s-1 would only cause decrementing of DX (and not effecting ES)
and thus wrapping to FFFF, then what would p++ do ? It would be
logical to assume that only DX would be affected and incremented by 1,
causing wrapping DX back to 0000 and hence ES:DX would have the same
representation as the original s and p == s would be true.

Paul

Mar 16 '06 #222
On Thu, 16 Mar 2006 18:07:40 +0100, "Alf P. Steinbach"
<al***@start.no > wrote:
* Al Balmer:
On Thu, 16 Mar 2006 12:28:19 +0100, "Alf P. Steinbach"
<al***@start.no > wrote:
* Richard Bos -> someone:
*Shrug* If you go about redefining terms to support your delusion that C
is a portable assembler, that's your problem, not that of C.
Happily I haven't followed this debate, so I don't know what you folks,
good or not, think "portable assembler" means, nor how you can think a
language is a compiler (or whatever).

C was designed as a portable assembly language, the most successful so
far, so if the term has any practical meaning, then C is that meaning.
The reference you give doesn't say that.


I'm sorry for not being clear:

Wikipedia is not a reference to back up some statement, and in fact it's
not a reference of any sort (but let's not go off discussing /that/
again, just trust me: it isn't).

I gave the link as an opportunity for Richard, and now you, to learn
some very basic things,

<sarcasm>
Why, thank you!
</sarcasm>
There aren't any "basic things" in that article which I haven't
already learned, most of them decades ago. I'm sure the same is true
for Richard and Keith. OTOH, the article could have been a learning
experience for you, but apparently it was not.

(Talk about making assumptions!)
and that's why I wrote "e.g.", which means, "for
example". Also see the links provided elsethread.


I think it's time to drag out an acronym I haven't used for a while -
ABIYP.

--
Al Balmer
Sun City, AZ
Mar 16 '06 #223
Keith Thompson wrote:
"Ed Prochak" <ed*******@gmai l.com> writes:
Keith Thompson wrote:
"Ed Prochak" <ed*******@gmai l.com> writes:
[...]
> C is an assembler because
I should have phrased this: C is LIKE an assembler.


And a raven is like a writing desk.
<http://www.straightdop e.com/classics/a5_266.html>

"C is an assembler" and "C is like an assembler" are two *very*
different statements. The latter is obviously true, given a
sufficiently loose interpretation of "like".


Well my original statement was that C was a glorified assembler.
We don't need to stretch the meaning of like to the breaking point.

> -- It doesn't impose strict data type checking, especially between
> integers and pointers.
> (While there has been some discussion about cases where conversions
> back and forth between them can fail, for most machines it works. Good
> thing too or some OS's would be written in some other language.)

Incorrect. Attempting to assign an integer value to a pointer object,
or vice versa, is a constraint violation, requiring a diagnostic.
a Warning.


The C standard doesn't distinguish between different kinds of
diagnostics, and it doesn't require any program to be rejected by the
compiler (unless it has a "#error" directive).


The point is I can assign an integer value to a pointer. The warning
is a nice reminder, but that is all it is. Assemblers allow integers
to be used as pointers. Many HLL's never allow this. Can you suggest
another HLL that allows simple assignment of integer to pointer? (I
recall PL/M, a version of PL/1 for micros from INTEL. It specifically
for embedded programming so this was a required feature.)
... This allows for
language extensions; an implementation is free to interpret an
otherwise illegal construct as it likes, as long as it produces some
kind of diagnostic in conforming mode. It also doesn't require the
diagnostic to have any particular form, or to be clearly associated
with the point at which the error occurred. (Those are
quality-of-implementation issues.)
Irrelevant
This looseness of requirements for diagnostics isn't a point of
similarity between C and assemblers; on the contrary, in every
assembler I've seen, misspelling the name of an opcode or using
incorrect punctuation for an addressing mode results in an immediate
error message and failure of the assembler.
You are missing my point. It has nothing to do with whether C generates
a diagnostic. And I'll happily accept the cast to be rid of it. Point
is I can manipulate memory pointers in C very easily, nearly as easily
as I can in assembler.
Integer and pointers can be converted back and forth only using a cast
(an explicit conversion operator). The result of such a conversion is
implementation-defined.

Even if this were correct, it certainly wouldn't make C an assembler.
To some degree you are right. It's actually pointer manipulation that
makes it closer to assembler.


C provides certain operations on certain types. Pointer arithmetic
happens to be something that can be done in most or all assemblers and
in C, but C places restrictions on pointer arithmetic that you won't
find in any assembler. For example, you can subtract one pointer from
another, but only if they're pointers to the same type; in a typical
assembler, pointer values don't even have types. Pointer arithmetic
is allowed only within the bounds of a single object (though
violations of this needn't be diagnosed; they cause undefined
behavior); pointer arithmetic in an assembler gives you whatever
result makes sense given the underlying address representation.


An assembly programmer has to take on more responsibility. C provides
some tools to help. In fact, the casting helps to a small degree.
consider writing memcpy() in assembler, C, or other HLL. It is very
easy for Assembler and C. In C it may lead to code that has hidden
assumptions (the topic here) but the code will have a look very much
like assembler. In some HLLs it might not be possible to write a
generic memory copy routine.

Let me put it this way. If you are implementing memcpy(), the very
fastest, most optimized version might be pure assembler. Next would be
a version in C customized for the target platform with close to 100% of
the performance of the assembler version. The C version will be easier
to maintain than the pure assembler, but to get it that close requires
the programmer to think of the consequences of certain programming
constructs. Then you'll get a version in some other HLL which might
run well, but will be measureably below the performance of the C and
assembler versions.
... C
says nothing about how pointers are represented, and arithmetic on
pointers is not defined in terms of ordinary integer arithmetic; in an
assembler, the representation of a pointer is exposed, and you'd
probably use the ordinary integer opertations to perform pointer
arithmetic.
Yes in C I need to consider the significance of pointer types. But this
is analogous to assembler opcode options.
MOVB -- move a byte
MOVW -- move a word
MOVL -- move a longword
> -- datatype sizes are dependent on the underlying hardware. While a lot
> of modern hardware has formed around the common 8bit char, and
> multiples of 16 for int types (and recent C standards have started to
> impose these standards), C still supports machines that used 9bit char
> and 18bit and 36bit integers. This was the most frustrating thing for
> me when I first learned C. It forces precisely some of the hidden
> assumptions of this topic.

I don't know what "recent C standards" you're referring to. C
requires CHAR_BIT to be at least 8; it can be larger. short and int
must be at least 16 bits, and long must be at least 32 bits. A
conforming implementation, even with the most current standard, could
have 9-bit char, 18-bit short, 36-bit int, and 72-bit long.
How about a bitsliced machine that uses only 6bit integers?


What about it? A conforming C implementation on such a machine must
have CHAR_BIT>=8, INT_MAX>=32768, LONG_MAX>=21474 83647, and so forth.
The compiler may have to do some extra work to implement this. (You
could certainly provide a non-conforming C implementation that
provides a 6-bit type called "int"; the C standard obviously places no
constraints on non-conforming implementations . I'd recommend calling
the resulting language something other than C, to avoid confusion.)


Actually I'd assign type short to that integer. Good point though. You
made me see I picked the wrong argument. Back to the machine with 9bit
CHAR. In C the MAX_INT is dependent on the underlying processor and is
allowed ro range up to what the hardware can handle, so instead of
32768, you can go up to 131071 Other HLLs do not let that happen. the
max int in PASCAL is 32767, even on that same machine. A High level
language was supposed to get us away from thinking about the underlying
hardware wasn't it?
But this is a common feature of many high-level languages. Ada, for
example has an implementation-defined set of integer types, similar to
what C provides; I've never heard anyone claim that Ada is an
assembler.
Forgive my memory,but is it PL/1 or ADA that lets the programmer define
what integer type he wants. Syntax was something like
INTEGER*12 X
defined X as a 12 bit integer. (Note that such syntax is portable in
that on two different processors, you still know that the range of X is
+2048 to -2047
The point is a 16bit integer in ADA is always a 16bit integer and
writing
x=32768 +10
will always overflow in ADA, but it is dependent on the compiler and
processor in C. It can overflow, or it can succeed.


I'm not familiar with PL/I.


Okay, I found a web page off the PL/I faq page. here's a comment about
PL/I' independence from the hardware that speaks directly about
dayatypes:
<start quote>
PL/I defines its data types very precisely without regard for any
hardware. For example, an "integer" is defined as having a mode of REAL
or COMPLEX, base of BINARY or DECIMAL, along with the precision that
you require. Therefore, FIXED BINARY(12) declares a binary integer of
12 data bits, whereas FIXED DECIMAL(3) declares a decimal integer of 3
decimal digits. You get precisely what you ask for. The implementers
deliver even if the machine has no support for such data type or
precision.
<end quote>

So I had the syntax wrong (It's been a LONG time since I did PL/I), but
the point is
the value range is independent of the underlying hardware. In C this is
true for the low end. That 6bit byte machine would require extra code
from the C compiler to implement 8bit char types. but on a 9bit byte
machine C happily lets the programmer get access to that ninth bit, not
so in PL/I.

PL/I seems to me better than C in that it reduces the hidden
assumptions. So if you need 12bit integers, you get exactly that with
an exception generated when you hit the limit, no matter what the
underlying hardware can handle.

Ada (not ADA) has a predefined type called Integer. It can have other
predefined integer types such as Short_Integer, Long_Integer,
Long_Long_Integ er, and so forth. There are specific requirements on
the ranges of these types, quite similar to C's requirements for int,
short, long, etc. There's also a syntax for declaring a user-defined
type with a specified range:
type Integer_32 is range -2**31 .. 2**31-1;
This type will be implemented as one of the predefined integer types,
selected by the compiler to cover the requested range.
Ada (yes you're right on the letter case) is similar to C. One reason
is that Ada is supposed to be for embedded systems, so it needs the
flexibility of open-ended data ranges. But it also does a LOT more type
checking than C. I only looked at it years ago, never written any real
code in Ada.
C99 has something similar, but not as elaborate: a set of typedefs in
<stdint.h> such as int32_t, intleast32_t, and so forth. Each of these
is implemented as one of the predefined integer types.
But in Ada you could declare
type Integer_24 is range -2**23 .. 2**23-1;
I don't expect stdint.h has those defined.
But my point on this was, you need to know your target processor in C
more than in a language like ADA. This puts a burden on the C
programmer closer to an assembler programmer on the same machine than
to a ADA programmer.
You can get just as "close to the metal" in Ada as you can in C.


Yes, Ada was a poor choice here. It's too close to C in its feature
set.
Or,
in both languages, you can write portable code that will work properly
regardless of the underlying hardware, as long as there's a conforming
implementation.
TRUE.
But portability alone doesn't free C from the feel of assembler.
16bit 8086 assembler code still worked essentially unchanged on the 386
processor.

.. C is lower-level than Ada, so it's there's a greater
bias in C to relatively low-level constructs and system dependencies,
but it's only a matter of degree.
yes, as I said in another post, it is a question of degree..
In this sense, C and Ada are far
more similar to each other than either is to any assembler I've ever
seen.
I can understand that view, but on the Assembler to HLL scale I still
put C closer to assembler. Ada does a lot more for you than C does,
AFAIK.
[...]
You're talking about an implementation, not the language.
a big characteristic of assembler is that it is a simple language.
C is also a very simple language. Other HLLs are simple too, but the
simplicity combined with other characteristics suggest to me an
assembler feel to the language.


If you're just saying there's an "assembler feel", I won't argue with
you -- except to say that, with the right mindset, you can write
portable code in C without thinking much about the underlying
hardware.


I never said you couldn't. I like C. I have been using it in various
projects since the early 80's. It is a great language. I guess I'm just
saying you can write better C code knowing its assembler side. Doing
that will help keep you aware of some of these gotchas we've been
discussing.
[...]
Again, you're talking about an implementation, not the language.
No I was talking about the original motivation for the design of the
language. It was designed to exploit the register increment on DEC
processors. in the right context, (e.g. y=x++;) the increment doesn't
even become a separate instruction, as I mentioned in another post.


The PDP-11 has predecrement and postincrement modes; it doesn't have
preincrement or postdecrement. And yet C provides all 4 combinations,
with no implied preference for the ones that happen to be
implementable as PDP-11 addressing modes. In any case, C's ancestry
goes back to the PDP-7, and to earlier languages (B and BCPL) that
predate the PDP-11.

I remembered UNIX started on earlir model, but I thought it was a
PDP-8. I don't recall a PDP-7. But I thought C came after the initial
versions of UNIX.

I'll double check my PDP-11 manual about the increment modes. I would
swear they were both. available. [...]
Here's what the C standard says about the "register" specifier:

A declaration of an identifier for an object with storage-class
specifier register suggests that access to the object be as fast
as possible. The extent to which such suggestions are effective is
implementation-defined.
I know that it is just a suggestion. The point is Why was it included
in the language at all? Initially it gave the programmer more control.


Sure, but giving the programmer more control is hardly synonymous with
assembly language.


If you approach C with an Assembler proing mindset, you can exploint
certain features to your advantage on targetted code. Being aware of
that aspect of C can help you avoid some of those things inwriting
portable C code.
And there are a few restrictions; for example, you can't take the
address of a register-qualified object.
Which makes sense to an assembler programmer, but not to a typical HLL
programmer.


Sure, it's a low-level feature.


No, someone with only a HLL view of coding would look at that
restriction and say
"what the %^&*! Why doesn't this work?"
But someone with assembly experience would understand it immediately.

> So IMHO, C is a nice generic assembler. It fits nicely in the narrow
> world between hardware and applications. The fact that it is a decent
> application development language is a bonus. I like C, I use it often.
> Just realize it is a HLL with an assembler side too.

You've given a few examples that purport to demonstrate that C is an
assembler.

Try giving a definition of the word "assembler" . If the definition
applies to C (the language, not any particular implementation) , I'd
say it's likely to be a poor definition, but I'm willing to be
surprised.
lets put it this way. there is a gradient scale, from pure digits of
machine language (e.g., programming obcodes in binary is closer to the
hardware than using octal or hex)
at the lowest end and moving up past assebmler to higher and higher
levels of abstraction away from the hardware. On that scale, I put C
much closer to assembler than any other HLL I know. here's some samples
PERL, BASH, SQL
C++, JAVA
PASCAL, FORTRAN, COBOL
C
assembler
HEX opcodes
binary opcodes
digital voltages in the real hardware.


That seems like a reasonable scale (I might put Forth somewhere below
C). But you don't indicate the relative distances between the levels.
C is certainly closer to assembler than Pascal is, but I'd say that C
and Pascal are much closer to each other than either is to assembler.


That's it. We just differ on the scale.

I don't have a stron sense of the distances. I guess I would put C
about equidistant from both assembler and PASCAL. Hm, maybe someday I
will have to come up with a scale for this)
FORTH is a good example too. To me FORTH is more like a VM language.
But I haven't done any programming in it, so I left it out.

You can write system-specific non-portable code in any language. In
assembler, you can *only* write system-specific non-portable code. In
C and everything above it, it's possible to write portable code that
will behave as specified on any system with a conforming
implementation, and a conforming implementation is possible on a very
wide variety of hardware. Based on that distinction, there's a
sizable gap between assembler and C.

And when you HAVE to write non-portable code, C is a better choice
than PASCAL or other HLLs (except maybe Ada).
--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.

Great discussion. Thanks for the informative replies.
Ed.

Mar 16 '06 #224
On Thu, 16 Mar 2006 18:51:19 +0100, RSoIsCaIrLiIoA <zz@zz.z> wrote:
On Thu, 16 Mar 2006 10:04 -0700, Al Balmer <al******@att.n et> wrote:
On Thu, 16 Mar 2006 12:34:01 +0100, RSoIsCaIrLiIoA <zz@zz.z> wrote:

is there someone out there that read this?
am i plonked from all NGs?


According to my newsreader, your first post was at 4:34 am, and your
second at 5:30 am. What were you expecting? Do you have this group
confused with a chat room?


pheraps in your time, my second post seems to me 12:34am, here in
Italy; i think you are in US. near Boston?


Bad guess. Anyway, local time doesn't affect the length of time
between the messages.

(Hint - a glance at my sig would have provided a clue as to my
whereabouts.)

--
Al Balmer
Sun City, AZ
Mar 16 '06 #225
* Al Balmer:

<sarcasm>
No, sarcasm is not called for or appropriate in this context.

Why, thank you!
Yes, you should thank me. But you do it like pointing at a very nice
car, then saying, "Hey, I'm being sarcastic! That's a car! End
sarcasm!". And in case you failed to understand that example, although
debating technique is probably off-topic in this group: sarcasm that
needs to be marked as such, is not a good way to win rhetorical points.
</sarcasm>

There aren't any "basic things" in that article which I haven't
already learned, most of them decades ago.
Didn't seem that way a message or so ago; then you presented the view of
a complete ignoramus, and -- now you did it again.

I'm sure the same is true for Richard and Keith.

OTOH, the article could have been a learning
experience for you, but apparently it was not.

(Talk about making assumptions!)


What strikes me about the quotes passage above is... Well... The last
paragraph, for example. LOL! ROTFF!
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Mar 16 '06 #226
Al Balmer wrote:
On Thu, 16 Mar 2006 12:34:01 +0100, RSoIsCaIrLiIoA <zz@zz.z> wrote:
is there someone out there that read this?
am i plonked from all NGs?


According to my newsreader, your first post was at 4:34 am, and your
second at 5:30 am. What were you expecting? Do you have this group
confused with a chat room?


However, it's true that many of us have him/her/it plonked, for
previous trolling.

Brian
Mar 16 '06 #227
On Thu, 16 Mar 2006 10:36:02 -0500, CBFalconer wrote:
"Michael Jørgensen" wrote:
"Paul Keinanen" <ke******@sci.f i> wrote in message
If s is stored in 16 bit mode in ES:DX with DX=0, then p=s-1
would need to decrement ES by one and store 000F in DX.


I don't think this is what happens. Instead I think DX will wrap
to FFFF, and ES will remain unchanged.


More easily answered if the original statement had been preserved
in context. However in this case if the ES segment has range
limits, a segment fault will be triggered. Due to the happy
looseness of the term "undefined behavior" no specific action is
needed, which is what enables the loosing of nasal demons or
launching of missiles.


Nah. Seg faults only happen on access, in that situation. The value of
DX can't matter: it isn't part of the "pointer" until an access happens.

It looks as though the AS/400 is the only machine that that particular
restriction in the standard is there to support. Yay.

Cheers,

--
Andrew

Mar 16 '06 #228
On Thu, 16 Mar 2006 21:07:53 +0100, "Alf P. Steinbach"
<al***@start.no > wrote:
* Al Balmer:

<sarcasm>
No, sarcasm is not called for or appropriate in this context.

My call, not yours.
Why, thank you!
Yes, you should thank me. But you do it like pointing at a very nice
car, then saying, "Hey, I'm being sarcastic! That's a car! End
sarcasm!". And in case you failed to understand that example, although
debating technique is probably off-topic in this group: sarcasm that
needs to be marked as such, is not a good way to win rhetorical points.


Depends on the audience. With some, one must be explicit.
</sarcasm>

There aren't any "basic things" in that article which I haven't
already learned, most of them decades ago.


Didn't seem that way a message or so ago; then you presented the view of
a complete ignoramus, and -- now you did it again.


How so? By stating a fact? One that contradicts your characterizatio n
of everyone who disagrees with you?
I'm sure the same is true for Richard and Keith.

OTOH, the article could have been a learning
experience for you, but apparently it was not.

(Talk about making assumptions!)


What strikes me about the quotes passage above is... Well... The last
paragraph, for example. LOL! ROTFF!


So you did catch it. Not necessarily unintelligent, just a (what's
that word? Oh, yes ...) ignoramus.

I should have quit when you first resorted to insulting those who
disagree with you. Bye, now.

--
Al Balmer
Sun City, AZ
Mar 16 '06 #229
* Al Balmer:
On Thu, 16 Mar 2006 21:07:53 +0100, "Alf P. Steinbach"
<al***@start.no > wrote:
* Al Balmer:
<sarcasm> No, sarcasm is not called for or appropriate in this context.

My call, not yours.
Why, thank you!

Yes, you should thank me. But you do it like pointing at a very nice
car, then saying, "Hey, I'm being sarcastic! That's a car! End
sarcasm!". And in case you failed to understand that example, although
debating technique is probably off-topic in this group: sarcasm that
needs to be marked as such, is not a good way to win rhetorical points.


Depends on the audience. With some, one must be explicit.
</sarcasm>


There aren't any "basic things" in that article which I haven't
already learned, most of them decades ago.

Didn't seem that way a message or so ago; then you presented the view of
a complete ignoramus, and -- now you did it again.


How so? By stating a fact?


That's stretching a bit beyond the breaking point: you have yet to state
/any/ relevant fact in responses to my postings.

In your first posting responding to my posting, you stated:

they're talking about you, not the rest of the world

which is insulting, and then

Remember that the moon is sometimes said to be made of green cheese.

which is even more insulting.

Not to mention that the logic chain that those sentences were part of,
was built on an incorrect premise, which I think you knew, seeing as you
now resort to outright lying (below).

One that contradicts your characterizatio n
of everyone who disagrees with you?
Note, I have so far responded to your calculated insults in a restrained
manner, and I will continue to restrain myself.

I have not characterized others, for the simple reason that of the three
or four or so people responding to my posting, only you tried to win
rhetorical points by using personal insults.

In short, that bit about me characterizing everyone who disagrees with
me, when I've only characterized you (and rightly so), that's untrue,
and that means you're now lying to try to resque yourself.

But you cannot resque yourself from that.

For anyone can sort messages on date+time and see that your comment is a
plain and simple lie, even with the most Al-friendly interpretation.

I'm sure the same is true for Richard and Keith.
OTOH, the article could have been a learning
experience for you, but apparently it was not.

(Talk about making assumptions!)

What strikes me about the quotes passage above is... Well... The last
paragraph, for example. LOL! ROTFF!


So you did catch it. Not necessarily unintelligent, just a (what's
that word? Oh, yes ...) ignoramus.


Yep, you're stupid.

I should have quit when you first resorted to insulting those who
disagree with you. Bye, now.


My only quibble there is with you: you started off being insulting and
off-topic. Be careful what you ask. You sometimes get what you ask for.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Mar 16 '06 #230

This thread has been closed and replies have been disabled. Please start a new discussion.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.