hardware errors, do C and Forth need different things in hardware?

70 views
Skip to first unread message

Jeff Fox

unread,
May 19, 2006, 3:06:45 PM5/19/06
to
Most software that came from mainframes and minis was
written from the perspective that an OS and hardware
circuits are needed to prevent unpredictably hostile or
buggy programs from wrecking everything. Where I
work in embedded Forth software the cooperative nature
of programs and any OS needed has a different set of
problems. Often when I talk to people who have the C
idea about hardware/software there is confusion about
terms like hardware errors, error trapping, and error
handling. I will address this and other topics at SVFIG
tomorrow. So let me ask about embedded Forth:

Which of the following 10 conditions should be considered
hardware errors? For those that are errors, how should the
hardware trap them and what should it do to assist with a
solution?

1. begin again \ forever

2. begin ?key until \ no key pressed

3. begin 255 p@ 8 and until \ port bit always false

4. data rom-address !

5. : demo 2 0 / ;
demo

6. : demo 8123 @ ; \ only 32K byes of memory 0-8000
demo

7. : demo blah recurse ; \ no return stack manipulation in blah
demo \ and with no tail recursion
optimization

8. the difference between the number of items pushed
to a stack by a program and the number of items poped
back from the stack is greater than the size of the stack.

9. a program pops from a stack more items than it pushed
to the stack.

10. hardware that will go to sleep when reading ports and
waiting for a neighbor to write is in a sleep state
and neighbors are also a sleep trying to read.

Anton Ertl

unread,
May 19, 2006, 3:30:02 PM5/19/06
to
"Jeff Fox" <f...@ultratechnology.com> writes:
>Which of the following 10 conditions should be considered
>hardware errors?

Most look like software errors. Some can be detected by hardware or
software, and then it's usually convenient if the hardware detects it
and informs the software of the problem.

> For those that are errors, how should the
>hardware trap them and what should it do to assist with a
>solution?

Typically record all the circumstances of the error in order to make
debugging easier.

>1. begin again \ forever

A hardware watchdog timer can detect this.

>2. begin ?key until \ no key pressed

That's bad programming, but usually not an error. Other tasks will
get their turn, and the task containing this nonsense does what it is
supposed to do.

>3. begin 255 p@ 8 and until \ port bit always false

Like 1, a hardware watchdog timer can be used to catch this.

>4. data rom-address !

A kind of MMU can detect this.

>5. : demo 2 0 / ;
> demo

Some architectures detect this in hardware (e.g., i386), some need
software for it (e.g., PPC).

>6. : demo 8123 @ ; \ only 32K byes of memory 0-8000
> demo

Also detectable by MMU.

>7. : demo blah recurse ; \ no return stack manipulation in blah
> demo \ and with no tail recursion
>optimization

So we get a return stack overflow. Can also be detected in hardware.
If the stack is implemented in memory, by an MMU.

>8. the difference between the number of items pushed
> to a stack by a program and the number of items poped
> back from the stack is greater than the size of the stack.

So there is either a stack overflow or an underflow. Like 7.

>9. a program pops from a stack more items than it pushed
> to the stack.

That is normal. Most Forth programs consume some values from the
stack.

>10. hardware that will go to sleep when reading ports and
> waiting for a neighbor to write is in a sleep state
> and neighbors are also a sleep trying to read.

A hardware deadlock? I would assume that such blocking hardware has
some timeout mechanism built-in. If not, a hardware watchdog timer
can help.

- anton
--
M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
New standard: http://www.complang.tuwien.ac.at/forth/ansforth/forth200x.html

Message has been deleted

bria...@rogers.com

unread,
May 19, 2006, 11:06:40 PM5/19/06
to

A Man Crying Alone In The Wilderness wrote:
> Anton Ertl wrote:
> > "Jeff Fox" <f...@ultratechnology.com> writes:
> > > <SNIP>

> > >10. hardware that will go to sleep when reading ports and
> > > waiting for a neighbor to write is in a sleep state
> > > and neighbors are also a sleep trying to read.
> >
> > A hardware deadlock? I would assume that such blocking hardware has
> > some timeout mechanism built-in. If not, a hardware watchdog timer
> > can help.
> >
>
> With development of my most current VLIW SMP MPP model ( from Mr.
> Moores 25X thoery), simple, I suggest not permitting a blocking or
> sleep feature for the diagonal enhanced processors. ( maybe a throttle
> is OK, none or all, but havn't thought much of SUPER SCALABLE POWER
> CONSERVATION, <insert your observation knowledge here> ).
>
> OH MY GOD! WHAT CAN WE DO TO STOP *** SOFT PARTICLE ERRORS *** FROM
> CORRUPTING A SEA OF PROCESSORS! ( WORKING DEEP IN GOVERNEMNT AI LEGAL
> ASSISTANCE PROBLEM ... )
>
> Oh, ya, maybe, simple red, yellow, green quad verification of cores,
> but I said that already, hmm, to Washington, about eight years ago!
>
> more,
>


Is it just me or does this text sound a lot like Ractor?

Is this a 'bot?

Brian Fox

Message has been deleted

rickman

unread,
May 20, 2006, 8:54:24 AM5/20/06
to
Anton Ertl wrote:
> "Jeff Fox" <f...@ultratechnology.com> writes:
> >Which of the following 10 conditions should be considered
> >hardware errors?
>
> Most look like software errors. Some can be detected by hardware or
> software, and then it's usually convenient if the hardware detects it
> and informs the software of the problem.

I think timers are not always the best solution...


> > For those that are errors, how should the
> >hardware trap them and what should it do to assist with a
> >solution?
>
> Typically record all the circumstances of the error in order to make
> debugging easier.
>
> >1. begin again \ forever
>
> A hardware watchdog timer can detect this.

Exactly what is the timer going to detect? Running in a loop is normal
operation. I would expect software to detect this type of construct
and not allow it.


> >2. begin ?key until \ no key pressed
>
> That's bad programming, but usually not an error. Other tasks will
> get their turn, and the task containing this nonsense does what it is
> supposed to do.

I don't agree that this is bad programming. How else do you wait for
keyboard input or any other external event?


> >3. begin 255 p@ 8 and until \ port bit always false
>
> Like 1, a hardware watchdog timer can be used to catch this.

I don't understand the error. Why would the port bit always be false?
Is this the wrong bit to check? Is the hardware stuck or a hardware
error? I also don't see how to easily check this with a timer. What
are the start and stop conditions for the timer?


> >4. data rom-address !
>
> A kind of MMU can detect this.
>
> >5. : demo 2 0 / ;
> > demo
>
> Some architectures detect this in hardware (e.g., i386), some need
> software for it (e.g., PPC).
>
> >6. : demo 8123 @ ; \ only 32K byes of memory 0-8000
> > demo
>
> Also detectable by MMU.

I believe the main reason this sort of mistake happens is when
addresses are calculated as in arrays and the index is not checked
against the size of the array. But it can also happen when address and
data are mixed such as incorrect stack handling... but that never
happens, right?


> >7. : demo blah recurse ; \ no return stack manipulation in blah
> > demo \ and with no tail recursion
> >optimization
>
> So we get a return stack overflow. Can also be detected in hardware.
> If the stack is implemented in memory, by an MMU.

I can't imagine a stack machine without stack checking for over and
underflow. I would expect that to be the most common error, but then
there are other ways to use a stack, right?


> >8. the difference between the number of items pushed
> > to a stack by a program and the number of items poped
> > back from the stack is greater than the size of the stack.
>
> So there is either a stack overflow or an underflow. Like 7.

Why would the difference matter. Wouldn't you get an overflow if you
pushed more things on the stack at any time; same with underflow?


> >9. a program pops from a stack more items than it pushed
> > to the stack.
>
> That is normal. Most Forth programs consume some values from the
> stack.
>
> >10. hardware that will go to sleep when reading ports and
> > waiting for a neighbor to write is in a sleep state
> > and neighbors are also a sleep trying to read.
>
> A hardware deadlock? I would assume that such blocking hardware has
> some timeout mechanism built-in. If not, a hardware watchdog timer
> can help.

I don't think you need a timer. What would you be timing??? If both
CPUs go to sleep waiting on one another, it could be normal if they are
also waiting on other conditions or you can just detect the mutual wait
in hardware. No need for a timer either way.

Message has been deleted

ben yates

unread,
May 20, 2006, 9:34:28 AM5/20/06
to
On Fri, 19 May 2006 12:06:45 -0700, Jeff Fox wrote:

> Most software that came from mainframes and minis was
> written from the perspective that an OS and hardware
> circuits are needed to prevent unpredictably hostile or
> buggy programs from wrecking everything. Where I
> work in embedded Forth software the cooperative nature
> of programs and any OS needed has a different set of
> problems. Often when I talk to people who have the C
> idea about hardware/software there is confusion about
> terms like hardware errors, error trapping, and error
> handling. I will address this and other topics at SVFIG
> tomorrow. So let me ask about embedded Forth:
>
> Which of the following 10 conditions should be considered
> hardware errors? For those that are errors, how should the
> hardware trap them and what should it do to assist with a
> solution?
>
> 1. begin again \ forever

