home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / FASTDA.ZIP / FASTDATE.DOC < prev    next >
Encoding:
Text File  |  1988-04-16  |  7.2 KB  |  136 lines

  1. !FAST! !FAST! !FAST! !FAST! !FAST! !FAST! !FAST! !FAST! !FAST! !FAST! !FAST!
  2.  
  3.   File: FastDate.DOC
  4. Author: David N.Dubois
  5.   Date: 1988.04.16
  6.  
  7. CountDays is a !FAST! routine which tells how many days it has been since a
  8. specific date. It is written in assembly language, and conforms to the far
  9. call conventions of TurboPascal 4.0.
  10.  
  11. It's somewhat cryptic, and filled with magic numbers, but it is fast.
  12.  
  13. Here's how it works.
  14.  
  15. Lines 35 .. 36   Standard procedure prologue for Turbo 4.0
  16.  
  17. Lines 38 .. 40   Gets the Year. Make sure that it is positive.  Let me
  18.                  explain. The procedure does not work with negative years.
  19.                  There are three reasons for this. First, I figured it was
  20.                  useless, particularly if you consider that the Gregorian
  21.                  calender has only been in effect since 1583. Secondly,
  22.                  signed arithemetic would have slowed the procedure
  23.                  slightly, and I didn't think it was worth it. Thirdly,
  24.                  there is no year 0. Year 1 A.D. was preceded by 1 B.C. So
  25.                  should 1 B.C. be represented by 0 or by -1? It's better to
  26.                  un-ask the question. When a negative, or zero, year is
  27.                  used, the function returns MaxLongInt.
  28.  
  29. Line  42         Copy Year into BX. Now there are two copies, one in AX and
  30.                  one in BX.
  31.  
  32. Lines 44 .. 46   Get the Month. Check to see if the month is March or
  33.                  beyond. The idea here, is that you want to count leap days
  34.                  for months after February on a leap year, or months upto
  35.                  February on the year after. Comparing the Month to 3 sets
  36.                  the carry flag if the Month is February or less. Doing an
  37.                  SBB (subtract with carry) will decrement AX if the Month is
  38.                  March or beyond. I will call this value Zeller's Year,
  39.                  since I understand that Mr. Zeller first thought of it.
  40.                  Now we have two different years. The actual year is in BX
  41.                  and Zeller's year is in AX.
  42.  
  43. Line  47         Store Zeller's year for later.
  44.  
  45. Lines 48 .. 49   Shifting right twice divides Zeller's year by 4. This tells
  46.                  us how many leap years have passed since the (alledged)
  47.                  year 0.
  48.  
  49. Lines 51 .. 55   Now we find out how many days have been eaten up by the
  50.                  months that have passed. This uses the DaysIntoYear table
  51.                  shown on line 31. First, we set DI to the position of the
  52.                  table. Actually it is set to 2 bytes before the start of
  53.                  the table. This is because the first month, January, is
  54.                  stored as a 1 rather than 0. Recall that CL contains the
  55.                  month. Its still there after it was loaded in line 44.
  56.                  Since the table is of words, we multiply the Month by two,
  57.                  by shifting left, to find the index into the table. We
  58.                  clear CH (by XORing it with itself) so that now CX contains
  59.                  2*Month. Adding that to the start of the table (less 2)
  60.                  gives us the actual offset of the number we want. The table
  61.                  is stored in the code segment, so we use a segment over-
  62.                  ride when looking up the number. This number is added to
  63.                  AX. So now, AX contains the number of leap days, plus the
  64.                  number of days in the preceding months of this year.
  65.  
  66. Lines 57 .. 58   Now we add on the days into the month. Recall that CH is
  67.                  still cleared from line 39, so loading CL with the month is
  68.                  like load CX with the month. We add into CX this time. Now
  69.                  CX contains the sum of: the days into the year, plus all
  70.                  the leap days. AX has been freed for other use.
  71.  
  72. Lines 60 .. 61   Now we ask, how many days have passed since the
  73.                  (hypothetical) year 0, if we count just the normal 365 days
  74.                  per year. Recall that BX contains the actual year that was
  75.                  placed there in line 42. Setting Ax to 365 and MULtiplying
  76.                  leaves the product in the DX:AX pair.
  77.  
  78. Lines 62 .. 63   We add the value in CX to this. The ADC is necessary since
  79.                  this number will probably be larger than 16-bits.
  80.  
  81. Lines 65 .. 68   Now we almost have our answer. All we have to do now is
  82.                  take into account those pesky years that are multiples of
  83.                  100. Recall that multiples of 100 are not leap years,
  84.                  except for multiples of 400. This requires a time-consuming
  85.                  division operation, so I wanted to avoid it if possible. I
  86.                  figured that most calls on the function would have years in
  87.                  the 20th and 21st century, and since there were none of
  88.                  these strange leap years during the period 1901 .. 2099, I
  89.                  figured I could skip the division in these years, and make
  90.                  up for it somewhere else.
  91.  
  92.                  Remember Zeller's Year? That was stored in SI on line 47.
  93.                  These lines check Zeller's Year, skipping to the end
  94.                  (Magic) if the year is in the 20th or 21st century.
  95.                  Otherwise we have to adjust for the 100's.
  96.  
  97. Lines 70 .. 71   Our answer so far, stored in DX:AX is transferred to CX:DI
  98.                  while we do our division.
  99.  
  100. Lines 72 .. 73   We are going to divide Zeller's Year by 100. We transfer
  101.                  the year, in SI, to the DX:AX pair. DX will always be zero.
  102.  
  103. Lines 74 .. 76   Divide Zeller's Year by 100. This will give us the number
  104.                  of multiples of 100 that we have already counted as leap
  105.                  years, even though they may not be. This is stored in BX
  106.                  while we make a final adjustment.
  107.  
  108. Lines 77 .. 78   By dividing that number by 4 (by shifting twice), we find
  109.                  out how many years have been multiples of 400.
  110.  
  111. Lines 79         Adding 15 takes into account the fact that we are ignoring
  112.                  years in the range of 1901 .. 2099. Had we done this
  113.                  calcualtion for those years, we would have ended up
  114.                  subtracting 15, so instead we add 15 here.
  115.  
  116. Line  80 .. 81   By adding the multiples of 400, and subtracting the
  117.                  multiples of 100, we have adjusted for the strange leap
  118.                  years. CWD quickly clears out DX for next operation.
  119.  
  120. Line  82 .. 83   Recall that the original un-adjusted count was stored
  121.                  temporarily in CX:DI in lines 70 and 71. Now we add that
  122.                  onto the adjustment, leaving the result back in DX:AX.
  123.  
  124. Line  84         Merge back into the main stream.
  125.  
  126. Lines 86 .. 88   As I explained above, I didn't want to handle negative
  127.                  years. If Year is less than or equal to zero, the function
  128.                  returns MaxLongInt.
  129.  
  130. Lines 90 .. 91   These lines add on a magic number. I'm going to keep the
  131.                  ORIGIN of this number secret.
  132.  
  133. Lines 93 .. 94   Result of function is stored in DX:AX. These lines are the
  134.                  standard post-logue for the Pascal calling sequence.
  135.  
  136.