[net.micro.pc] Clock Interrupt Screw-Up?

kpk@gitpyr.UUCP (Kevin P. Kleinfelter) (09/26/85)

I have a section of assembler code which exhibits an interesting anomaly:

  The code works just fine when interrupts are disabled.  However, when
interrupts are enabled the code produces the wrong results.  There is
nothing time-critical in the code -- it merely converts an ASCII encoded
number into a binary value, and back to ASCII, and then prints the result.
The result is always correct when interrupts are disabled, but about
1 in 20 times it is wrong when interrupts are enabled.  The wrong value
appears to be a random value, and appears on a random basis.  The only
interrupt which should be occuring is the clock (timer) interrupt.

Questions:
  Has anyone encountered similar behavior?
  Does the 8088 ALWAYS push and pop the flags correctly    int/rti?
  Are there any known bugs in MSDOS 2.1 's clock interrupt routine?


(The code is rather lengthy or I would post it).

Any suggestions, similar experiences, answers would be appreciated.



DISCLAIMER OF RESPONSIBILITY:
  My employer thinks I am responsible.  I am not.

kim@mips.UUCP (Kim DeVaughn) (10/04/85)

[...]

> I have a section of assembler code which exhibits an interesting anomaly:
> 
>   The code works just fine when interrupts are disabled.  However, when
> interrupts are enabled the code produces the wrong results.  There is
> ...
> number into a binary value, and back to ASCII, and then prints the result.
> The result is always correct when interrupts are disabled, but about
> 1 in 20 times it is wrong when interrupts are enabled.  The wrong value
> appears to be a random value, and appears on a random basis.  The only
> interrupt which should be occuring is the clock (timer) interrupt.


Without seeing the code, this is purely a guess ...

Sounds alot like you've been bitten by the "multiple prefixes on a string-op"
feature of the 8086/8.  Let's say, for example, you code:

		rep movs   ES:byte ptr[DI],CS:[SI]

to move a string.  "rep" is a prefix to the "movs" instruction, but so is
the "CS:" seg-reg override byte.  As long as there's no interruption, this
works just fine.  If a rupt occurs in the middle of the move though, watch
out!

If a rupt had to wait until all repetitions were completed, it might have to
wait quite awhile on large byte counts ... too long for some time-critical
functions.  To avoid this, the 8086 will recognize a rupt (assuming they are
enabled, of course) after a fundemental "unit of operation" is complete.
In this case, that means after a byte has been transfered, CX has been
decremented, SI and DI have been incremented (or decremented), and the test
for CX=0 has been performed.

The problem is that the instruction pointer points to the "rep" prefix while
the string-op is executing, and the "rep" prefix MUST be the prefix just prior
to the string-op itself.  It's the offset of the "rep" that gets pushed on the
stack when a rupt comes in ... and that's where execution resumes after the
rupt handler returns control via an "iret".

Of course NOW the 8086's bus-unit is merrily forming source addresses using
DS:SI rather than CS:SI like we thought we told it to;  it never saw the CS:
override prefix again.  (Yes, Virginia, it *is* supposed to work that way ...
like I said, it's a feature, not a bug, and yes, it is documented ... bahhhh!)

Anyway, if you find any such beasties, just stick a "cli/sti" pair around
the offender, and maybe send a "Thank you" note to those wonderful folk who
brought you segmentation in the first place :-).  Hope this helps.

BTW, anyone know if this stunning example of architectural innovation is still
with us in the 286?

/kim

"Anything free is worth what you pay for it."  --  Lazarus Long

-- 

UUCP:  {decvax,ucbvax,ihnp4}!decwrl!mips!kim
DDD:   415-960-1200
USPS:  MIPS Computer Systems Inc,  1330 Charleston Rd,  Mt View, CA 94043

glen@intelca.UUCP (Glen Shires) (10/07/85)

> [...]
> 
> > I have a section of assembler code which exhibits an interesting anomaly:
> > 
> >   The code works just fine when interrupts are disabled.  However, when
> > interrupts are enabled the code produces the wrong results.  There is
> > ...
> > number into a binary value, and back to ASCII, and then prints the result.
> > The result is always correct when interrupts are disabled, but about
> > 1 in 20 times it is wrong when interrupts are enabled.  The wrong value
> > appears to be a random value, and appears on a random basis.  The only
> > interrupt which should be occuring is the clock (timer) interrupt.
> 
> 
> Without seeing the code, this is purely a guess ...
> 
> Sounds alot like you've been bitten by the "multiple prefixes on a string-op"
> feature of the 8086/8.  Let's say, for example, you code:
> 
> 		rep movs   ES:byte ptr[DI],CS:[SI]
> 
> to move a string.  "rep" is a prefix to the "movs" instruction, but so is
> the "CS:" seg-reg override byte.  As long as there's no interruption, this
> works just fine.  If a rupt occurs in the middle of the move though, watch
> out!
> [...]
all true.
most instructions don't require more than one interrupt.
REP CS: MOVS is an exception.  One fix is the sti/cli, another is avoid
the CS: override (use DS):
> 
> BTW, anyone know if this stunning example of architectural innovation is still
> with us in the 286?
> 
> /kim
> 
The 186/188, and 286 allow multiple prefixes!


-- 
^ ^    Glen Shires, Intel, Santa Clara, Ca.
O O     Usenet: {ucbvax!amd,pur-ee,hplabs}!intelca!glen
 >      ARPA:   "amd!intelca!glen"@BERKELEY
\-/    --- stay mellow

kds@intelca.UUCP (Ken Shoemaker) (10/08/85)

> Without seeing the code, this is purely a guess ...
> 
> Sounds alot like you've been bitten by the "multiple prefixes on a string-op"
> feature of the 8086/8.  Let's say, for example, you code:
> 
> 		rep movs   ES:byte ptr[DI],CS:[SI]
> 
> to move a string.  "rep" is a prefix to the "movs" instruction, but so is
> the "CS:" seg-reg override byte.  As long as there's no interruption, this
> works just fine.  If a rupt occurs in the middle of the move though, watch
> out!
> 
> .........................
> 
> Anyway, if you find any such beasties, just stick a "cli/sti" pair around
> the offender, and maybe send a "Thank you" note to those wonderful folk who
> brought you segmentation in the first place :-).  Hope this helps.
> 
> BTW, anyone know if this stunning example of architectural innovation is still
> with us in the 286?
> 
> /kim
> 
> "Anything free is worth what you pay for it."  --  Lazarus Long
> 
> -- 
> 
> UUCP:  {decvax,ucbvax,ihnp4}!decwrl!mips!kim
> DDD:   415-960-1200
> USPS:  MIPS Computer Systems Inc,  1330 Charleston Rd,  Mt View, CA 94043

Actually, the "normal" order of prefixes puts the repeat prefix before the
segment override prefix, so that what happens then is that you don't move
enough words or whatever.  In this case, the fix is even easier: you just
check the cx register after the string move and loop if it isn't zero.
I agree that this isn't the best of all possible worlds, and this little
feature isn't also featured on the 186 or the 286: they iret you to the
first prefix, so the string move picks up correctly where it left off.
What this has to do with segmentation, I'll never know...
-- 
...and I'm sure it wouldn't interest anybody outside of a small circle
of friends...

Ken Shoemaker, Microprocessor Design for a large, Silicon Valley firm

{pur-ee,hplabs,amd,scgvaxd,dual,qantel}!intelca!kds
	
---the above views are personal.  They may not represent those of the
	employer of its submitter.