Software error. But have you _ever_ used such a loop in your programming?
I have - usually at end of program to keep the screen current. Usually
when debugging.

>
> 2. begin ?key until \ no key pressed

User error - press a key! :) Not a software or hardware error.

>
> 3. begin 255 p@ 8 and until \ port bit always false

Either a bug (wrong port $) or an unsatisfied condition. Not an error.
Perhaps the software _could_ be more robust.

>
> 4. data rom-address !

Not an error, perhaps. Was used in some instances for bank-switching.

>
> 5. : demo 2 0 / ;
> demo

Here, a hardware trap of div by 0 is nice, I admit... but I don't agree
that it has to be a NMI.

>
> 6. : demo 8123 @ ; \ only 32K byes of memory 0-8000
> demo

Depends on the architecture as to what happens, it may "wrap" by design.
Or your system may have ROM above this, see previous answer to #4.

>
> 7. : demo blah recurse ; \ no return stack manipulation in blah
> demo \ and with no tail recursion
> optimization

software error.

>
> 8. the difference between the number of items pushed
> to a stack by a program and the number of items poped back from the
> stack is greater than the size of the stack.

software error, with perhaps hardware stack checking.

>
> 9. a program pops from a stack more items than it pushed
> to the stack.

Same as #8, stack underflow.

>
> 10. hardware that will go to sleep when reading ports and
> waiting for a neighbor to write is in a sleep state and neighbors are
> also a sleep trying to read.

Application design issue.

Message has been deleted

Coos Haak

unread,
May 20, 2006, 1:03:17 PM5/20/06
to
Op Sat, 20 May 2006 09:34:28 -0400 schreef ben yates:

> On Fri, 19 May 2006 12:06:45 -0700, Jeff Fox wrote:
>

<snip>


>> 1. begin again \ forever
>
> Software error. But have you _ever_ used such a loop in your programming?
> I have - usually at end of program to keep the screen current. Usually
> when debugging.
>

Normal use in embedded processing. At reset, the watchdog timer will start
counting and when an overflow occurs, it resets the system.
The user task between begin and again must therefore regularly reset the
watchdog timer before a reset could interrupt its task. Only when the task
is someway halted, the WDT can reset the system and the process can resume
normally.

--
Coos

CHForth, 16 bit DOS applications
http://home.hccnet.nl/j.j.haak/forth.html

Jeff Fox

unread,
May 20, 2006, 2:32:22 PM5/20/06
to
My point was that I could list ten advantages that we have
in Forth where we can write simpler, easier to understand,
easier to compile, easier to run, and faster code on
simpler cheaper and easier to understand hardware and
that they would likely just look like bugs to C programmers.

These are ways Forth can beat C because C wants to
insist that one needs mainframe hardware and software.
That's the problem it was designed to sovle, to write
Unix as the software traffic cop for the hardware traffic
cop for hostile C programs.

But when you show the advantages that define cooperative
Forth software and that distinguish it from C those things
may not be visible at all from inside of the set of rules that
apply to C/Unix and the mainframe world of hostile programs.
Forth looks like a bug, an error in design, in that enviroment.

But back to the examples listed as things from embedded
Forth. There are no bugs, just simple code that does what
it says.

Not hidden complications, no hidden software, no hidden
hardware adding problems. If you think they are bugs,
they become bugs. They are bugs in C, and in C Forth
thus becomes a bug.

The list is ordered from most simple and obvious to the
most useful and most powerful Forth features that C
programmers can easily confuse with bugs. I have
explained most of them many times and people
probably knew exactly what I would say about each one.

People were suppose to be able to see that they get
more useful, and more powerful by number and that after
the first nine were not bugs one was suppose to be able
to guess that the last one was the most important non-bug.

The first reads BEGIN AGAIN. All Forth programmers are
suppose to be able to read that. It is suppose to be simple.
It does not imply hidden background tasks or watchdogs.
Thinking it is dozens of times more complicated than it
is misses the power of Forth and is an error. It isn't C.

It reminds me of a test I saw on the web to read some code
and count the number of paths through the code. I got a
low score. It looked like three at first, then I saw two more.
But I missed twenty hidden paths that could be trigged
by different combinations of data triggering different error
trapping hardware mechanisms and throwing different
exceptions. Once you are convinced something is a
bug, and you make it so in the hardware and software
it is a bug. It is how 'good' software in Forth is invisible
in C and why Forth looks like bugs there.

What makes Forth fundamentally different than C and
gives it some fundamental advantages over C is that
it can do things with much less overhead than C. That
is because in C the idea is that software is bad and
an OS and hardware traps are needed to protect
everything from bad software. Bugs are planned, and
the whole picture is all about the planning for bugs.

Forth is about planning for good code where the bugs
don't happen. If you say BEGIN AGAIN damn it, you
mean BEGIN AGAIN not twenty other possible
meanings based on C insisting that it is one of twenty
different bugs that need extra hardware and software
to be handled properly.

You can say, ok, this is perfectly sound mathematically and
prove it. You can show exactly how many possible paths
there are through good code. You can handle every possible
'error condition' in a program without having any hardware
error conditions. Hardware error conditions are about
software design errors or hardware/software design errors
and wether bugs should be designed in. Bugs can often be
traced back to conceptual problems of people who introduce
errors intentionally as an essential part of their concept of
data processing.

This one issue, of whether software is fundamentally
good and cooperative or fundamentally hostile and
uncooperative seems to distinguish the mutually exclusive
'everything needs to be like mainframes' and 'everything
does not need to be like mainframes' mentalities.

Hostile and uncooperative software looks buggy and inefficient
from the point of view of 'good' Forth software. And what is
'good' simple cooperative software in Forth looks like bugs
from the hardware and OS are all about the hostile and
uncooperative nature of programs point of view. They
are mutually exclusive sets.

It was test to see if you could distinguish ten things that
define embedded Forth and show that give it some advantages
over C software or if those things looked like errors like they
would to a C programmer.

If the power of the last few items not being errors at all is apparent
to someone then Forth is visible to them as something other than
a bug.

John Passaniti

unread,
May 20, 2006, 10:29:54 PM5/20/06
to
Jeff Fox wrote:
> These are ways Forth can beat C because C wants to
> insist that one needs mainframe hardware and software.
> That's the problem it was designed to sovle, to write
> Unix as the software traffic cop for the hardware traffic
> cop for hostile C programs.

C doesn't insist on anything.

