At 10/23/2013 08:30 PM, Paul Gilmartin wrote:
>OK. Pure HLASM. I've long wondered why division by zero is permitted
>in arithmetic expressions when otherwise overflows (even in division)
>are reported as errors.
>
>The only rationale I can think of (and a poor one) is that it was
>initially an implementation oversight that was so rapidly codified
>by use that when it was discovered no repair was feasible.
>
>-- gil
For several of you that were confused by this, let me first point out
that Gill's question pertained to division allowed in the Assembler
at assembly time, not in runtime machine instruction execution.
More specifically, here are a couple of Assembler examples showing
what is allowed:
&ANSWER SETA 12/0
ANSWER EQU 12/0
In both cases, the assigned value is 0.
The reason that this useful is that this quirk can be exploited to
create, for example, a MAX or MIN function that is evaluated at
assembly time. (Maybe this has changed, but the last time I looked,
the Assembler did not offer native MAX and MIN functions.)
Here's how:
Below is some commentary from a macro of mine that needs to compute,
at assembly time, the size of a buffer that has to be big enough to
hold around 50 or so variations of a control block. Following that
commentary, I will try to translate this stuff into plainer English.
Note, the following will display best with a fixed pitch font. If
necessary, copy/paste it all into NOTEPAD for better readability.
Anyway, here it is:
*************************************************************
* *
* Required length of AUTOPARM. *
* *
* The following EQUs calculate the length that the *
* AUTOPARM, TWAPARM and RSTKPARM fields need to be in order *
* to hold the largest of the above defined parameter maps. *
* It does this by calculating the maximum of all AnnnnL *
* symbols, and it does that by repeatedly calculating the *
* maximum of a given AnnnnL symbol against the maximum of *
* all prior AnnnnL symbols. *
* *
* The computation is made possible by the following two *
* facts: *
* (1) The assembler defines x/0 to =0. *
* (2) All divisions are integral with no remainder or *
* fraction. *
* So each MAX computation looks like this: *
* *
* *
* oldmax oldmax [This is non-0 ] *
* newmax = ------ / ------ * oldmax [if and only if] *
* newlen newlen [oldmax=>newlen] *
* *
* newlen newlen [This is non-0 ] *
* + ------ / ------ * newlen [if and only if] *
* oldmax oldmax [newlen=>oldmax] *
* *
* newlen oldmax [This is non-0 ] *
* - 0 - ------ / ------ * newlen [if and only if] *
* oldmax newlen [newlen=oldmax ] *
* *
* Note, the " - 0 - " is present simply for spacing *
* reasons: Each of the following EQU statements is so long *
* that it has to be continued for a total of three lines. *
* The extra "-0" shifts the statement definition such that *
* no variable symbol name is broken by a continuation *
* character. This makes future editing somewhat easier. *
* *
*************************************************************
SPACE 3
ABEGIN EQU 1 STARTING POINT (CAN'T =0)
SPACE 1
AAD64Q EQU (ABEGIN/AAD64L)/(ABEGIN/AAD64L)*ABEGIN+(AAD64L/ABEGIN)/(|
AAD64L/ABEGIN)*AAD64L-0-(ABEGIN/AAD64L)*(AAD64L/ABEGIN)*|
ABEGIN
* MAX(1,AAD64L)
SPACE 1
AAFINQ EQU (AAD64Q/AAFINL)/(AAD64Q/AAFINL)*AAD64Q+(AAFINL/AAD64Q)/(|
AAFINL/AAD64Q)*AAFINL-0-(AAD64Q/AAFINL)*(AAFINL/AAD64Q)*|
AAD64Q
* MAX(AAD64L,AAFINL)
etc. etc. etc
Basically, in order to compute a maximum of two values you need to
add together three terms:
- One that equals the first value but only when it is high or equal.
- One that equals the second value but only when it is high or equal.
- One that adjusts for the doubling that occurs when both terms are equal.
For each of these terms, they must resolve to zero when their
particular criteria are not met. Two facts about assembly time
arithmetic are what makes this possible:
- The assembler permits n/0=0.
- Division results are always integers. Remainders are discarded.
Let's just look at the first of these terms from the above example:
(ABEGIN/AAD64L)/(ABEGIN/AAD64L)*ABEGIN [+...]
I'll translate this into something more readable:
(A/B)/(A/B)*A
Here's a better layout (better when your font is courier):
A/B
--- * A
A/B
To show what happens when A is low, I'll let A=2 and B=20:
2/20 0
---- * 2 becomes --- * 2 becomes 0*2 becomes 0.
2/20 0
To show what happens when A is high, I'll let A=70 and B=6:
70/6 11
---- * 7 becomes ---- * 7 becomes 1*7 becomes 7.
70/6 11
I'll leave it to you to work out the remainder of the computations.
IHTH,
Dave Cole
ColeSoft Marketing
414 Third Street, NE
Charlottesville, VA 22902
EADDRESS:
dbc...@colesoft.com
Home page:
www.colesoft.com
Facebook:
www.facebook.com/colesoftware
YouTube:
www.youtube.com/user/colesoftware