Editing PEG:TP7 divide by zero bug

Jump to: navigation, search

Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.

The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then save the changes below to finish undoing the edit.
Latest revision Your text
Line 7: Line 7:
 
<code>Delay(x)</code> induces a delay in execution with a duration of <code>x</code> milliseconds. In order to do this, it performs some useless instruction (specifically, decrementing a register) some number of times. For any given delay, the number of times to execute the instruction is likely to differ from one CPU to another, since two CPUs with different speeds take different amounts of time to execute the same set of instructions. TP7 solves this problem by determining, in the initialization code, how many times it can do so in one timer tick. A single timer tick is about 55 ms, so it divides by 55 to determine the number of times it must execute the instruction in one millisecond.<br/>
 
<code>Delay(x)</code> induces a delay in execution with a duration of <code>x</code> milliseconds. In order to do this, it performs some useless instruction (specifically, decrementing a register) some number of times. For any given delay, the number of times to execute the instruction is likely to differ from one CPU to another, since two CPUs with different speeds take different amounts of time to execute the same set of instructions. TP7 solves this problem by determining, in the initialization code, how many times it can do so in one timer tick. A single timer tick is about 55 ms, so it divides by 55 to determine the number of times it must execute the instruction in one millisecond.<br/>
 
<br/>
 
<br/>
The <code>DIV</code> instruction on the Intel x86 architecture is used to divide the dword <code>DX:AX</code>, the number of times to decrement the register in 55 ms, by the word 55, the quotient being stored in <code>AX</code>. Since a 32-bit value is being divided by a 16-bit value, it is possible that the result does not fit into the 16-bit <code>AX</code> register. (For example, if the CPU can perform 55 million decrements in 55 ms, then the result of the division, 1 million, is too large to fit into <code>AX</code>.) When this occurs, the CPU generates a divide exception (INT 0). This exception is caught by the program's RTL, which reports it as error 200, division by zero. (That is, the exception actually occurs in two cases: when division by zero occurs or when the quotient is too large to fit in the destination register, but most programs assume that the former case occurred, since it is far more common than the latter.)
+
The <code>DIV</code> instruction on the Intel x86 architecture is used to divide the dword <code>DX:AX</code>, the number of times to decrement the register in 55 ms, is divided by the word 55, the quotient being stored in <code>AX</code>. Since a 32-bit value is being divided by a 16-bit value, it is possible that the result does not fit into the 16-bit <code>AX</code> register. (For example, if the CPU can perform 55 million decrements in 55 ms, then the result of the division, 1 million, is too large to fit into <code>AX</code>.) When this occurs, the CPU generates a divide exception (INT 0). This exception is caught by the program's RTL, which reports it as error 200, division by zero. (That is, the exception actually occurs in two cases: when division by zero occurs or when the quotient is too large to fit in the destination register, but most programs assume that the former case occurred, since it is far more common than the latter.)
  
 
=Fixes=
 
=Fixes=
 
Fundamentally, the solution to this problem is to use a 32-bit counter for the number of times to execute an instruction per millisecond. Since the source code of the CRT unit is not available, all patches must be applied at the binary level. There are two programs included with our distribution of Borland Pascal 7.0: <code>TPPATCH.EXE</code> and <code>t7tplfix</code> (a <code>.zip</code> file). The former can be used to patch any program compiled with TP/BP 7.0 that is afflicted by the bug by passing it the executable as a command-line parameter (and it will not affect any other executables). The latter patches the CRT unit itself and should be started from within the <code>bin</code> directory. (Any programs compiled after the application of this patch will no longer have the bug.)
 
Fundamentally, the solution to this problem is to use a 32-bit counter for the number of times to execute an instruction per millisecond. Since the source code of the CRT unit is not available, all patches must be applied at the binary level. There are two programs included with our distribution of Borland Pascal 7.0: <code>TPPATCH.EXE</code> and <code>t7tplfix</code> (a <code>.zip</code> file). The former can be used to patch any program compiled with TP/BP 7.0 that is afflicted by the bug by passing it the executable as a command-line parameter (and it will not affect any other executables). The latter patches the CRT unit itself and should be started from within the <code>bin</code> directory. (Any programs compiled after the application of this patch will no longer have the bug.)

Please note that all contributions to PEGWiki are considered to be released under the Attribution 3.0 Unported (see PEGWiki:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!

Cancel | Editing help (opens in new window)