Back a couple years ago, you wrote one of your typically leading
messages asking about the executable size of a simple "Hello World"
program in C. I happened to be working with a C compiler for
microcontroller at the time (ImageCraft's HC08), and so I compiled some
code to see the size. The result was around a couple hundred bytes,
assuming one used puts to display the string instead of the overkill
printf that's in most canonical examples. A minimal printf shot the
size to about 1800 bytes. And in either case, that was the *entire*
code, including startup and the vector to allow the processor to run the
program. There was no OS on the target. This was code that talked to
the bare metal.

Your reply at the time was "nice."

I really get tired of your apples-to-oranges comparisons. When talking
about Forth, you have both feet planted firmly in the embedded systems
space. You talk about systems that aren't general purpose, but are
designed to be specific in what they do. And the company you now work
for sells chips that are designed for specific functions, not for
general-purpose computing.

So that's where you start, but for some reason the second you begin
talking about C, you move the discussion somewhere else entirely. It
doesn't matter that the vast array of micros being used in embedded
systems don't have any operating system on the target. It doesn't
matter that the majority of these are programmed in C with code that
talks to the bare metal. It doesn't matter that the size of many of
these systems doesn't even allow for a minimal operating system. It
doesn't matter that for years, magazines that target the embedded
systems community have talked about commonly-used techniques in C for
using various models of cooperative multitasking (round robin task
lists, message passing, a variety of state machine models, etc.).

None of that (and much more) matters to you. To you, C programmers have
a "mindset" that forces them to require an operating system on the
target, and write code that is far above the bare metal.

The problem is that you know better-- you have to know better-- but if
you talked about C programmers who target embedded systems then your
rants wouldn't work.

The thing is, you're right when you're talking outside the embedded
systems space. C programmers writing code for general-purpose systems
do expect an operating system to both provide services and to abstract
away the underlying machine for portability. But that's not C for
embedded systems-- supposedly what you're talking about.

> The first reads BEGIN AGAIN. All Forth programmers are
> suppose to be able to read that. It is suppose to be simple.
> It does not imply hidden background tasks or watchdogs.
> Thinking it is dozens of times more complicated than it
> is misses the power of Forth and is an error. It isn't C.

do {
} while(1);

I don't see a bug there. I don't see a hidden background task.

> What makes Forth fundamentally different than C and
> gives it some fundamental advantages over C is that
> it can do things with much less overhead than C. That
> is because in C the idea is that software is bad and
> an OS and hardware traps are needed to protect
> everything from bad software. Bugs are planned, and
> the whole picture is all about the planning for bugs.

Give a concrete example. I will code in C, and then show you the
assembly code generated. You won't see anything in the assembly code
that is unexpected, no reliance on an OS, no hardware traps needed to
protect anything.

Jeff Fox

unread,
May 21, 2006, 12:06:34 AM5/21/06
to
Finally, I do think that despite all the years that some
people never understood that the kind of software
that Chuck Moore was talking about when he said
'good software' was cooperative correct simple and
eligant programs doing exactly what they are suppose
to do and avoiding many errors that other people
cannot see how to avoid.

Context, again, this is about why it is hard to explain
what simple Forth software is and what simple Forth
hardware is to people who are thinking C software
and C hardware. This isn't about 'you' doing something
else and calling that Forth, whoever 'you' are.

This thread is about whether these traditional embedded
Forth sorts of things that I described earliker are easily
mistaken for bugs in C view or might look like they might
need or want the sort of complications that this code avoids.

> 1. begin again \ forever

Every Forth programmer is suppose to be able to read that.
It is simple. There is no confusion about what it says.
It does not specify an error condition and to consider it an
error would be introduce a real error. I would expect that
most programmers in traditional Forth have done it many
times.

> 2. begin ?key until \ no key pressed

Another non-error. Misinterpretting it as an error that needs
hidden background tasks or watchdog timers or interrupts
is sort of the opposite of this simple straightforward code
that does what it says, says what it does and is the
sort of thing that gives Forth an advantage.

> 3. begin 255 p@ 8 and until \ port bit always false

Just like 2, except waiting on an event that might or might
not be a key press. But it does what it says and says
what it does, ad it is clear and simple.

> 4. data rom-address !

Traditional embedded style Forth has always made this sort
of thing easy. Maybe on this project when I wrote to ROM it
gets decoded as io output. Maybe the comment will read,
"turn on the panel light" and it won't be an error at all
either in software or hardware. Writing to ROM could be
something to give us an advantage over hardware or
software that make the real problem harder to solve.

If it confuses solutions for bugs it will introduce REAL bugs.

> 5. : demo 2 0 / ;
> demo

It is unlikely to define demo that way, but division by zero is
'undefined.' So we get to do what we want since we got to
define what / does with 0. And since that is what our code
says we want to do here, we assume that the action that
we want to have associated with division by zero will take
place and that no error is going to happen here.

Throwing an error that we didn't want would be a bug.

> 6. : demo 8123 @ ; \ only 32K byes of memory 0-8000
> demo

Oh, yes, little by little they get more powerful. If we only have
a 15-bit memory space we may be using higher bits for
io and addresses might wrap. That is the way simple fast
and cheap devices will work and the way simple fast software
can take advantage of it and outperform software that has
to follow all a mainframe OS policeman's rules.

This is very typical sort of Forth that can win. We don't think
it should be disqualified because winning code would be
considered a bug or must be dissallowed.

> 7. : demo blah recurse ; \ no return stack manipulation in blah

> demo \ no tail recursion optimization

So it is just a special case of 8. 8 is more general and more
powerful. And as I have explained many times. If you can
use fewer transistors to make a faster lower power circuit
eliminates the possibility of certain states from happening
it may be a big advantage. Avoiding errors is very different
than trapping them and dealing with them at rurntime.

Faster simpler cleaner stacks that can't produce overflow
error states are an advantage and software that can take
advantage of them can avoid dealing with errors that other
hardware and software designs require.

> 8. the difference between the number of items pushed
> to a stack by a program and the number of items poped
> back from the stack is greater than the size of the stack.

But if the number pushed is greater than the number poped
by more than the size of the stack it will overflow right? No,
not if it wraps. By wrapping it will always hold the
maximum amount and will not create an overflow error
nor will an overflow error recovery be required just because
more items were pushed that poped.

We have been doing this for half the history of Forth and
we have reported the power that it offers in simplifying things
speeding things and eliminating error states. We do it
all the time and we explain the advantages over and over.

Consider that you want to write the shortest, fastest and
lower power consuming code that you can to do xyz.
We have been talking about that goal. And after you write
the inner loop of your app you realize that it has a balanced
stack, exactly the same number of DUPs as DROPs. So
you ask yourself, in this embedded Forth what will happen
if I remove the final DROP in the loop?

And you conclude that there is nothing wrong with it, no
error happen, no error condition will be trapped, and you
can leave an extra item on the stack in this inner loop
as long as it doesn't matter. As long as when you leave
the loop you consider the stack empty and you can
treat it like an infinite stack until you declare it empty.

You know the code is smaller, faster, and uses less power.
You know it is not an error and that nothing needs to be
trapped or considered an error. You know that having
smaller, cheaper, faster, and simpler hardware and
software is an advantage. You know that it has an
advantage over using stacks that have to follow all
the rules that C requires for stack use and stack
error handling.

> 9. a program pops from a stack more items than it pushed
> to the stack.

These non-bugs are getting more powerful. The ability to
keep taking the same items off the stack again and again
without generating an error is something that can be
exploited. Since stacks are faster than memory here
and can deliver a repeating pattern faster than reading
it from memory or dealing with hardware stack underflow
trapping it is another win. It is another form of freedom
to beat hardware and software that has to work the
way mainframes work.

And people are suppose to figure out the pattern of the quiz
by now. Nine non-bugs each getting more useful and a
more important example of what distinguishes where
traditional cooperative Forth has gone in the last twenty
years and things that give it an advantage are suppose to
suggest that the biggest non-error is the last.

> 10. hardware that will go to sleep when reading ports and
> waiting for a neighbor to write is in a sleep state
> and neighbors are also a sleep trying to read.

If any of the others were confused for errors it is likely
that this one would be too. This characterized everything
we are doing. If you confuse it with an error you will have
trouble understanding what we do and what advantages
we get by doing it the way we do it. Since it is a bit of a
trick question because we haven't released all the
hardware and software details of what we are doing I
gave everyone more than nine hints.

Understanding how something like this could be a very
powerful thing and how it isn't a bug will be key to further
understanding of what we are doing. So far I haven't seen
people thinking about traditional Forth design techniques
or newbies have much trouble with the concepts. But
those who picture this stuff working like a tiny linear mainframe
running hostile programs instead of a sea of tiny cooperating
Forth programs on a sea of tiny processors have trouble
with the basics.

I talked about this stuff at SVFIG today and people seemed to
understand my points. I didn't get any arguments that Forth
is really a bug. They did laugh a bit about how some of these
traditional ideas are easily confused with bugs by some.

Jeff Fox

unread,
May 21, 2006, 12:20:16 AM5/21/06
to
rickman wrote:
> I think timers are not always the best solution...

If we wanted a timer we could have a timer task or a timer node
or a timer group, or use a timer circuit, but we would not have
an interrupt driven timer. Different paradigm.

> Exactly what is the timer going to detect? Running in a loop is normal
> operation. I would expect software to detect this type of construct
> and not allow it.

Yes, a normal operation. As are all the others where we are.

> I don't agree that this is bad programming. How else do you wait for
> keyboard input or any other external event?

My point is that some see it that way. I don't.

I say it's Forth. He says it's a bug.
I say it's good. He says it's bad.

My point is that we seem to be using different definitions and terms.

What we were refering to as 'good software' he calls bad programming.

It makes you wonder sometimes who does and who doesn't understand
what you write or say.

On a port handshake lockup,

> I don't think you need a timer. What would you be timing??? If both
> CPUs go to sleep waiting on one another, it could be normal if they are
> also waiting on other conditions or you can just detect the mutual wait
> in hardware. No need for a timer either way.

As you say, a timer on the circuit itself would be one option. If it
was
an error there might be several ways of handling it without a timer. Or
sometimes it might not be an error or problem at all.

Jeff Fox

unread,
May 21, 2006, 12:29:48 AM5/21/06
to
ben yates wrote:
> > 1. begin again \ forever
>
> Software error. But have you _ever_ used such a loop in your programming?

Thousands of times. Maybe I wanted to halt a program as simply and
completely at some spot for debugging. Maybe I wanted to see only
a single address frozen on the address bus. Maybe I wanted to see
exactly how much power was being drawn by the processor when it
was doing exactly what I told it to do.

jump $ is very basic idea.

> I have - usually at end of program to keep the screen current. Usually
> when debugging.

Sure, in fact it might be the only way to end some program!

> > 2. begin ?key until \ no key pressed
>
> User error - press a key! :) Not a software or hardware error.

;-) I will, I will. But I haven't yet and I want it to wait for me.

> Not an error.
> Perhaps the software _could_ be more robust.

Sure. But I only asked about 'hardware errors' that needed trapping.

> Not an error, perhaps. Was used in some instances for bank-switching.

> Here, a hardware trap of div by 0 is nice, I admit... but I don't agree


> that it has to be a NMI.

> Depends on the architecture as to what happens, it may "wrap" by design.


> Or your system may have ROM above this, see previous answer to #4.

7, 8, 9, and 10 also depend on the architecture ( and view) and as I
have explained they cause no error conditions for us.

> Application design issue.

Indeed it could be a software error. If we are running someone
else's hostile software we might have a problem with it. If we
use cooperative software there are ways to assist with
application design issues.

Jeff Fox

