TRS-80 DOS - LDOS 5.3.1 for the Model I - DATECONV/CMD Disassembled

Page Customization

Summary:

LDOS 5.3.1 DATECONV/CMD Disassembly - Date-Format Conversion Utility (Model I)

DATECONV/CMD converts a diskette created under LDOS 5.1.4 or earlier to the x.3 time and date directory format introduced with LDOS 5.3 and LS-DOS 6.3. The 5.3 series expanded the accepted date range to 1980-1999 and added a modification time stamp to every directory entry; DATECONV rewrites the older directory records so that date and time information is interpreted correctly under 5.3. The command syntax is DATECONV :d, where :d names the drive to convert.

The utility is a transient /CMD load module. The DOS reads its 628-byte image into memory at 5200H and transfers to 5200H with Register Pair HL addressing the command-line tail. DATECONV parses the drive, confirms the pack is mounted and not write-protected through the resident @CKDRV service, and reads the directory cylinder named by the Drive Code Table. It then decides how the disk should be treated: an older non-x.3 disk that is a bootable SYSTEM disk without the required x.3 system files is refused (matching the manual's instruction to first move x.3 system files onto such a disk with BACKUP), while a disk already in the x.3 format has only its blank-user-access-password files touched so that genuine time stamps are protected.

For each in-use primary directory record that carries an old-style date, DATECONV copies the record's three-bit year field into the extended-dating word - the directory field that under LDOS 5.1.4 held the user access-password hash and under 5.3 carries the packed modification time and extended year. It counts each file it updates, walks every directory sector, writes each modified sector back with the deleted-data address mark LDOS uses for directory sectors, sets bit 3 of the Granule Allocation Table configuration word to mark the whole pack as an x.3 dated disk, and prints the number of files updated. Pressing BREAK during the scan aborts the conversion.

DATECONV issues no RST 28H request of its own. Every service it uses is either a TRS-80 Model I ROM low-core routine or a resident SYS0/SYS entry point, so no system overlay loads while it runs and SYS0/SYS alone is sufficient to cross-reference it.

Variables and Self-Modifying Cells

Address RangePurpose
5348H
1 byte
Drive number patched into the write-sector routine's LD C,00H at 5347H (self-modifying; written at 5222H from the command-line drive).
535AH
1 byte
Drive number patched into the read-sector routine's LD C,00H at 5359H (self-modifying; written at 5225H).
526FH
1 byte
Directory cylinder patched into the LD D,00H at 526EH (self-modifying; written at 5238H from DCT+09H).
52A2H
1 byte
Conversion-mode flag patched into the LD A,00H at 52A1H (self-modifying; written at 5249H). Non-zero on an already-x.3 disk, restricting conversion to blank-access-password records.
52D3H
1 byte
Directory sector-scan limit patched into the LD A,00H at 52D2H (self-modifying; written at 5281H).
52FBH
2 bytes
Saved entry Stack Pointer patched into the LD SP,0000H at 52FAH (self-modifying; written at 5200H).
5472H-5473H
2 bytes
File-conversion counter; incremented at 52BAH for each file updated and formatted into the completion message at 52E9H.
5500H-55FFH
256 bytes
Shared directory sector buffer above the load image, used for every GAT, HIT and directory-record read and write.

Major Routines

AddressRoutineEntry / Exit
5200HProgram Entry and Sign-On
Saves the entry stack, prints the banner, and falls into the drive parser.
Entry: HL = command-line tail. Exit: falls through to 520FH.
5284HMain Conversion Loop
Walks every directory sector and record, converting old-style dates and counting updated files.
Entry: D = directory cylinder, drive patched into the read/write routines. Exit: falls into 52D9H.
52FAHExit Routine
Restores the entry SP and returns success, or diverts to @ABORT on an error under a JCL job.
Entry: HL = return code (0000H/0FFFFH). Exit: RET or JP @ABORT 4030H.
5309HDecimal Count Formatter
Writes a 16-bit value as right-justified ASCII into a five-byte field.
Entry: HL = value, DE = field. Exit: DE preserved.
5322HBreak/Pause Check
Freezes on a pending BREAK and preserves the caller's registers and flags.
Entry: none. Exit: Z when no BREAK pending; caller flags preserved across a freeze.
5344HWrite Directory Sector
Writes the buffer with a deleted-data mark and verifies it.
Entry: D = cylinder, E = sector, C = drive (patched). Exit: RET on success, JP 5362H on error.
5356HRead Directory Sector
Reads a sector into the buffer, accepting the deleted-data mark as success.
Entry: D = cylinder, E = sector, C = drive (patched). Exit: RET on success, HL = 5500H.
5362HError Display via @ERROR
Displays the system message for the code in Register A and exits with an error code.
Entry: A = error code. Exit: JP 5377H then 52FAH.
5369HMessage Error Stubs
Three overlapping entries that display the system-disk, write-protected and abort messages.
Entry: 5369H/536DH/5371H. Exit: JP 52FAH.

Cross-Reference Notes

DATECONV/CMD is a transient utility that issues no RST 28H request of its own. It calls the resident SYS0/SYS services @DSPLY (4467H), @CKDRV (44B8H), GETDCT (478FH), WRPROT (4768H), VERSEC (4772H), RDSECT (4777H), @ERROR (4409H), @LOGOT (447BH), @DIV (44C4H) and @ABORT (4030H), and the TRS-80 Model I ROM low-core routines @PAUSE (0060H) and @KBD (002BH). It reads the resident flags KFLAG$ (4423H, the BREAK bit) and SFLAG$ (430FH, the JCL-active bit). No SYS overlay is loaded while it runs, and nothing in the DOS calls into DATECONV.

Disassembly:

5200H - Program Entry and Sign-On

DATECONV is a transient /CMD utility. The DOS loads its 628-byte load module into memory at 5200H and transfers to 5200H with Register Pair HL pointing at the command-line text that follows the DATECONV keyword. The routine first preserves the stack so it can return cleanly, prints its sign-on banner through the resident video service, and then falls into the drive parser.

5200
LD (52FBH),SP ED 73 FB 52
Self-Modifying Code
Store the current Stack Pointer (the DOS return frame present when DATECONV was entered) into 52FBH, which is the two-byte operand of the LD SP,0000H instruction at 52FAH. The exit routine at 52FAH re-loads SP from this patched operand to discard everything DATECONV pushed and hand control back to the DOS.
5204
PUSH HL E5
Save the command-line pointer (Register Pair HL, addressing the character after the DATECONV command name) onto the stack so it survives the sign-on print, which destroys HL.
5205
GOSUB to the break/pause check at 5322H so any pending BREAK is cleared before conversion begins. The routine returns with the caller's registers intact.
5208
LD HL,5381H 21 81 53
Point Register Pair HL at the sign-on message text stored at 5381H ("DATECONV - LDOS Date Conversion - Version 5.3.1" and the MISOSYS copyright line).
520B
GOSUB to the resident @DSPLY video service at 4467H in SYS0/SYS to display the carriage-return-terminated string that Register Pair HL points at (the sign-on banner at 5381H).
520E
POP HL E1
Restore the command-line pointer (Register Pair HL) that was saved at 5204H, so HL again addresses the character after the DATECONV command name for the drive parser below.

520FH - Command-Line Drive Specification Parse

The command syntax is DATECONV :d. This block skips leading blanks, requires a colon, reads the single drive digit, verifies it is 0-7, and writes it into the drive-number operand of both the sector-read and sector-write routines. A malformed specification jumps to the illegal-drive error stub at 537DH.

520F
LD A,(HL) 7E
Loop Start
Fetch the next command-line character (addressed by Register Pair HL) into Register A while scanning past blanks.
5210
CP 20H FE 20
Compare Register A (the current command-line character) against 20H (ASCII space). If Register A equals 20H the Z FLAG is set, marking a blank to be skipped.
5212
INC HL 23
Advance the command-line pointer (Register Pair HL) to the next character.
5213
If the Z FLAG is set (the character just tested was a blank), LOOP BACK to 520FH to skip it and test the following character.
5215
CP 3AH FE 3A
Compare Register A (the first non-blank command-line character) against 3AH (ASCII colon). A valid drive specification must begin with a colon; if Register A equals 3AH the Z FLAG is set.
5217
If the NZ FLAG is set (the first non-blank character was not a colon), JUMP to the illegal-drive error stub at 537DH.
521A
LD A,(HL) 7E
Fetch the character following the colon (addressed by Register Pair HL) into Register A; this is the drive digit.
521B
SUB 30H D6 30
SUBtract 30H (ASCII zero) from Register A to convert the drive digit from its ASCII code to a binary drive number 0-9.
521D
CP 08H FE 08
Compare the binary drive number (Register A) against 08H. If Register A is below 08H the CARRY FLAG is set (a legal drive 0-7); if Register A is 08H or above the NO CARRY FLAG is set.
521F
If the NO CARRY FLAG is set (the drive number is 8 or greater, out of range), JUMP to the illegal-drive error stub at 537DH.
5222
LD (5348H),A 32 48 53
Self-Modifying Code
Store the binary drive number (Register A) into 5348H, the operand of the LD C,00H at 5347H inside the write-sector routine, so that routine selects this drive.
5225
LD (535AH),A 32 5A 53
Self-Modifying Code
Store the binary drive number (Register A) into 535AH, the operand of the LD C,00H at 5359H inside the read-sector routine, so that routine selects this drive.
5228
LD C,A 4F
Copy the binary drive number (Register A) into Register C, where the resident @CKDRV service expects the drive to check.

5229H - Drive Availability Check

The resident @CKDRV service confirms the drive holds a mounted, ready pack and reports its write-protect status. A missing drive is treated as an illegal drive; a write-protected pack cannot be converted and is reported separately.

5229
GOSUB to the resident @CKDRV service at 44B8H in SYS0/SYS to test the drive selected in Register C. It returns NZ if the drive is not available and sets the CARRY FLAG if the mounted diskette is write-protected.
522C
If the NZ FLAG is set (@CKDRV found no available drive), JUMP to the illegal-drive error stub at 537DH.
522F
If the CARRY FLAG is set (@CKDRV found the diskette write-protected), JUMP to the write-protected message stub at 536DH; a read-only pack cannot be converted.

5232H - Directory Cylinder, GAT Read and Dating-Flag Test

The Drive Code Table entry gives the directory cylinder. DATECONV reads sector 0 of that cylinder (the Granule Allocation Table) and tests the high byte of the GAT configuration word: bit 3 marks a disk that is already in the x.3 extended-dating format. On such a disk DATECONV skips the system-disk gate and converts only files whose access-password word is still blank, protecting genuine x.3 time stamps.

5232
GOSUB to the resident GETDCT service at 478FH in SYS0/SYS, which sets Register Pair IY to 4700H + drive*10H, the base of the Drive Code Table entry for the drive in Register C.
5235
LD A,(IY+09H) FD 7E 09
Fetch DCT+09H (the directory cylinder number for this drive) into Register A.
5238
LD (526FH),A 32 6F 52
Self-Modifying Code
Store the directory cylinder (Register A) into 526FH, the operand of the LD D,00H at 526EH, so the conversion loop reads the directory cylinder rather than cylinder 0.
523B
LD D,A 57
Copy the directory cylinder (Register A) into Register D, the cylinder argument the read-sector routine expects.
523C
LD E,00H 1E 00
Load Register E with 00H, selecting sector 0 of the directory cylinder; sector 0 holds the Granule Allocation Table.
523E
GOSUB to the read-sector routine at 5356H to read the GAT (cylinder in Register D, sector 0 in Register E) into the buffer at 5500H.
5241
LD A,(55CDH) 3A CD 55
Fetch the high byte of the GAT configuration word (buffer 5500H offset CDH) into Register A; this byte carries the disk-format flags.
5244
BIT 3,A CB 5F
Test bit 3 of the GAT configuration byte (Register A). Bit 3 set marks a disk already in the x.3 extended-dating format; the Z FLAG is set when the bit is clear.
5246
If the Z FLAG is set (bit 3 clear, so this is an older non-x.3 disk), JUMP to 524EH to run the system-disk gate before converting.
5249
LD (52A2H),A 32 A2 52
Self-Modifying Code
The disk is already x.3-dated. Store the GAT configuration byte (Register A, now non-zero) into 52A2H, the operand of the LD A,00H at 52A1H, so the record loop switches to the blank-access-password-only test that protects existing time stamps.
524C
Skip the system-disk gate (unnecessary on an x.3 disk) by jumping to the sector-count setup at 526EH.

524EH - System-Disk Detection

On an older non-x.3 disk, DATECONV refuses to convert a bootable SYSTEM disk that does not already carry the x.3 system files, matching the manual: a TRSDOS 6.2, LDOS 5.1 or earlier SYSTEM disk must first have x.3 system files copied onto it with BACKUP. The gate is skipped when bit 7 of the GAT configuration byte marks the pack as exempt, or when the first directory slot examined is unused.

524E
BIT 7,A CB 7F
Test bit 7 of the GAT configuration byte (Register A, still holding the value read at 5241H). Bit 7 set marks a pack exempt from the system-disk gate; the NZ FLAG is set when the bit is set.
5250
If the NZ FLAG is set (bit 7 marks the pack exempt), JUMP past the gate to the sector-count setup at 526EH.
5252
LD E,05H 1E 05
Load Register E with 05H to select sector 5 of the directory cylinder (Register D still holds the directory cylinder from 523BH); this is a directory sector whose first record is tested for use.
5254
GOSUB to the read-sector routine at 5356H to read directory-cylinder sector 5 into the buffer at 5500H.
5257
LD A,(5500H) 3A 00 55
Fetch the first byte of that directory sector (buffer 5500H, the attribute byte of the record in slot 0) into Register A.
525A
AND 10H E6 10
Mask Register A to bit 4, the directory attribute's in-use flag. The Z FLAG is set when bit 4 is clear (the slot is free).
525C
If the Z FLAG is set (the first directory slot is free, so there is nothing that would make this a system disk), JUMP to the sector-count setup at 526EH.
525E
LD DE,0002H 11 02 00
Load Register D with 00H and Register E with 02H, selecting cylinder 0, sector 2; the system-signature byte tested next lives on track 0.
5261
GOSUB to the read-sector routine at 5356H to read cylinder 0, sector 2 into the buffer at 5500H.
5264
LD A,(HL) 7E
Fetch the first byte of that sector into Register A (the read-sector routine returns Register Pair HL still pointing at the buffer base 5500H); this is the system-signature byte.
5265
CP 53H FE 53
Compare the signature byte (Register A) against 53H (ASCII S). If Register A equals 53H the Z FLAG is set, marking a pack safe to convert.
5267
If the Z FLAG is set (signature byte is 53H), JUMP to the sector-count setup at 526EH to proceed with conversion.
5269
CP 63H FE 63
Compare the signature byte (Register A) against 63H (ASCII c), the second accepted value. If Register A equals 63H the Z FLAG is set.
526B
If the NZ FLAG is set (the signature byte is neither 53H nor 63H, so this is an unconvertible SYSTEM disk), JUMP to the message stub at 5369H, which displays "SYSTEM disk conversion requires a 5.3 or 6.3 disk!".

526EH - Directory Sector-Scan Limit

Before the conversion loop, DATECONV works out how many directory sectors it must scan. It reads the third directory sector and derives a sector limit from the ending-record-number field of the record it finds there, capped at 21H, and stores it as the loop bound.

526E
LD D,00H 16 00
Self-Modifying Code
Load Register D with the directory cylinder. The operand shown as 00H was patched at 5238H with DCT+09H, so at run time this is LD D,directory-cylinder.
5270
LD E,03H 1E 03
Load Register E with 03H to select sector 3 of the directory cylinder.
5272
GOSUB to the read-sector routine at 5356H to read directory-cylinder sector 3 (Register D cylinder, Register E sector 3) into the buffer at 5500H.
5275
LD A,(5514H) 3A 14 55
Fetch buffer offset 14H (5500H+14H), the low byte of the ending-record-number field of the first directory record in that sector, into Register A.
5278
SUB 02H D6 02
SUBtract 02H from Register A to discount the GAT and HIT sectors that precede the directory records, leaving a provisional directory sector count.
527A
CP 21H FE 21
Compare the provisional count (Register A) against 21H. If Register A is below 21H the CARRY FLAG is set.
527C
If the CARRY FLAG is set (the count is below 21H and therefore in range), JUMP to 5280H, leaving Register A unchanged.
527E
LD A,20H 3E 20
The count exceeded the limit, so clamp Register A to 20H (the highest sector index before the increment below).
5280
INC A 3C
INCrement Register A by 1 to form the inclusive highest directory sector number the conversion loop will scan.
5281
LD (52D3H),A 32 D3 52
Self-Modifying Code
Store the sector limit (Register A) into 52D3H, the operand of the LD A,00H at 52D2H, which the loop compares against the current sector number to decide when to stop.

5284H - Main Conversion Loop

This is the core of DATECONV. For each directory sector from sector 2 up to the computed limit, it reads the sector and walks its eight 32-byte records. An in-use primary record that carries an old-style date has the low three date bits copied into its extended-dating word, and on an already-x.3 disk only records whose access-password word is still blank (hash 4296H) are touched. After each sector is scanned it is written back.

5284
LD E,02H 1E 02
Load Register E with 02H, the first directory sector that holds records (sectors 0 and 1 are the GAT and HIT). Register D still holds the directory cylinder.
5286
Loop Start
GOSUB to the read-sector routine at 5356H to read the current directory sector (Register D cylinder, Register E sector) into the buffer at 5500H, which the routine leaves addressed by Register Pair HL.
5289
PUSH HL E5
Loop Start
Save the record base pointer (Register Pair HL, addressing the start of the current 32-byte directory record in the buffer) so it can be recovered and advanced after this record is processed.
528A
BIT 7,(HL) CB 7E
Test bit 7 of the record's attribute byte (addressed by Register Pair HL). Bit 7 set marks a secondary (extended) directory record, which carries no date and is skipped; the NZ FLAG is set when the bit is set.
528C
If the NZ FLAG is set (this is a secondary record), JUMP to 52C1H to skip it.
528F
BIT 4,(HL) CB 66
Test bit 4 of the record's attribute byte (addressed by Register Pair HL), the in-use flag. The Z FLAG is set when bit 4 is clear (a free slot).
5291
If the Z FLAG is set (the slot is free), JUMP to 52C1H to skip it.
5294
INC L 2C
Advance the low byte of the record pointer (Register L) by 1, moving Register Pair HL toward record offset 2 (the date byte).
5295
INC L 2C
Advance Register L again so Register Pair HL now addresses record offset 2, the packed date byte (bits 7-3 day, bits 2-0 the low three year bits).
5296
LD A,(HL) 7E
Fetch the packed date byte at record offset 2 (addressed by Register Pair HL) into Register A.
5297
OR A B7
OR Register A with itself to set the flags. The Z FLAG is set when the date byte is 00H (an entry with no date set).
5298
If the Z FLAG is set (the record carries no date), JUMP to 52C1H to skip it.
529A
AND 07H E6 07
Mask Register A to its low three bits, the year value stored in the old date format.
529C
LD C,A 4F
Save the three-bit year (Register A) in Register C; it will be written into the record's extended-dating word.
529D
LD A,L 7D
Copy the low byte of the record pointer (Register L, currently record base + 2) into Register A for arithmetic.
529E
ADD A,10H C6 10
ADD 10H to Register A so it addresses record offset 12H, the access-password word that under LDOS 5.3 carries the packed modification time and extended year.
52A0
LD L,A 6F
Copy the adjusted offset (Register A) back into Register L, so Register Pair HL now addresses record offset 12H.
52A1
LD A,00H 3E 00
Self-Modifying Code
Load Register A with the conversion-mode flag. The operand shown as 00H is 00H on an older disk (convert every dated record) but was patched at 5249H with the non-zero GAT configuration byte on an already-x.3 disk (convert only blank-access-password records).
52A3
OR A B7
OR Register A with itself. The Z FLAG is set when the conversion-mode flag is 00H (older disk, unconditional conversion).
52A4
If the Z FLAG is set (older disk), JUMP to 52B6H to convert the record without the blank-password test.
52A6
PUSH DE D5
Already-x.3 disk path. Save Register Pair DE (the current sector cylinder and number) before the comparison below overwrites it.
52A7
PUSH HL E5
Save the pointer to the record's access-password word (Register Pair HL) so it can be restored after the comparison.
52A8
LD DE,4296H 11 96 42
Load Register Pair DE with 4296H, the hash of eight blanks, i.e. the value an old-style blank user-access password produces.
52AB
LD A,(HL) 7E
Fetch the low byte of the record's access-password word (addressed by Register Pair HL) into Register A.
52AC
INC HL 23
Advance Register Pair HL to the high byte of the access-password word.
52AD
LD H,(HL) 66
Fetch the high byte of the access-password word (addressed by Register Pair HL) into Register H.
52AE
LD L,A 6F
Move the low byte saved in Register A into Register L, so Register Pair HL now holds the record's 16-bit access-password word.
52AF
OR A B7
OR Register A with itself to clear the CARRY FLAG before the subtraction.
52B0
SBC HL,DE ED 52
SUBtract Register Pair DE (the blank-password hash 4296H) from Register Pair HL (the record's access-password word). The Z FLAG is set only when they are equal, i.e. the password is blank.
52B2
POP HL E1
Restore the pointer to the record's access-password word (Register Pair HL) saved at 52A7H.
52B3
POP DE D1
Restore Register Pair DE (the sector cylinder and number) saved at 52A6H.
52B4
If the NZ FLAG is set (the access-password word is not blank, so this record carries a genuine x.3 time stamp), JUMP to 52C1H to leave it untouched.
52B6
LD (HL),00H 36 00
Store 00H into the low byte of the record's extended-dating word (addressed by Register Pair HL), clearing the old blank-access-password hash.
52B8
INC HL 23
Advance Register Pair HL to the high byte of the extended-dating word.
52B9
LD (HL),C 71
Store the three-bit year saved in Register C into the high byte of the extended-dating word (addressed by Register Pair HL), completing the date conversion for this record.
52BA
LD HL,(5472H) 2A 72 54
Fetch the running file-conversion counter (the 16-bit value at 5472H) into Register Pair HL.
52BD
INC HL 23
INCrement the counter (Register Pair HL) by 1 to record that another file has been converted.
52BE
LD (5472H),HL 22 72 54
Store the updated counter (Register Pair HL) back to 5472H. The INC HL above also leaves the NZ FLAG set, which the break check preserves so a normal record advance is not mistaken for an abort.
52C1
GOSUB to the break/pause check at 5322H. It returns Z when no BREAK is pending; a pending BREAK freezes the display and, because the caller's flags are preserved, leaves the non-zero result from the record advance above so the test below aborts.
52C4
If the NZ FLAG is set (the operator pressed BREAK), JUMP to the message stub at 5371H, which displays "Date conversion aborted!".
52C7
POP HL E1
Restore the record base pointer (Register Pair HL) saved at 5289H, addressing the start of the record just processed.
52C8
LD A,L 7D
Copy the low byte of the record base (Register L) into Register A to advance to the next record.
52C9
ADD A,20H C6 20
ADD 20H (32, the directory record length) to Register A so it addresses the next record in the sector. The Z FLAG is set only when the low byte wraps to 00H, i.e. all eight records of the 256-byte sector have been visited.
52CB
LD L,A 6F
Copy the advanced offset (Register A) back into Register L, so Register Pair HL addresses the next directory record.
52CC
Loop End
If the NZ FLAG is set (Register L did not wrap, so records remain in this sector), LOOP BACK to 5289H to process the next record.
52CF
All eight records processed. GOSUB to the write-sector routine at 5344H to write the modified directory sector from the buffer at 5500H back to the disk.
52D2
LD A,00H 3E 00
Self-Modifying Code
Load Register A with the directory sector-scan limit. The operand shown as 00H was patched at 5281H with the highest directory sector number to process.
52D4
INC E 1C
INCrement Register E, the current directory sector number, to move to the next sector.
52D5
CP E BB
Compare the sector limit (Register A) against the current sector number (Register E). If Register A is at least Register E the NO CARRY FLAG is set, meaning more sectors remain.
52D6
Loop End
If the NO CARRY FLAG is set (the current sector is within the limit), LOOP BACK to 5286H to read and convert the next directory sector.

52D9H - Mark Disk Dated and Report Completion

With every directory sector converted, DATECONV sets bit 3 of the GAT configuration byte so the pack is recognised as an x.3 extended-dating disk, writes the GAT back, formats the file count into the completion message, displays it, and returns success.

52D9
LD E,00H 1E 00
Load Register E with 00H to select sector 0 of the directory cylinder (the GAT). Register D still holds the directory cylinder.
52DB
GOSUB to the read-sector routine at 5356H to re-read the GAT into the buffer at 5500H.
52DE
LD A,(55CDH) 3A CD 55
Fetch the high byte of the GAT configuration word (buffer 5500H offset CDH) into Register A.
52E1
OR 08H F6 08
OR Register A with 08H to set bit 3, the flag that marks the disk as being in the x.3 extended-dating format.
52E3
LD (55CDH),A 32 CD 55
Store the updated configuration byte (Register A) back into the GAT buffer at offset CDH (5500H+CDH).
52E6
GOSUB to the write-sector routine at 5344H to write the updated GAT from the buffer at 5500H back to the disk.
52E9
LD HL,(5472H) 2A 72 54
Fetch the final file-conversion count (the 16-bit value at 5472H) into Register Pair HL for display.
52EC
LD DE,53E4H 11 E4 53
Point Register Pair DE at the leading blank field of the completion message at 53E4H (" file(s) updated, conversion complete").
52EF
PUSH DE D5
Save the message-buffer pointer (Register Pair DE) so it can be recovered as the display argument after formatting.
52F0
GOSUB to the decimal formatter at 5309H, which writes the count in Register Pair HL as right-justified ASCII digits into the five-byte field starting at the buffer in Register Pair DE.
52F3
POP HL E1
Recover the message-buffer pointer into Register Pair HL (53E4H), the argument @LOGOT expects.
52F4
GOSUB to the resident @LOGOT service at 447BH in SYS0/SYS to display the carriage-return-terminated completion message (Register Pair HL, at 53E4H).
52F7
LD HL,0000H 21 00 00
Load Register Pair HL with 0000H, the success return code the @CMNDR convention expects (0000H success, 0FFFFH error).

52FAH - Exit Routine

Common exit for both the success and error paths. It restores the entry stack pointer saved at 5200H, then returns to the DOS on success or, when running under a JCL job, diverts to @ABORT on an error code so the job halts.

52FA
LD SP,0000H 31 00 00
Self-Modifying Code
Restore the Stack Pointer. The operand shown as 0000H was patched at 5200H with the DOS return frame's SP, so this discards everything DATECONV pushed. Register Pair HL holds the return code (0000H success or 0FFFFH error).
52FD
LD A,H 7C
Copy the high byte of the return code (Register H) into Register A to test whether the code is zero.
52FE
OR L B5
OR Register A with the low byte of the return code (Register L). The Z FLAG is set only when the whole return code is 0000H (success).
52FF
RET Z C8
If the Z FLAG is set (return code 0000H, success), RETurn to the DOS.
5300
LD A,(430FH) 3A 0F 43
The return code was 0FFFFH (error). Fetch SFLAG$ (the system flags byte at 430FH) into Register A to check whether a JCL job is in effect.
5303
BIT 5,A CB 6F
Test bit 5 of SFLAG$ (Register A), which is set while a Job Control Language job is running. The Z FLAG is set when the bit is clear (no job).
5305
RET Z C8
If the Z FLAG is set (no JCL job active), RETurn to the DOS with the error already reported.
5306
A JCL job is in effect, so JUMP to the resident @ABORT vector at 4030H in SYS0/SYS to terminate the job on the error.

5309H - Decimal Count Formatter

Converts the 16-bit value in Register Pair HL into right-justified ASCII decimal, written backwards into a five-character field that begins at the buffer addressed by Register Pair DE. The field is first blanked so leading positions stay as spaces.

5309
LD B,05H 06 05
Load Register B with 05H, the width of the blank field to clear ahead of the digits.
530B
LD A,20H 3E 20
Load Register A with 20H (ASCII space), the fill character.
530D
LD (DE),A 12
Loop Start
Store a space (Register A) into the field byte addressed by Register Pair DE.
530E
INC DE 13
Advance the field pointer (Register Pair DE) to the next byte.
530F
DECrement Register B and LOOP BACK to 530DH until all five field bytes have been blanked. Register Pair DE now points just past the field.
5311
PUSH DE D5
Save the pointer just past the field (Register Pair DE) so the caller's DE can be restored on exit.
5312
DEC DE 1B
Step Register Pair DE back one byte to the least-significant digit position, where the first digit is written.
5313
LD A,0AH 3E 0A
Loop Start
Load Register A with 0AH (10), the divisor used to peel off one decimal digit.
5315
GOSUB to the resident @DIV service at 44C4H in SYS0/SYS, which divides Register Pair HL by Register A (10), returning the quotient in Register Pair HL and the remainder (the next digit) in Register A.
5318
ADD A,30H C6 30
ADD 30H (ASCII zero) to the digit remainder (Register A) to form its ASCII character.
531A
LD (DE),A 12
Store the ASCII digit (Register A) into the current field position addressed by Register Pair DE.
531B
DEC DE 1B
Step Register Pair DE back one byte to the next-higher digit position.
531C
LD A,H 7C
Copy the high byte of the remaining quotient (Register H) into Register A to test for zero.
531D
OR L B5
OR Register A with the low byte of the quotient (Register L). The Z FLAG is set when the quotient has reached zero and all digits have been emitted.
531E
Loop End
If the NZ FLAG is set (digits remain), LOOP BACK to 5313H to emit the next digit.
5320
POP DE D1
Restore the caller's field pointer (Register Pair DE) saved at 5311H.
5321
RET C9
RETurn to the caller with the count formatted into the buffer.

5322H - Break/Pause Check

Checks the resident KFLAG$ BREAK bit. With no break pending it returns immediately with the Z FLAG set. With a break pending it clears the flag, freezes with a delay, re-freezes if BREAK is pressed again, and waits for a key to be released before continuing; the caller's registers and flags are preserved across the freeze.

5322
PUSH HL E5
Save Register Pair HL so the routine can use it to address the flag byte without disturbing the caller.
5323
LD HL,4423H 21 23 44
Point Register Pair HL at KFLAG$ (the resident keyboard-flag byte at 4423H) whose bit 0 is the BREAK flag.
5326
BIT 0,(HL) CB 46
Test bit 0 of KFLAG$ (addressed by Register Pair HL), the BREAK-pressed flag. The Z FLAG is set when no break is pending.
5328
If the Z FLAG is set (no break pending), JUMP to 5342H to restore Register Pair HL and RETurn with the Z FLAG still set, signalling no abort.
532A
PUSH AF F5
A break is pending. Save Register Pair AF so the caller's accumulator and flags are preserved across the freeze and restored on exit.
532B
PUSH BC C5
Save Register Pair BC across the freeze.
532C
PUSH DE D5
Save Register Pair DE across the freeze.
532D
RES 0,(HL) CB 86
Loop Start
Clear bit 0 of KFLAG$ (addressed by Register Pair HL), acknowledging the BREAK.
532F
LD BC,0B00H 01 00 0B
Load Register Pair BC with 0B00H, the delay count for the freeze pause (Register B = 0BH outer count).
5332
GOSUB to the ROM @PAUSE delay routine at 0060H, which spins for the count in Register Pair BC to hold the display frozen.
5335
BIT 0,(HL) CB 46
Test bit 0 of KFLAG$ (addressed by Register Pair HL) again to see whether BREAK was pressed during the pause. The NZ FLAG is set if it was.
5337
If the NZ FLAG is set (BREAK pressed again), LOOP BACK to 532DH to clear it and pause once more, extending the freeze.
5339
Loop Start
GOSUB to the ROM @KBD scan routine at 002BH, which returns the pressed key in Register A or 00H if no key is down.
533C
OR A B7
OR Register A with itself. The Z FLAG is set when Register A is 00H (no key currently pressed).
533D
Loop End
If the NZ FLAG is set (a key is still held), LOOP BACK to 5339H to wait until it is released.
533F
POP DE D1
Restore Register Pair DE saved at 532CH.
5340
POP BC C1
Restore Register Pair BC saved at 532BH.
5341
POP AF F1
Restore Register Pair AF saved at 532AH, so the caller's accumulator and flags survive the freeze; the flags on return therefore reflect the caller's state before the call, which the conversion loop relies on to signal its abort.
5342
POP HL E1
Restore Register Pair HL saved at 5322H.
5343
RET C9
RETurn to the caller.

5344H - Write Directory Sector

Writes the 256-byte buffer at 5500H back to the current directory sector with a deleted-data address mark, the mark LDOS uses for directory sectors, then verifies it. Any controller error falls through to the @ERROR path. The cylinder is in Register D and the sector in Register E from the caller.

5344
LD HL,5500H 21 00 55
Point Register Pair HL at the 256-byte sector buffer at 5500H, the data source for the write.
5347
LD C,00H 0E 00
Self-Modifying Code
Load Register C with the drive number. The operand shown as 00H was patched at 5222H with the command-line drive, so this is LD C,drive.
5349
GOSUB to the resident WRPROT service at 4768H in SYS0/SYS, which writes the buffer (Register Pair HL) to the drive (Register C), cylinder (Register D) and sector (Register E) using a deleted-data address mark. It returns NZ on a controller error.
534C
If the NZ FLAG is set (the write reported an error), JUMP to the @ERROR display path at 5362H with the error code in Register A.
534E
GOSUB to the resident VERSEC service at 4772H in SYS0/SYS to verify the sector just written; it returns the controller status in Register A.
5351
CP 06H FE 06
Compare the verify status (Register A) against 06H, the value that indicates a directory sector's deleted-data mark verified correctly. The Z FLAG is set when they match.
5353
If the NZ FLAG is set (verify status was not 06H, a genuine error), JUMP to the @ERROR display path at 5362H with the status in Register A.
5355
RET C9
The sector wrote and verified. RETurn to the caller.

5356H - Read Directory Sector

Reads one sector into the 256-byte buffer at 5500H. The read status 06H, the deleted-data mark that flags a directory sector, is accepted as success alongside a clean read; any other error falls through to the @ERROR path. The cylinder is in Register D and the sector in Register E from the caller.

5356
LD HL,5500H 21 00 55
Point Register Pair HL at the 256-byte sector buffer at 5500H, the destination for the read; the routine returns with Register Pair HL still holding 5500H.
5359
LD C,00H 0E 00
Self-Modifying Code
Load Register C with the drive number. The operand shown as 00H was patched at 5225H with the command-line drive, so this is LD C,drive.
535B
GOSUB to the resident RDSECT service at 4777H in SYS0/SYS, which reads the drive (Register C), cylinder (Register D) and sector (Register E) into the buffer (Register Pair HL). It returns the Z FLAG set on a clean read and the controller status in Register A otherwise.
535E
RET Z C8
If the Z FLAG is set (a clean read), RETurn to the caller with the sector in the buffer.
535F
CP 06H FE 06
The read was not clean; compare the status (Register A) against 06H, the deleted-data mark that normally flags a directory sector. The Z FLAG is set when they match.
5361
RET Z C8
If the Z FLAG is set (status 06H, the expected directory-sector mark), RETurn to the caller treating the read as successful.

5362H - Error Display via @ERROR

Common error exit for the disk primitives and the illegal-drive stub. It sets the return-to-caller and message-only option bits, calls the resident @ERROR service to display the system message for the code in Register A, then loads the error return code and exits.

5362
OR 0C0H F6 C0
OR Register A (the error code) with 0C0H to set bit 7 (return to the caller rather than abort) and bit 6 (display the message only), the option bits @ERROR reads.
5364
GOSUB to the resident @ERROR service at 4409H in SYS0/SYS to display the system error message for the code in Register A.
5367
JUMP to 5377H to load the error return code and take the common exit.

5369H - Message Error Stubs

Three entry points that each load the address of a plain-text error message into Register Pair HL and converge on a single @LOGOT display call. The entries overlap: a single DD byte sits between each 3-byte LD HL, so that when execution falls through from one entry the DD prefixes the following LD HL into a harmless LD IX, preserving the message address already in Register Pair HL.

5369
LD HL,5428H 21 28 54
System-disk entry (reached from 526BH). Point Register Pair HL at the message at 5428H, "SYSTEM disk conversion requires a 5.3 or 6.3 disk!".
536C
DEFB 0DDH DD
Self-Modifying Code
Skip byte. On fall-through from 5369H this DD prefixes the LD HL at 536DH into an inert LD IX,545BH, so the message address in Register Pair HL survives; entered directly at 536DH the same bytes read as LD HL.
536D
LD HL,545BH 21 5B 54
Write-protected entry (reached from 522FH). Point Register Pair HL at the message at 545BH, "Write protected drive!".
5370
DEFB 0DDH DD
Self-Modifying Code
Skip byte. On fall-through this DD prefixes the LD HL at 5371H into an inert LD IX,540FH, preserving Register Pair HL; entered directly at 5371H the bytes read as LD HL.
5371
LD HL,540FH 21 0F 54
Abort entry (reached from 52C4H). Point Register Pair HL at the message at 540FH, "Date conversion aborted!".
5374
GOSUB to the resident @LOGOT service at 447BH in SYS0/SYS to display the carriage-return-terminated message that Register Pair HL now addresses.
5377
LD HL,0FFFFH 21 FF FF
Load Register Pair HL with 0FFFFH, the error return code the exit routine tests (0000H success, 0FFFFH error).
537A
JUMP to the exit routine at 52FAH to restore the stack and return the error.

537DH - Illegal-Drive Error Stub

Reached when the command line lacks a colon, names a drive above 7, or names an unavailable drive. It loads error code 20H (32, illegal drive number) and joins the @ERROR display path.

537D
LD A,20H 3E 20
Load Register A with 20H (32), the LDOS error code for an illegal drive number.
537F
JUMP to the @ERROR display path at 5362H, which sets the option bits and displays the message for the code in Register A.

5381H - Sign-On Message

The banner displayed at start-up through @DSPLY (4467H) at 520BH. The text is terminated by a line feed and carriage return.

5381
DEFM 'DATECONV - LDOS Date Conversion - Version 5.3.1' 44 41 54 45 43 4F 4E 56 ...
Sign-on line 1: the program name and version. Displayed by @DSPLY at 520BH.
53B0
DEFB 0AH 0A
Line feed separating the two banner lines.
53B1
DEFM 'Copyright 1991 MISOSYS, Inc., All rights reserved' 43 6F 70 79 ...
Sign-on line 2: the MISOSYS copyright notice.
53E2
DEFB 0AH, 0DH 0A 0D
Line feed and carriage return ending the banner.

53E4H - Conversion-Complete Message

Displayed through @LOGOT (447BH) at 52F4H. The leading five blanks are overwritten by the right-justified file count that the formatter at 5309H builds, leaving the sixth blank as a separator.

53E4
DEFM ' file(s) updated, conversion complete' 20 20 20 20 20 20 66 69 6C 65 ...
Completion message. The formatter at 5309H writes the file count right-justified into the first five spaces (5500-series field 53E4H-53E8H).
540E
DEFB 0DH 0D
Carriage return ending the message.

540FH - Abort Message

Displayed through @LOGOT (447BH) at 5374H when the operator presses BREAK during conversion (entry 5371H).

540F
DEFM 'Date conversion aborted!' 44 61 74 65 20 63 6F 6E 76 ...
Shown when conversion is interrupted by BREAK.
5427
DEFB 0DH 0D
Carriage return ending the message.

5428H - System-Disk Message

Displayed through @LOGOT (447BH) at 5374H when the system-disk gate rejects the pack (entry 5369H).

5428
DEFM 'SYSTEM disk conversion requires a 5.3 or 6.3 disk!' 53 59 53 54 45 4D 20 64 69 73 6B ...
Shown when an older SYSTEM disk lacking x.3 system files is presented for conversion.
545A
DEFB 0DH 0D
Carriage return ending the message.

545BH - Write-Protected Message

Displayed through @LOGOT (447BH) at 5374H when @CKDRV reports the pack write-protected (entry 536DH).

545B
DEFM 'Write protected drive!' 57 72 69 74 65 20 70 72 6F 74 65 63 74 65 64 ...
Shown when the target diskette is write-protected and cannot be converted.
5471
DEFB 0DH 0D
Carriage return ending the message.

5472H - File-Conversion Counter

The 16-bit running count of directory entries converted. It is initialised to zero in the load image, incremented at 52BAH for each file, and formatted into the completion message at 52E9H.

5472
DEFW 0000H 00 00
File-conversion counter; incremented at 52BAH, read at 52E9H.