Windfall wrote:
KC9UDX wrote:
OK thanks. I was starting to think you had paragraphs of comments in your code.
I do describe the entry and exit conditions at the top of each routine. I always do that, but it's downright essential in sources this big.
Indeed. Every function in my code, unless very trivial, has a comment header that, at minimum, tells what the entry register values must be and what the exit register values will be, such as in this 65C816 assembly language subroutine header:
Code:
;================================================================================
;
;lbopbo: CONVERT LOGICAL BLOCK OFFSET TO PHYSICAL BLOCK OFFSET
;
; —————————————————————————————————————————————————————————
; Calling syntax: LONGX ;16 bit index
; LDX LBOLSW ;LBO LSW
; LDY LBOMSW ;LBO MSW
; JSR LBOPBO ;convert LBO to PBO
;
; Exit registers: .A: entry value
; .B: entry value
; .X: PBO LSW (1,2)
; .Y: PBO MSW (1,2)
; DB: entry value
; DP: entry value
; PB: entry value
; SR: NVmxDIZC
; ||||||||
; |||||||+———> 0: okay
; ||||||| 1: PBO wrapped — error
; +++++++————> entry value
;
; Notes: 1) The returned PBO is zero-based.
;
; 2) Content is undefined if an error occurs.
; —————————————————————————————————————————————————————————
Depending on the complexity of what the function does, the comment header could be quite wordy, viz:
Code:
;===============================================================================
;
;mktime: CONVERT BROKEN-DOWN TIME TO CALENDAR TIME
;
; ————————————————————————————————————————————————————————————————————————
; Calling syntax: per altzone ;pointer to daylight saving time zone data
; per timezone ;pointer to standard time zone data
; per time ;pointer to calendar time field (2)
; per tm ;pointer to broken-down time structure (1)
; jsr mktime
;
; Exit registers: .A: entry value
; .B: entry value
; .X: entry value
; .Y: entry value
; DB: entry value
; DP: entry value
; PB: entry value
; SR: NVmxDIZC
; ||||||||
; |||||||+———> 0: okay
; ||||||| 1: conversion error
; +++++++————> entry value
;
; Notes: 1) tm must point to a broken-down date & time structure of type
; tm, in which fields are as follows:
;
; Offset Field Description
; ——————————————————————————————
; $00 tm_sec seconds
; $02 tm_min minutes
; $04 tm_hour hour
; $06 tm_mday day-of-month
; $08 tm_mon month
; $0A tm_year year
; $0C tm_wday day-of-week¹
; $0E tm_yday day-of-year¹
; $10 tm_isdst DST flag
; ——————————————————————————————
; ¹Input values are ignored & will be replaced
; by data computed from the input date.
;
; All fields are of size s_int. Refer to the tm structure def-
; inition in include/calendrics/tm.asm.
;
; 2) The value returned in time is the number of seconds that have
; elapsed since the "epoch" (discussed below). time must be of
; size s_time_t, which is defined in include/calendrics/tm.asm.
;
; 3) time is assumed to be UTC, not local time. See below informa-
; tion for more details.
;
; 4) This function does not verify that the data in tm are valid.
; An error exit will occur if an intermediate computation causes
; an over- or underflow, or attempts division by zero. Nonsens-
; ical dates, such as Feb 30, or times, such as 61 minutes, may
; produce unexpected results.
; —-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-
; mktime converts the broken-down time in the structure tm into the number
; of seconds that have elapsed since the "epoch," which is defined as Sun-
; day, October 1, 00:00:00 UTC, 1752. The conversion is accurate for all
; dates from the epoch to December 31, 23:59:59 UTC, 9999.
;
; This conversion is different than that used in most UNIX-like operating
; systems, in which the epoch is Thursday, January 1, 1970 & time_t is a
; signed integer. UNIX generates a negative result for dates prior to the
; epoch, with a maximum regression to December 13, 1901 in the case of 32
; bit time_t definitions. This implementation of mktime generates an un-
; signed integer of size s_time_t for any date & time within the accept-
; able range.
;
; maktime makes reference to several external variables for time zone &
; daylight saving time (DST) conversion data:
;
; § timezone
;
; This variable of s_int size defines the local time zone as a signed
; offset to UTC when standard time is in effect. mktime interprets it
; as follows:
;
; x00000xxxxxxxxxx
; | ||||||||||
; | ++++++++++———> minutes offset from UTC (0-1023)
; +——————————————————> 0: locale is west of UTC
; 1: locale is east of UTC
;
; For example, if timezone is $81E0 the locale is 8 hours east of UTC &
; 28,800 seconds will be subtracted from the computed time value before
; it is returned. If timezone is $0168 then the locale is 6 hours west
; of UTC & 21,600 seconds will be added to the computed time value be-
; it is returned. This scheme accommodates time zones that are not ex-
; act hour multiples east or west of UTC.
;
; § altzone
;
; This variable of s_int size defines the local time zone as a signed
; offset to UTC when daylight saving time is in effect. mktime inter-
; prets it as follows:
;
; x00000xxxxxxxxxx
; | ||||||||||
; | ++++++++++———> minutes east/west of UTC (0-1023)
; +——————————————————> 0: locale is west of UTC
; 1: locale is east of UTC
;
; If altzone is $0000 then it is ignored by & time zone compensation is
; based upon timezone. If timezone & altzone are both $0000 then it is
; assumed that the locale is in the UTC time zone.
;
; Daylight saving time will only apply when tm_isdst in the tm structure
; is $0001. Otherwise, standard time will be assumed, regardless of the
; value of altzone.
;
; Upon a successful conversion, mktime will rewrite all fields in the tm
; structure, as an internal call will be made to localtim to reverse the
; conversion to compute the day-of-week (tm_wday) & day-of-year (tm_yday)
; fields. A side-effect of this reverse conversion is other fields in tm
; may also change, usually because a value prior to conversion was nonsen-
; sical, e.g., a date such as Feb 30.
; ————————————————————————————————————————————————————————————————————————
The above describes the
mktime function I wrote that converts a human-readable form of the local date and time of day into a machine-friendly format. A stack frame has to be set up for the call, and the data structures referred to by the stack frame are populated with new values upon exit. Hence the assembly language equivalent of bloviating.
To those just starting out with assembly language, the above sort of thing may seem to be unnecessarily elaborate and a big time-waster. After all, we all have good memories and never forget anything, right? However, a year or two later when you revisit the function, such as to add features, you'll be glad you committed your thoughts at the time to "paper."
The sames applies regardless of the language being used. In years past, I did a lot of development in Thoroughbred Dictionary-IV, which is a complex timesharing form of BASIC. Like almost all BASIC implementations, Thoroughbred has the
REM (remark) statement for commenting programs. I tended to use it quite liberally, and when the occasion arose in which I would have to maintain a program I had written long ago I didn't have to rely on memory to figure out why I wrote things the way I did.