unread,
May 21, 2006, 12:35:16 AM5/21/06
to
Coos Haak wrote:
> >> 1. begin again \ forever
>
> Normal use in embedded processing. At reset, the watchdog timer will start
> counting and when an overflow occurs, it resets the system.
> The user task between begin and again must therefore regularly reset the
> watchdog timer before a reset could interrupt its task. Only when the task
> is someway halted, the WDT can reset the system and the process can resume
> normally.

That might be a normal thing to do, if you have a watchdog timer
and your application needs to occasionally restart itself for some
reason.
If you new all that when you wrote the BEGIN AGAIN you probably would
not have written the comment that said \ FOREVER

If you as the programmer wrote and intended FOREVER and didn't know
about a watchdog timer programmed by someone else that is going to
reset the system under you now have a bug.

If you as the programmer did know that BEGIN AGAIN was going to
wait for the watchdog the comment should have said
\ wait here for the watchdog timer to reset the system

But that is just a case of bad commenting not of a hardware error.
The code says BEGIN AGAIN \ FOREVER and if it doesn't there is
a hardware error that needs to be fixed.

Jeff Fox

unread,
May 21, 2006, 12:50:55 AM5/21/06
to
Anton Ertl wrote:
> >9. a program pops from a stack more items than it pushed
> > to the stack.

Ok. I know I have explained how it should not be seen as an error
in what we do and how we have considered it normal for a very long
time.

> That is normal. Most Forth programs consume some values from the
> stack.

We agree. But I am pretty sure it is only because you read the
question backwards and so got the correct answer.

To check my hypothesis I tried gForth to see if it sees and error.

Gforth 0.6.2, Copyright (C) 1995-2003 Free Software Foundation, Inc.
Gforth comes with ABSOLUTELY NO WARRENTY; for details type 'license'
Type 'bye' to exit
ok
: demo compiled
1 2 3 compiled
drop drop drop drop compiled
; ok
: test compiled
demo compiled
." this is not an error!" compiled
; ok
test this is not an error!
*the terminal*:10: Stack underflow
test
^^^^
Backtrace:
ok

Anton Ertl

unread,
May 21, 2006, 2:34:42 AM5/21/06
to
"Jeff Fox" <f...@ultratechnology.com> writes:
>Anton Ertl wrote:
>> >9. a program pops from a stack more items than it pushed
>> > to the stack.
...

>> That is normal. Most Forth programs consume some values from the
>> stack.
>
>We agree.

After reading your other comments (hey, I'm reading your comments for
a change!), I doubt it, for this item.

>But I am pretty sure it is only because you read the
>question backwards and so got the correct answer.

Maybe you were not clear enough in your question (and that's not
limited to this item).

>To check my hypothesis I tried gForth to see if it sees and error.
>
>Gforth 0.6.2, Copyright (C) 1995-2003 Free Software Foundation, Inc.
>Gforth comes with ABSOLUTELY NO WARRENTY; for details type 'license'
>Type 'bye' to exit
> ok
>: demo compiled
> 1 2 3 compiled
> drop drop drop drop compiled
>; ok
>: test compiled
> demo compiled
> ." this is not an error!" compiled
>; ok
>test this is not an error!
>*the terminal*:10: Stack underflow

: demo 1 2 3 drop drop drop drop ; ok
: test demo ." this is not an error!" ; ok
1 test this is not an error! ok

New standard: http://www.forth200x.org/forth200x.html
EuroForth 2006: http://www.complang.tuwien.ac.at/anton/euroforth2006/

Jeff Fox

unread,
May 21, 2006, 10:42:45 AM5/21/06
to
Anton Ertl wrote:
> After reading your other comments (hey, I'm reading your comments for
> a change!), I doubt it, for this item.
>
> >But I am pretty sure it is only because you read the
> >question backwards and so got the correct answer.
>
> Maybe you were not clear enough in your question (and that's not
> limited to this item).

The simplest explaination would be that people who don't read
the comments are the one who don't understand them. They
might seem a lot clearer to you if you read them. It certainly
provides a simple explanation for your confusion about the
most basic terms we use.

We say good, you think bad. We say Forth you say bad programming.
We say good means cooperative, simple and free. You say good means
safely hostle, complicated and restricted. We say Forth you say
bad C. You say C we say bad Forth.

I read your definition of terms. You igore ours because it makes
a distinction between a C approach and a Forth approach. This
is what we define as what defines Forth and lets it win over C.
You cannot accept this and would rather ingore the tradition
that Forth isn't C.

You ignore what people say about traditional Forth and how it
works and only pay attention to a mix of C and a little Forth-like
behavior on top. And you argue with what people who do
traditional Forth say, or you ignore it because they don't
think like C programmers.

> >*the terminal*:10: Stack underflow
>
> : demo 1 2 3 drop drop drop drop ; ok
> : test demo ." this is not an error!" ; ok

except gforth insists that it is an error.

> 1 test this is not an error! ok

I tried it again. gForth still throws an error.
the program lies about it not being an error in gforth
then crashes out an error message saying
Stack underflow just as I expected, confirmed and
posted. I find it odd that you posted that it doesn't.

Your comments about waiting for characters being a bug
sounds to me like you are just thinking in Unix and
trying to map some Forth into that world.

But thanks again for demonstrating my point that it
is easy for some people to confuse everything about
the design of cooperative Forth programs, what we
call good software for bugs in their world of hostile
programs. So I suppose I should also thank you
for not reading the comments that explain why we
call Forth good so that you could provide an example
of how some people might confuse each thing for a
bug.

Bernd Paysan

unread,
May 21, 2006, 3:02:31 PM5/21/06
to
Jeff Fox wrote:
>> 1 test this is not an error! ok
>
> I tried it again. gForth still throws an error.
> the program lies about it not being an error in gforth
> then crashes out an error message saying
> Stack underflow just as I expected, confirmed and
> posted. I find it odd that you posted that it doesn't.

It probably depends on the plattform. We can only ensure that it behaves
like it should on plattforms that supports propper mmap() functionality. I
have no problem getting the errors I like to see on Linux, but won't
guarantee that it works fine on Windows or DOS.

--
Bernd Paysan
"If you want it done right, you have to do it yourself"
http://www.jwdt.com/~paysan/

Jeff Fox

unread,
May 21, 2006, 3:59:01 PM5/21/06
to
I wondered if he had just fixed the bug in another version
and that the one I download from the web would throw
a stack underflow error in a situation that is not an
error in the kind of embedded Forth that I had been talking
about.

Whenever someone says to me that a bug isn't their
bug because it is in the OS that they called I am inclined
to point out to them that they chose to call that OS in that
way and that if they did that they should accept that it IS
their bug.

But ok. If it worked in Linux gForth then maybe Anton
getting one right was not a mistake on his part like I
assumed.

John Passaniti

unread,
May 21, 2006, 4:10:37 PM5/21/06
to
Jeff Fox wrote:
> This thread is about whether these traditional embedded
> Forth sorts of things that I described earliker are easily
> mistaken for bugs in C view or might look like they might
> need or want the sort of complications that this code avoids.

This thread is actually about both your poor communication skills and
your inability to have a discussion without creating a straw-man. This
thread is how you discuss Forth in a embedded systems context, but
refuse to talk about C in the same context. And this thread is about a
fundamental intellectual dishonesty on your part, coupled with more
logical fallacies than I have time to look up the Latin names for.

Let's dive into your latest stream of context-free nonsense:

>> 1. begin again \ forever
>
> Every Forth programmer is suppose to be able to read that.
> It is simple. There is no confusion about what it says.
> It does not specify an error condition and to consider it an
> error would be introduce a real error. I would expect that
> most programmers in traditional Forth have done it many
> times.

It is impossible to say if this is an error or not because you didn't
provide any context. If the statement prior to begin turns on the x-ray
generator aimed at the patient's head, it is a very serious error. If
the statement prior to begin was a message on the front panel saying
"please cycle power to complete firmware update" then it isn't an error.

So what's the context? You don't say.

>> 2. begin ?key until \ no key pressed
>
> Another non-error. Misinterpretting it as an error that needs
> hidden background tasks or watchdog timers or interrupts
> is sort of the opposite of this simple straightforward code
> that does what it says, says what it does and is the
> sort of thing that gives Forth an advantage.

It is impossible to say if this is an error or not because you didn't
provide any context. Is ?key detecting a keystroke on a console's
keypad? If so, it's not an error since you're waiting on human input.
Is ?key tied to a serial port giving status on a fly-by-wire plane's
flaps? If so, it could be a very serious error.

>> 3. begin 255 p@ 8 and until \ port bit always false
>
> Just like 2, except waiting on an event that might or might
> not be a key press. But it does what it says and says
> what it does, ad it is clear and simple.

Yet again, it is impossible to say if this is an error or not because
you didn't provide any context. Does the port bit go false when the
battery level in the child's toy sitting on a shelf drops below a
threshold? Or does the port bit go false when the hardware driving the
cardiac stimulator fails? I think there is a difference there, but you
refuse to provide any context.

>> 4. data rom-address !
>
> Traditional embedded style Forth has always made this sort
> of thing easy. Maybe on this project when I wrote to ROM it
> gets decoded as io output. Maybe the comment will read,
> "turn on the panel light" and it won't be an error at all
> either in software or hardware. Writing to ROM could be
> something to give us an advantage over hardware or
> software that make the real problem harder to solve.

