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.