C doesn't care if you write to ROM addresses. You're free to do that:

*((char*) rom_address) = 42;

What the underlying hardware does is a matter of how you have the
address lines hooked up. I have certainly designed systems (programmed
in C) that write to ROM addresses to drive front panel LEDs, to shift
out data to a '595, to address write-only hardware, to tickle external
watchdogs, and probably other examples I can't recall. There is no
error there, and the technique is well-known in the embedded systems world.

However, as always, context matters. If there is no hardware there but
just a ROM, then the statement is clearly an error. But you don't
provide the context, so the question is meaningless.

>> 5. : demo 2 0 / ;
>> demo
>
> It is unlikely to define demo that way, but division by zero is
> 'undefined.' So we get to do what we want since we got to
> define what / does with 0. And since that is what our code
> says we want to do here, we assume that the action that
> we want to have associated with division by zero will take
> place and that no error is going to happen here.

On the majority of embedded systems I've programmed in C over the past
20-something years, division is implemented as a library routine.
That's either because (like on the Z80) there is no division
instruction, or because (like on the 8051 and HC08 family) there is a
divide instruction, but it is of limited precision. And as such, I've
had complete control over handling of division by zero, and could make
it do whatever I like. No C compiler I have ever used has prevented me
from compiling the code (although many will issue a warning, which is
appropriate and can always be disabled).

So while C code running on a general purpose processor with a general
purpose operating system may indeed throw an exception, I thought we
were talking about embedded systems here. So again, context matters,
but you don't offer it.

>> 6. : demo 8123 @ ; \ only 32K byes of memory 0-8000
>> demo
>
> Oh, yes, little by little they get more powerful. If we only have
> a 15-bit memory space we may be using higher bits for
> io and addresses might wrap. That is the way simple fast
> and cheap devices will work and the way simple fast software
> can take advantage of it and outperform software that has
> to follow all a mainframe OS policeman's rules.

There are currently two embedded systems in the world (both incidentally
written in C) where I have exploited this modulo addressing, and it
isn't an error-- it's part of the hardware and software design. C (of
course) had no problem with it.

But here we go again, what is the context? Are you describing a system
where this is part of the design and thus not an error? Or are you
describing an unintentional addressing past the limit of addressability?
You don't say (of course), so the example is meaningless.

>> 7. : demo blah recurse ; \ no return stack manipulation in blah
>> demo \ no tail recursion optimization

C would also allow this:

void demo(void) {
blah();
demo();
}

There may be some C compilers that attempt to do the obvious tail
recursion optimization, but none of the microcontroller C compilers I
have do, and gcc (with the default level of optimization) doesn't
either. So C will let you code this without complaint.

So again, since we don't have C complaining at all about this, so we
need to switch the discussion to the processor the code runs on. On
microcontrollers with constrained hardware stacks (6502, HC05, some 8051
derivatives), this code would fill the stack endlessly with the return
address of demo. It wouldn't be an error, and the processor would
happily execute the code forever. I can't see how that would be useful,
but if the programmer who wrote it had a reason for it, C is happy to
comply and the underlying hardware will faithfully execute it.

But what's the context? What processor are we talking about? What
real-world technique is this performing? Tell us the processor, show us
a real-world application the technique (not trivial "demo"), and your
example might make sense. Until then, it's meaningless because there is
no context.

>> 8. the difference between the number of items pushed
>> to a stack by a program and the number of items poped
>> back from the stack is greater than the size of the stack.

In most (but certainly not all) C compilers, a function call is composed
of the following steps:

1. Arguments are passed on a stack.
2. The function is called and returns.
3. The stack is adjusted to remove the arguments pushed.

In this case, the calling convention doesn't allow for your scenario,
since the stack is cleaned up after the return of the function. But
many C compilers also offer alternate calling conventions, typically to
interface to code from other languages. Specifically, many offer the
calling convention usually used by Pascal:

1. Arguments are pushed on a stack.
2. The function is called.
3. The function is responsible for popping off the arguments.
4. The function returns.

This would allow for your scenario, although the function called
couldn't be C (since the compiler would adjust the stack). You could
call a Forth word from C like this, or you could call a C function
compiled with the standard calling convention. In any case, this is
something that C doesn't have any comment on. This is more the domain
of the code generated by the compiler and the linker. But it can
certainly be done if there is a reason to do so.

So again, we have to talk about the hardware, not C. And again, you
aren't providing context. Is the system designer exploiting some
element of the processor's design, or is this a bug? You don't give
specifics, so again, your example is meaningless.

>> 9. a program pops from a stack more items than it pushed
>> to the stack.

C certainly allows this:

#include <stdarg.h>

void example(int x, ...) {
va_list arg;
va_start(args, x);
printf("arg 1 = %d\n", x);
printf("arg 2 = %d\n", va_arg(args, int));
printf("arg 3 = %d\n", va_arg(args, int));
va_end(args);
}

... later in the code...

example(1);

Here I've defined function example that will consume three arguments,
but I've only passed one argument to it. What will the two arguments
be? It depends entirely on the context of the system. In one platform
I've used, the third argument would be the return address of the caller.
In other cases, it would be garbage.

But in any case, C certainly allows this, and it isn't an error. It
might be useful in some kind of profiling application, or it might be
helpful in some other way. C doesn't care, and assumes you know what
you're doing.

So what's the context? What processor are we talking about? You don't
say, making your arguments meaningless.

>> 10. hardware that will go to sleep when reading ports and
>> waiting for a neighbor to write is in a sleep state
>> and neighbors are also a sleep trying to read.

This doesn't involve C at all. The compiler will let you generate code
that allows you to access a port. It doesn't impose any restrictions on
what happens to the larger system when you access those ports. In fact,
although it isn't used for communication, many microcontrollers have
ports or memory locations that when written to put the processor into a
sleep mode, waiting for some event to occur. C is completely agnostic
about this and doesn't consider it an error in the least.

I just had a funny idea. There are a number of C compilers out there
(lcc, vbcc, gcc) for which you can write back-end code generators to
target any system you like. Based on what little technical data has
been released on IntellaSys's chips, it doesn't sound difficult to come
up with a C compiler back-end that generates code for IntellaSys's
chips. What would Jeff say when C code targeting his company's chips
does exactly what he claims it can't do? (Answer: He would come up
with some other equally idiotic argument as a distraction.)

> I talked about this stuff at SVFIG today and people seemed to
> understand my points. I didn't get any arguments that Forth
> is really a bug. They did laugh a bit about how some of these
> traditional ideas are easily confused with bugs by some.

This is like President Bush going to speak in front of friendly neocon
groups. Just as I wouldn't expect tough questions from the neocons to
the President, you aren't likely to be challenged on your claims in a
Forth user group. But if you were instead to stand in front of a bunch
of C programmers who actually do embedded systems work (not the
straw-men you're inventing who don't), I'm sure the result would be far
different.

You would be primarily asked about context, and you would be told that
your argument makes no sense because it lacks context. You start off
talking about embedded systems, but then shift the context to general
purpose systems running general purpose operating systems when it suits
your argument. That's intellectual dishonesty coupled with logical
fallacy. And oddly, you wear both as a badge of honor.

So in summary, none of the examples you provided are errors to this
embedded systems programmer. They aren't errors because your discussion
lacks specificity and context, and they aren't errors because they are
actual techniques I have used in C in my embedded systems work.

Here's a radical idea, Jeff. Before you invent straw-men for your next
nonsensical argument, feel free to pass your questions to me first. As
a embedded systems programmer who uses C, I can point out the idiotic
nonsense sooner so you won't embarrass yourself too much. And gosh, you
might actually learn about what real-world embedded systems programmers
do and think-- something I assume would be useful in your role at
IntellaSys.

Marcel Hendrix

unread,
May 21, 2006, 6:19:01 PM5/21/06
to
Bernd Paysan <bernd....@gmx.de> writes Re: hardware errors, do C and Forth need different things in hardware?
[..]

> It probably depends on the plattform. We can only ensure that it behaves
> like it should on plattforms that supports propper mmap() functionality.
[..]

0.6.2 is the current release, according to http://www.jwdt.com/~paysan/gforth.html.

( gforth-fast.exe )


Gforth 0.6.2, Copyright (C) 1995-2003 Free Software Foundation, Inc.

Gforth comes with ABSOLUTELY NO WARRANTY; for details type `license'
Type `bye' to exit


: demo 1 2 3 drop drop drop drop ; ok

: test demo ." this is not an error!" ; ok


1 test this is not an error! ok

( gforth-itc.exe )


Gforth 0.6.2, Copyright (C) 1995-2003 Free Software Foundation, Inc.

Gforth comes with ABSOLUTELY NO WARRANTY; for details type `license'
Type `bye' to exit


: demo 1 2 3 drop drop drop drop ; ok

: test demo ." this is not an error!" ; ok


1 test this is not an error! ok

( gforth-ditc.exe )


Gforth 0.6.2, Copyright (C) 1995-2003 Free Software Foundation, Inc.

Gforth comes with ABSOLUTELY NO WARRANTY; for details type `license'
Type `bye' to exit


: demo 1 2 3 drop drop drop drop ; ok

: test demo ." this is not an error!" ; ok


1 test this is not an error! ok

-marcel

Jeff Fox

unread,
May 21, 2006, 6:40:34 PM5/21/06
to
Great! Sometimes it is very useful to know that I was wrong.
Thanks.

John

unread,
May 21, 2006, 6:49:15 PM5/21/06
to
Anton Ertl wrote:
> "Jeff Fox" <f...@ultratechnology.com> writes:
>>To check my hypothesis I tried gForth to see if it sees and error.
>>
>>Gforth 0.6.2, Copyright (C) 1995-2003 Free Software Foundation, Inc.
>>Gforth comes with ABSOLUTELY NO WARRENTY; for details type 'license'
>>Type 'bye' to exit
>>ok
>>: demo compiled
>>1 2 3 compiled
>>drop drop drop drop compiled
>>; ok
>>: test compiled
>>demo compiled
>>." this is not an error!" compiled
>>; ok
>>test this is not an error!
>>*the terminal*:10: Stack underflow
>
>
> : demo 1 2 3 drop drop drop drop ; ok
> : test demo ." this is not an error!" ; ok
> 1 test this is not an error! ok
>
> - anton

Apples and oranges: Anton (and Marcel) put a "1" on the stack before executing "test" and Jeff did not.

Jeff Fox

unread,
May 21, 2006, 7:40:20 PM5/21/06
to
I have the impression that people would prefer that I don't
try to respond to your posts and focus on answering
their questions. But unless someone asks again that
I not bother I will try.

John Passaniti wrote:
> C doesn't insist on anything.

Only on C being C.

> Back a couple years ago, you wrote one of your typically leading
> messages asking about the executable size of a simple "Hello World"
> program in C. I happened to be working with a C compiler for
> microcontroller at the time (ImageCraft's HC08), and so I compiled some
> code to see the size. The result was around a couple hundred bytes,
> assuming one used puts to display the string instead of the overkill
> printf that's in most canonical examples. A minimal printf shot the
> size to about 1800 bytes. And in either case, that was the *entire*
> code, including startup and the vector to allow the processor to run the
> program. There was no OS on the target. This was code that talked to
> the bare metal.
>
> Your reply at the time was "nice."

It was nice. I hadn't thought of that kind of simplified definition of
a 'hello world program.' So I did the same sort of thing that you
had talked about in this embedded C style hello world. One version
was only about a hundred times smaller than yours, and the
other was only a couple of dozen times smaller.

I didn't want an apples to organges comparison since I had at
first been talking about a traditional hello world display to a video
terminal. So when you wanted to compare that to a simplfied
version I wrote a simplfied version too for comparison that
would be more fair and got the same kind of results.

> I really get tired of your apples-to-oranges comparisons. When talking
> about Forth, you have both feet planted firmly in the embedded systems
> space. You talk about systems that aren't general purpose, but are
> designed to be specific in what they do. And the company you now work
> for sells chips that are designed for specific functions, not for
> general-purpose computing.

General-purpose is a meaningless buzzword. There is no such thing.
Realtime embedded processing is general purpose realtime embedded
processing. Mainframe batch processing is general purpose limited
mainframe batch processing. Typical desktop processing is general
purpose toy desktop computer processing. But the 'general' purpose
is simply the kind of processing that is going on.

General purpose processing on PC has a different meaning that it
did twentyyears ago. It has a different meaning than general purpose
dsp processing, general purpose symbol processing, general purpose
floating point number crunching, or general purpose io response
programs. They are all general purpose and all limited and all
different.

All chips are designed for specific purposes. There is no such thing
as a general purpose chip. It is a meaningless argument. There is
no general purpose hardware, there is no general purpose language.
There have not even been many efforts to even try to invent a
general purpose language and those failed terribly.

All human natural languages are different and express different ideas.
These different languages express the differences between cultures.
All programming languages are different and express different ideas.
These different languages express the differences between cultures.
Attempts to translate often result in things being lost in translation
because there is no such thing as a general purpose language
that it can express everything in every other language. Everyone
knows that cultural things get lost in translation.

> So that's where you start, but for some reason the second you begin
> talking about C, you move the discussion somewhere else entirely. It
> doesn't matter that the vast array of micros being used in embedded
> systems don't have any operating system on the target. It doesn't
> matter that the majority of these are programmed in C with code that
> talks to the bare metal. It doesn't matter that the size of many of
> these systems doesn't even allow for a minimal operating system. It
> doesn't matter that for years, magazines that target the embedded
> systems community have talked about commonly-used techniques in C for
> using various models of cooperative multitasking (round robin task
> lists, message passing, a variety of state machine models, etc.).

Sometimes two languages use the same words, like good, like multitask,
like OS, to mean very different things because they assume a different
context. Since most of the confusion I encounter comes from people
assuming a C context instead of Forth context and trying to translate
the terms they hear there is confusion. Sometimes I address the
source of that confusion and look at how some terms mean different
things.

Any idiot can try to cause confusion by purposely taking things
out of one context and putting them in another where what was
true now becomes false. And any good sophist will try to convince
others that the original statements that were true in their original
context are somehow now really false.

> None of that (and much more) matters to you. To you, C programmers have
> a "mindset" that forces them to require an operating system on the
> target, and write code that is far above the bare metal.

Not quite. But they expect a lot more bare metal if they are thinking
C.
That has been the point of this thread in my mind. I know it your mind
it is a thread talking about how you feel personally about me.

I say the C mindset expects hardware that resembles and works
like mainframes or minis, hardware designed to deal with that set
of restricted problems. I say it is not general purpose hardware.
It is C purpose hardware. C expects and demands C purpose hardware.

Forth expects less. It can live with more, it can easily run on C
purpose
hardware because it is more 'general purpose' than C. And Forth
purpose
hardware needs less than C purpose hardware because it expects
cooperative software not hostile software, the biggest problem one has
to deal with in C purpose hardware and software.

Does general purpose mean hostile? If that is all someone thinks there
is then the answer is yes, all software is hostile therefore general
purpose
means dealing with hostile software. If that is how one defines
'general
purpose' then yes.

But I maintain that 'general purpose' must include all cases, not just
the problems that come along with minicomputers and mainframes
running multiuser or batch programs using one of the popular
mainframe OS. That's a special case of computing if ever there
was one.

> The problem is that you know better-- you have to know better-- but if
> you talked about C programmers who target embedded systems then your
> rants wouldn't work.

The problem you have is that you don't like my definition that general
purpose must include Forth and that if it intentionally excludes Forth
it is a specialized form of computing, not general purpose. The
problem
that you have is that I don't accept that C means general purpose. It
doesn't.

> The thing is, you're right when you're talking outside the embedded
> systems space. C programmers writing code for general-purpose systems
> do expect an operating system to both provide services and to abstract
> away the underlying machine for portability. But that's not C for
> embedded systems-- supposedly what you're talking about.

That's not general purpose. That's C OS purpose and it is really very
specialize as it has to deal with a long list of problems that just
don't
exist in many other forms of computing that really need to be
covered by the term general purpose.

> do {
> } while(1);
>
> I don't see a bug there. I don't see a hidden background task.

Good. I don't either. But I only see a code snippet not the whole
application or system just like the example I gave.

And since in that context it is what it is, it is clearly not a bug.
If that is a bug then C is a bug. Likewise if BEGIN AGAIN
is a bug that must not be allowed then Forth is a bug.

> > What makes Forth fundamentally different than C and
> > gives it some fundamental advantages over C is that
> > it can do things with much less overhead than C. That
> > is because in C the idea is that software is bad and
> > an OS and hardware traps are needed to protect
> > everything from bad software. Bugs are planned, and
> > the whole picture is all about the planning for bugs.
>
> Give a concrete example. I will code in C, and then show you the
> assembly code generated. You won't see anything in the assembly code
> that is unexpected, no reliance on an OS, no hardware traps needed to
> protect anything.

If I wrote an example of code that needed no hardware traps and had
no reliance on an OS then I would expect you to be able to make a
copy of it, fairly closely in some other enviroment. It might or might
not be as small and clean and that mostly depends on the program
and the hardware. I expect that you could copy something.

Of course if I add real world constraints you will lose. If I choose
the problem, if I choose the target, if I choose the contraints
then confounding C is easy. Without knowing the odds, the
target, and the problem to be solved claiming that one language
can do whatever another language can do is absurd.

I must admit it would be fun to go somewhere where I could
put my money where my mouth is and take a lot of money
from a troublesome fool. But it would be too easy, too unfair,
and no one would learn anything that they don't already know.

I would love to take you up on that, but I think that no one would
learn
anything because they know you would fail. And I don't think you
would learn anything because I would expect you to just sluff it off
and come back the next day denying that it ever happened, denying
that you have ever been wrong about any of this stuff, and going
back to more personal complaints about me.

And it wouldn't be fair anyway to expect you to write code for free
since you are a professional. You would be giving me a huge advantage
if I choose the weapons and the place of the engagement and that
would be very fair either. I would be willing to give you lots of
advantages and lots of odds, headstart, relaxed requriements
for you etc., but it would still be a sucker bet.

And I know that people don't want to see me respond to your
personal stuff, or try to make this about you like you want to
make it about me. So we really shouldn't try the programming
challange.

But thanks for the questions that let me clarify my positiion
about things like, C programmers are so arrogant that they
tell you C is general purpose. Maybe they all think that
they are generals.

Jeff Fox

unread,
May 21, 2006, 8:20:13 PM5/21/06
to
The context of each question was clearly stated as whether it
should be catagorically considered a bug needing hardware
to trap and fix without any other context.

All code when put into the wrong context will be wrong. That
was not the question.

The questions were all like this, "Does the follow Forth code
do what the comment says or it is a bug that *always* needs fixing
in *every* possible case, maybe even needing hardware traps?"

BEGIN AGAIN \ forever

If
that means 'forever' or until power is cycled or reset is pressed
and that *could* be valid code
then it should *NOT* be catagorically considered a bug
and it should *NOT* be disallowed either by the compiler
or by the hardware.

If
it is simply a bug in *all* cases
then the software or hardware should prevent it
or fix it.

As far as I got you got the answers right whenever
you left the questions in the orginal context.

Jerry Avins

unread,
May 21, 2006, 9:58:04 PM5/21/06
to
John wrote:

For a program to pop more than it pushes is an error. Anton and Marcel
showed that for a word, it is not. Jeff's straw-man assertion was too
strong, and he was corrected. If not for history, I'd have done it myself.

Jerry
--
Engineering is the art of making what you want from things you can get.
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

John Passaniti

unread,
May 21, 2006, 10:52:32 PM5/21/06
to
Jeff Fox wrote:
> The questions were all like this, "Does the follow Forth code
> do what the comment says or it is a bug that *always* needs fixing
> in *every* possible case, maybe even needing hardware traps?"

Given that criteria, *none* of the examples you posted are categorically
*always* considered errors to a C programmer, since I can easily show at
least one case (usually taken from my past and current experience) where
they are not considered errors. So your entire argument fails right
there. You're making grandiose claims about C programmers and "C think"
and here I am providing a counterexample.

Again, you talk about Forth in an embedded systems context, but when you
talk about C, you refuse to do the same. You compare apples to oranges,
which of course is nothing new to you. You've been delighting
comp.lang.forth with your fruit-salad nonsense for years.

> BEGIN AGAIN \ forever
>
> If
> that means 'forever' or until power is cycled or reset is pressed
> and that *could* be valid code
> then it should *NOT* be catagorically considered a bug
> and it should *NOT* be disallowed either by the compiler
> or by the hardware.

It isn't disallowed by C. Any functioning C compiler will generate code
that does exactly what it says. The equivalent C code is either:

while (1)
;

Or...

do {
} while (1);

Format as you like, the compiler doesn't care.

Okay, dispensing with the question of C, let's move next to the
hardware. Code this in a C compiler for any of the microprocessors I
typically use (Z80-family, 6502-family, 8051, HC08, ColdFire, ARM, and
probably others), and they will gladly allow that code to run until the
end of time or the next power cycle, which ever comes first.

So if it isn't disallowed by C, and isn't disallowed by the hardware...
what exactly is your point again?

> If
> it is simply a bug in *all* cases
> then the software or hardware should prevent it
> or fix it.

There are two cases to consider:

Your code is clearly a bug in *some* cases, but since C (like Forth)
can't tell if this is a bug or the actual intent of the programmer, C
will faithfully compile the code to do what the programmer wants-- just
like Forth. C puts absolutely no barrier to the programmer here and
does what the programmer wrote. And since we're talking about embedded
systems here and not general purpose computing, we typically don't have
any operating system on the target that could possibly complain either.

So we turn to hardware. Here again, the code may certainly be a bug in
*some* cases, but the microprocessor can't know that. So on smaller
microprocessors, the decision is to simply ignore the issue-- processors
like the Z80-family, 6502-family, 8051-family, and many others typically
don't have any kind of watchdog in the system at all. If the specific
application calls for a watchdog (for example safety-critical systems),
it is added externally and thus becomes a decision by the system
designer. In processors that that have integrated watchdogs, I have yet
to see any microprocessor or microcontroller where the programmer
couldn't disable it if they knew it wasn't necessary.

> As far as I got you got the answers right whenever
> you left the questions in the orginal context.

You didn't provide the context for each example, except possibly in your
own head. I wish you would be honest about that, but for some reason
you feel the need to lie. You wrote a message that was intentionally
ambiguous and vague so that you could make another one of your grandiose
points that went nowhere when held up to the light of day.

It must be a Zen thing-- I guess you're always trying to find balance.
For every worthwhile insight you provide comp.lang.forth, you feel the
need to balance it with bullshit straw-men arguments that don't make any
sense. But don't worry Jeff, I'm sure you can issue more speeches in
front of audiences who won't question you. Must do wonders for your ego.

Jeff Fox

unread,
May 22, 2006, 6:14:17 PM5/22/06
to
I did a few futher tests and found it is actually a bit more
compliated. Some Forths will allow one to drop items
from the stack and it apparently just resets the stack
pointer to the bottom of the stack each time and causes
no error.

Some Forths will allow the error to happen and won't
throw out of a program when it happens. They may
report a stack underflow when they get to the command line
: demo drop ." ok " ;
: test demo cr ." still running " ;
: it test cr ." no errors " ;

doesn't display an error message until it hits the command line.

: demo 10 0 do drop loop ;

does the same thing in displaying a message when it hits
the command line in swiftforth.

: demo 1000000 0 do drop loop ;

crashes the environment

My assertion, was that it has not been an error for us for
fifteen years. My assertion was that it was seen as an
error by some despite the fact that we see it as a nice
exploitable feature. My assertion was that the way it
was implemented in some Forth it would cause a crash.

I was right about all that, so I don't see how anyone
should see that my valid demonstration of how 'some'
people do see it as an error is a straw man. Jerry
has repeated that he see it as an error.

But we don't think it has to be an error. We agree that
if you see it as an error, and implement it as an error
then it IS an error for you. I won't go so far as to say
that it was an error by you if you implemented it that way.
I would say it is an error by you if you still think that
it *has* to be an error.

The whole point was to ask if some people see errors
where other people don't. The answer is yes. And
even in ANS Forth it seems it has a lot to do with the
implementation.

Dropping something from the bottom of a stack might
or might give a warning or an error in ANS Forth it
seems. It might put a message on the command line.
It might crash the system. Or it might do nothing
except readjust the pointer to the bottom of the stack.

It is not an error where we live, and that is hard for some
people to understand. Maybe someone will be able to
communicate to some that what we do is real and does
exist and that it is different that what remember about
Forth from thirty years ago in a few ways. One of them
is that dropping garbage off the bottom of the stack
is a useful thing and not an error condition for us.

Despite this being a simple idea it is a stumbling block
for many who cling to the thirty year old practice and
even older notions. I notice that Pic processors have
a stack wrap feature. Some users like it and say it
simplifies their programming. Some users say that
it is different and that they don't like that. Some say
that they want to use C and those crazy wrapping
stacks make that difficult. The problem that people
are used to what people are used to is not unique
to us.

Bernd Paysan

unread,
May 22, 2006, 4:58:53 PM5/22/06
to
Marcel Hendrix wrote:

I don't know what Jeff wanted to see, but IMHO the critical point is when
you *not* have the 1 on the stack before you call test. The question then
is: Does Gforth catch the stack problem before it prints "this is not an
error!" or does it print this message and then realize that the stack is
empty.

The latter is the case when we don't have hardware or OS support for
detecting the empty stack when it actually happens.

jmdra...@yahoo.com

unread,
May 23, 2006, 4:55:06 PM5/23/06
to

Jeff Fox wrote:

> This thread is about whether these traditional embedded
> Forth sorts of things that I described earliker are easily
> mistaken for bugs in C view or might look like they might
> need or want the sort of complications that this code avoids.
>
> > 1. begin again \ forever
>
> Every Forth programmer is suppose to be able to read that.
> It is simple. There is no confusion about what it says.
> It does not specify an error condition and to consider it an
> error would be introduce a real error. I would expect that
> most programmers in traditional Forth have done it many
> times.

I agree. Not an error. It's an endless loop that's obviously
documented as an endless loop by the "\ forever". A bug
is when someone accidently creates an endless loop.
For example someone forgetting to increment a list
pointer.

> > 2. begin ?key until \ no key pressed
>
> Another non-error. Misinterpretting it as an error that needs
> hidden background tasks or watchdog timers or interrupts
> is sort of the opposite of this simple straightforward code
> that does what it says, says what it does and is the
> sort of thing that gives Forth an advantage.

Hmmm...ok. I'd call this a "documentation quirk".
The code is clear. Keep looping until a key is
pressed. Why didn't the comment just say that?

begin ?key until \ wait until key pressed

Anyway, if the keyboard is unplugged at this point that's
a hardware error. ;) Of course, assuming hotplugging
the keyboard is ok, it's easily fixable.

> > 3. begin 255 p@ 8 and until \ port bit always false
>
> Just like 2, except waiting on an event that might or might
> not be a key press. But it does what it says and says
> what it does, ad it is clear and simple.

Another commenting quirk (to me anyway). The code is
clear. The comment isn't. Why would you expect
the port bit to ALWAYS be false if there's a chance there
might be an event when it's TRUE? I'd rather see:

begin 255 p@ 8 and until \ port bit false unless event X

Maybe "event X" is critical temperature of nuclear reactor
reached. Maybe the code after this loop is "initiate
emergency shutdown".

> > 4. data rom-address !
>
> Traditional embedded style Forth has always made this sort
> of thing easy. Maybe on this project when I wrote to ROM it
> gets decoded as io output. Maybe the comment will read,
> "turn on the panel light" and it won't be an error at all
> either in software or hardware. Writing to ROM could be
> something to give us an advantage over hardware or
> software that make the real problem harder to solve.
>
> If it confuses solutions for bugs it will introduce REAL bugs.

The first computers I programmed on used memory
mapped I/O. (TRS-80 model 4 and color computer).
"Peeking" and "Poking" ROM was legal. Admittedly
this was beyond much of what I was doing at the time.

> > 5. : demo 2 0 / ;
> > demo
>
> It is unlikely to define demo that way, but division by zero is
> 'undefined.' So we get to do what we want since we got to
> define what / does with 0. And since that is what our code
> says we want to do here, we assume that the action that
> we want to have associated with division by zero will take
> place and that no error is going to happen here.
>
> Throwing an error that we didn't want would be a bug.

Ok. I honestly never thought of that. But I think that's
dependent on:

A) defining your own CPU or
B) redefining "/" as a word rather than a primative

I tested # 5 on Pentium ColorForth (the version I have
anyway) and it locks up. I suppose I could redefine
the "/" to check and see if the divisor is 0 and take
some action other than executing the Pentium
division primative. But wouldn't that slow my code
down? Still I suppose this doesn't apply if your
talking about Forth running on a Forth chip. And
I'm guessing you're giving us another "hint" about
the new Intellasys chips. ;)

> Consider that you want to write the shortest, fastest and
> lower power consuming code that you can to do xyz.
> We have been talking about that goal. And after you write
> the inner loop of your app you realize that it has a balanced
> stack, exactly the same number of DUPs as DROPs. So
> you ask yourself, in this embedded Forth what will happen
> if I remove the final DROP in the loop?

Ok. That's pretty cool. I had to read it a few times to
understand.

> > 9. a program pops from a stack more items than it pushed
> > to the stack.
>
> These non-bugs are getting more powerful. The ability to
> keep taking the same items off the stack again and again
> without generating an error is something that can be
> exploited. Since stacks are faster than memory here
> and can deliver a repeating pattern faster than reading
> it from memory or dealing with hardware stack underflow
> trapping it is another win. It is another form of freedom
> to beat hardware and software that has to work the
> way mainframes work.

Also interesting.

> And people are suppose to figure out the pattern of the quiz
> by now. Nine non-bugs each getting more useful and a
> more important example of what distinguishes where
> traditional cooperative Forth has gone in the last twenty
> years and things that give it an advantage are suppose to
> suggest that the biggest non-error is the last.
>
> > 10. hardware that will go to sleep when reading ports and
> > waiting for a neighbor to write is in a sleep state
> > and neighbors are also a sleep trying to read.
>
> If any of the others were confused for errors it is likely
> that this one would be too. This characterized everything
> we are doing. If you confuse it with an error you will have
> trouble understanding what we do and what advantages
> we get by doing it the way we do it. Since it is a bit of a
> trick question because we haven't released all the
> hardware and software details of what we are doing I
> gave everyone more than nine hints.

Ok. Here's how I see this might work. One or more
of the sleeping processors is waiting for a signal
external to the chip? For example a digital audio
signal comes in and causes a cascade of chips
waking up in sequence?

Regards,

John M. Drake

John Passaniti

unread,
May 25, 2006, 2:14:06 AM5/25/06
to
Jeff Fox wrote:
> I have the impression that people would prefer that I don't
> try to respond to your posts and focus on answering
> their questions. But unless someone asks again that
> I not bother I will try.

I honestly don't care if you respond to me or not. You have
consistently shown in the past that you aren't interested in real
discussion where your statements are challenged, counterexamples are
provided, and your logic is examined.

>> C doesn't insist on anything.
>
> Only on C being C.

Wow, how Zen. The thing is what it is. Why not write that on some rice
paper and hang it from a cherry blossom tree?

> It was nice. I hadn't thought of that kind of simplified definition of
> a 'hello world program.' So I did the same sort of thing that you
> had talked about in this embedded C style hello world. One version
> was only about a hundred times smaller than yours, and the
> other was only a couple of dozen times smaller.

One thing that I find amusing about you is how you apply different
standards in order to win arguments. In past conversation, you have
insisted that C programmers include the size of the operating system and
any libraries in with the size of their program. And at least for
embedded systems, I fully agree, they should.

Yet you don't seem to do the same when talking about Forth. You claim
your Forth version of the "Hello World" program was a "hundred times
smaller" than the 192 bytes I gave. I'll assume that means it was 92
bytes long. Are you honestly telling me that you have a Forth compiler
that is less than 92 bytes long? Last I checked, the smallest
Forth-like language I knew of ("False") was around 1k bytes long.

Please post the source code for this Forth compiler that's 92 bytes
long. It's so short, it shouldn't take you any time to post the source.

No, unless you were lying (which with you is always a possibility),
you're probably comparing apples to oranges again. Yes Jeff, if I write
"Hello World" in assembly language for the same processor, I can get it
down to about 32 bytes, including all code needed (processor
initialization, a routine to write to the UART, and a simple loop to
output the characters). So what you're probably doing here is not
talking about Forth, but talking about cross-compiling to a different
processor that needs less initialization than the processor I'm using,
and you're probably not initializing RAM.

Wow, that's compelling.

Of course, none of this matters. Your original question was based on
your continued misunderstanding of the differences between C programmers
targeting operating systems and C programmers targeting embedded
systems. You were expecting to hear about a "Hello World" program that
was kilobytes if not megabytes long, and my statement that an embedded
version of the code (which was your question) was 192 bytes kind of
knocked your argument out of the water.

The fact you can generate less code isn't the point, since you're either
not including the size of Forth, or you're talking about coding the
equivalent in assembly language.

> I didn't want an apples to organges comparison since I had at
> first been talking about a traditional hello world display to a video
> terminal. So when you wanted to compare that to a simplfied
> version I wrote a simplfied version too for comparison that
> would be more fair and got the same kind of results.

The equivalent for writing to video (typically a block of memory) takes
slightly less code:

#include <string.h>

void main(void) {
strcpy((char*) 0x8000, "Hello World!");
}

This code assumes that video memory starts at 0x8000 in RAM. Since you
didn't specify where video memory was located, I used an address from a
system I've used in the past. Total size of this application code is
165 bytes.

If your have a different video system in mind, please provide specifics.

> General-purpose is a meaningless buzzword. There is no such thing.

More semantic games. I am clearly using "general purpose" to
differentiate between embedded systems and non-embedded systems. If you
still have a hard time understanding the difference, I suggest you read
this white paper:

http://www.intellasys.net/resources/EmbeddedProcessors.pdf

You might know the author. He doesn't seem to have a problem seeing the
difference between embedded applications (which are dedicated systems
and thus not general purpose).

> Any idiot can try to cause confusion by purposely taking things
> out of one context and putting them in another where what was
> true now becomes false.

Stop calling yourself an idiot.

> Not quite. But they expect a lot more bare metal if they are thinking
> C. That has been the point of this thread in my mind. I know it your
> mind it is a thread talking about how you feel personally about me.

Again, the counterexamples to your statement exist all around you, but
you choose to ignore them. Ignoring the fact that I know *no* embedded
systems programmers who code in C that expect anything more than the
ability of the compiler to generate code. They don't expect operating
systems. They don't expect the underlying processor will have exotic
support for multitasking. They don't expect *anything* more than what
the processor itself can do, and what the hardware connected to it is
designed for.

> I say the C mindset expects hardware that resembles and works
> like mainframes or minis, hardware designed to deal with that set
> of restricted problems. I say it is not general purpose hardware.
> It is C purpose hardware. C expects and demands C purpose hardware.

Yet you provide *zero* examples to illustrate this claim, and I can
provide endless counterexamples. You show no real-world system that
illustrates your claim because you know you can't. The moment you are
forced away from comparing apples to oranges, your argument falls flat
on it's face.

It's simple Jeff. If you make a claim, you should be able to
demonstrate that claim. And here, such a demonstration requires more
than just you saying so. It requires real world examples. You provide
none.

>> do {
>> } while(1);
>>
>> I don't see a bug there. I don't see a hidden background task.
>
> Good. I don't either. But I only see a code snippet not the whole
> application or system just like the example I gave.

Nonsense. You code example was this:

BEGIN AGAIN \ forever

Where is the "whole application or system" described?

> And since in that context it is what it is, it is clearly not a bug.
> If that is a bug then C is a bug. Likewise if BEGIN AGAIN
> is a bug that must not be allowed then Forth is a bug.

It is neither a bug in Forth or C because you di