Digital Research failed to publish the assembly listing of their block/deblock algorithm. They just published the code. Here is the assembly listing of the code produced by their MAC assembler. The content of the .SYM and .HEX files is appended to the end of the listing: ;***************************************************** ;* * ;* SECTOR DEBLOCKING ALGORITHMS FOR CP/M 2.0 * ;* * ;***************************************************** ; ; UTILITY MACRO TO COMPUTE SECTOR MASK SMASK MACRO HBLK ;; COMPUTE LOG2(HBLK), RETURN @X AS RESULT ;; (2 ** @X = HBLK ON RETURN) @Y SET HBLK @X SET 0 ;; COUNT RIGHT SHIFTS OF @Y UNTIL = 1 REPT 8 IF @Y = 1 EXITM ENDIF ;; @Y IS NOT 1, SHIFT RIGHT ONE POSITION @Y SET @Y SHR 1 @X SET @X + 1 ENDM ENDM ; ;***************************************************** ;* * ;* CP/M TO HOST DISK CONSTANTS * ;* * ;***************************************************** 0800 = BLKSIZ EQU 2048 ;CP/M ALLOCATION SIZE 0200 = HSTSIZ EQU 512 ;HOST DISK SECTOR SIZE 0014 = HSTSPT EQU 20 ;HOST DISK SECTORS/TRK 0004 = HSTBLK EQU HSTSIZ/128 ;CP/M SECTS/HOST BUFF 0050 = CPMSPT EQU HSTBLK * HSTSPT ;CP/M SECTORS/TRACK 0003 = SECMSK EQU HSTBLK-1 ;SECTOR MASK SMASK HSTBLK ;COMPUTE SECTOR MASK 0002 = SECSHF EQU @X ;LOG2(HSTBLK) ; ;***************************************************** ;* * ;* BDOS CONSTANTS ON ENTRY TO WRITE * ;* * ;***************************************************** 0000 = WRALL EQU 0 ;WRITE TO ALLOCATED 0001 = WRDIR EQU 1 ;WRITE TO DIRECTORY 0002 = WRUAL EQU 2 ;WRITE TO UNALLOCATED ; ;***************************************************** ;* * ;* THE BDOS ENTRY POINTS GIVEN BELOW SHOW THE * ;* CODE WHICH IS RELEVANT TO DEBLOCKING ONLY. * ;* * ;***************************************************** ; ; DISKDEF MACRO, OR HAND CODED TABLES GO HERE 0000 = DPBASE EQU $ ;DISK PARAM BLOCK BASE ; BOOT: WBOOT: ;ENTER HERE ON SYSTEM BOOT TO INITIALIZE 0000 AF XRA A ;0 TO ACCUMULATOR 0001 325B01 STA HSTACT ;HOST BUFFER INACTIVE 0004 325D01 STA UNACNT ;CLEAR UNALLOC COUNT 0007 C9 RET ; SELDSK: ;SELECT DISK 0008 79 MOV A,C ;SELECTED DISK NUMBER 0009 325201 STA SEKDSK ;SEEK DISK NUMBER 000C 6F MOV L,A ;DISK NUMBER TO HL 000D 2600 MVI H,0 REPT 4 ;MULTIPLY BY 16 DAD H ENDM 000F+29 DAD H 0010+29 DAD H 0011+29 DAD H 0012+29 DAD H 0013 110000 LXI D,DPBASE ;BASE OF PARM BLOCK 0016 19 DAD D ;HL=.DPB(CURDSK) 0017 C9 RET ; SETTRK: ;SET TRACK GIVEN BY REGISTERS BC 0018 60 MOV H,B 0019 69 MOV L,C 001A 225301 SHLD SEKTRK ;TRACK TO SEEK 001D C9 RET ; SETSEC: ;SET SECTOR GIVEN BY REGISTER C 001E 79 MOV A,C 001F 325501 STA SEKSEC ;SECTOR TO SEEK 0022 C9 RET ; SETDMA: ;SET DMA ADDRESS GIVEN BY BC 0023 60 MOV H,B 0024 69 MOV L,C 0025 226601 SHLD DMAADR 0028 C9 RET ; SECTRAN: ;TRANSLATE SECTOR NUMBER BC 0029 60 MOV H,B 002A 69 MOV L,C 002B C9 RET ; ;***************************************************** ;* * ;* THE READ ENTRY POINT TAKES THE PLACE OF * ;* THE PREVIOUS BIOS DEFINITION FOR READ. * ;* * ;***************************************************** READ: ;READ THE SELECTED CP/M SECTOR 002C 3E01 MVI A,1 002E 326401 STA READOP ;READ OPERATION 0031 326301 STA RSFLAG ;MUST READ DATA 0034 3E02 MVI A,WRUAL 0036 326501 STA WRTYPE ;TREAT AS UNALLOC 0039 C3A700 JMP RWOPER ;TO PERFORM THE READ ; ;***************************************************** ;* * ;* THE WRITE ENTRY POINT TAKES THE PLACE OF * ;* THE PREVIOUS BIOS DEFINITION FOR WRITE. * ;* * ;***************************************************** WRITE: ;WRITE THE SELECTED CP/M SECTOR 003C AF XRA A ;0 TO ACCUMULATOR 003D 326401 STA READOP ;NOT A READ OPERATION 0040 79 MOV A,C ;WRITE TYPE IN C 0041 326501 STA WRTYPE 0044 FE02 CPI WRUAL ;WRITE UNALLOCATED? 0046 C26000 JNZ CHKUNA ;CHECK FOR UNALLOC ; ; WRITE TO UNALLOCATED, SET PARAMETERS 0049 3E10 MVI A,BLKSIZ/128 ;NEXT UNALLOC RECS 004B 325D01 STA UNACNT 004E 3A5201 LDA SEKDSK ;DISK TO SEEK 0051 325E01 STA UNADSK ;UNADSK = SEKDSK 0054 2A5301 LHLD SEKTRK 0057 225F01 SHLD UNATRK ;UNATRK = SECTRK 005A 3A5501 LDA SEKSEC 005D 326101 STA UNASEC ;UNASEC = SEKSEC ; CHKUNA: ;CHECK FOR WRITE TO UNALLOCATED SECTOR 0060 3A5D01 LDA UNACNT ;ANY UNALLOC REMAIN? 0063 B7 ORA A 0064 CA9F00 JZ ALLOC ;SKIP IF NOT ; ; MORE UNALLOCATED RECORDS REMAIN 0067 3D DCR A ;UNACNT = UNACNT-1 0068 325D01 STA UNACNT 006B 3A5201 LDA SEKDSK ;SAME DISK? 006E 215E01 LXI H,UNADSK 0071 BE CMP M ;SEKDSK = UNADSK? 0072 C29F00 JNZ ALLOC ;SKIP IF NOT ; ; DISKS ARE THE SAME 0075 215F01 LXI H,UNATRK 0078 CD4401 CALL SEKTRKCMP ;SEKTRK = UNATRK? 007B C29F00 JNZ ALLOC ;SKIP IF NOT ; ; TRACKS ARE THE SAME 007E 3A5501 LDA SEKSEC ;SAME SECTOR? 0081 216101 LXI H,UNASEC 0084 BE CMP M ;SEKSEC = UNASEC? 0085 C29F00 JNZ ALLOC ;SKIP IF NOT ; ; MATCH, MOVE TO NEXT SECTOR FOR FUTURE REF 0088 34 INR M ;UNASEC = UNASEC+1 0089 7E MOV A,M ;END OF TRACK? 008A FE50 CPI CPMSPT ;COUNT CP/M SECTORS 008C DA9800 JC NOOVF ;SKIP IF NO OVERFLOW ; ; OVERFLOW TO NEXT TRACK 008F 3600 MVI M,0 ;UNASEC = 0 0091 2A5F01 LHLD UNATRK 0094 23 INX H 0095 225F01 SHLD UNATRK ;UNATRK = UNATRK+1 ; NOOVF: ;MATCH FOUND, MARK AS UNNECESSARY READ 0098 AF XRA A ;0 TO ACCUMULATOR 0099 326301 STA RSFLAG ;RSFLAG = 0 009C C3A700 JMP RWOPER ;TO PERFORM THE WRITE ; ALLOC: ;NOT AN UNALLOCATED RECORD, REQUIRES PRE-READ 009F AF XRA A ;0 TO ACCUM 00A0 325D01 STA UNACNT ;UNACNT = 0 00A3 3C INR A ;1 TO ACCUM 00A4 326301 STA RSFLAG ;RSFLAG = 1 ; ;***************************************************** ;* * ;* COMMON CODE FOR READ AND WRITE FOLLOWS * ;* * ;***************************************************** RWOPER: ;ENTER HERE TO PERFORM THE READ/WRITE 00A7 AF XRA A ;ZERO TO ACCUM 00A8 326201 STA ERFLAG ;NO ERRORS (YET) 00AB 3A5501 LDA SEKSEC ;COMPUTE HOST SECTOR REPT SECSHF ORA A ;CARRY = 0 RAR ;SHIFT RIGHT ENDM 00AE+B7 ORA A ;CARRY = 0 00AF+1F RAR ;SHIFT RIGHT 00B0+B7 ORA A ;CARRY = 0 00B1+1F RAR ;SHIFT RIGHT 00B2 325A01 STA SEKHST ;HOST SECTOR TO SEEK ; ; ACTIVE HOST SECTOR? 00B5 215B01 LXI H,HSTACT ;HOST ACTIVE FLAG 00B8 7E MOV A,M 00B9 3601 MVI M,1 ;ALWAYS BECOMES 1 00BB B7 ORA A ;WAS IT ALREADY? 00BC CAE300 JZ FILHST ;FILL HOST IF NOT ; ; HOST BUFFER ACTIVE, SAME AS SEEK BUFFER? 00BF 3A5201 LDA SEKDSK 00C2 215601 LXI H,HSTDSK ;SAME DIASK? 00C5 BE CMP M ;SEKDSK = HSTDSK? 00C6 C2DC00 JNZ NOMATCH ; ; SAME DISK, SAME TRACK? 00C9 215701 LXI H,HSTTRK 00CC CD4401 CALL SEKTRKCMP ;SEKTRK = HSTTRK? 00CF C2DC00 JNZ NOMATCH ; ; SAME DISK, SAME TRACK, SAME BUFFER? 00D2 3A5A01 LDA SEKHST 00D5 215901 LXI H,HSTSEC ;SEKHST = HSTSEC? 00D8 BE CMP M 00D9 CA0001 JZ MATCH ;SKIP IF MATCH ; NOMATCH: ;PROPER DISK, BUT NOT CORRECT SECTOR 00DC 3A5C01 LDA HSTWRT ;HOST WRITTEN? 00DF B7 ORA A 00E0 C45001 CNZ WRITEHST ;CLEAR HOST BUFF ; FILHST: ;MAY HAVE TO FILL THE HOST BUFFER 00E3 3A5201 LDA SEKDSK 00E6 325601 STA HSTDSK 00E9 2A5301 LHLD SEKTRK 00EC 225701 SHLD HSTTRK 00EF 3A5A01 LDA SEKHST 00F2 325901 STA HSTSEC 00F5 3A6301 LDA RSFLAG ;NEED TO READ? 00F8 B7 ORA A 00F9 C45101 CNZ READHST ;YES, IF 1 00FC AF XRA A ;0 TO ACCUM 00FD 325C01 STA HSTWRT ;NO PENDING WRITE ; MATCH: ;COPY DATA TO OR FROM BUFFER 0100 3A5501 LDA SEKSEC ;MASK BUFFER NUMBER 0103 E603 ANI SECMSK ;LEAST SIGNIF BITS 0105 6F MOV L,A ;READY TO SHIFT 0106 2600 MVI H,0 ;DOUBLE COUNT REPT 7 ;SHIFT LEFT 7 DAD H ENDM 0108+29 DAD H 0109+29 DAD H 010A+29 DAD H 010B+29 DAD H 010C+29 DAD H 010D+29 DAD H 010E+29 DAD H ; HL HAS RELATIVE HOST BUFFER ADDRESS 010F 116801 LXI D,HSTBUF 0112 19 DAD D ;HL = HOST ADDRESS 0113 EB XCHG ;NOW IN DE 0114 2A6601 LHLD DMAADR ;GET/PUT CP/M DATA 0117 0E80 MVI C,128 ;LENGTH OF MOVE 0119 3A6401 LDA READOP ;WHICH WAY? 011C B7 ORA A 011D C22601 JNZ RWMOVE ;SKIP IF READ ; ; WRITE OPERATION, MARK AND SWITCH DIRECTION 0120 3E01 MVI A,1 0122 325C01 STA HSTWRT ;HSTWRT = 1 0125 EB XCHG ;SOURCE/DEST SWAP ; RWMOVE: ;C INITIALLY 128, DE IS SOURCE, HL IS DEST 0126 1A LDAX D ;SOURCE CHARACTER 0127 13 INX D 0128 77 MOV M,A ;TO DEST 0129 23 INX H 012A 0D DCR C ;LOOP 128 TIMES 012B C22601 JNZ RWMOVE ; ; DATA HAS BEEN MOVED TO/FROM HOST BUFFER 012E 3A6501 LDA WRTYPE ;WRITE TYPE 0131 FE01 CPI WRDIR ;TO DIRECTORY? 0133 3A6201 LDA ERFLAG ;IN CASE OF ERRORS 0136 C0 RNZ ;NO FURHTER PROCESSING ; ; CLEAR HOST BUFFER FOR DIRECTORY WRITE 0137 B7 ORA A ;ERRORS? 0138 C0 RNZ ;SKIP IF SO 0139 AF XRA A ;0 TO ACCUM 013A 325C01 STA HSTWRT ;BUFFER WRITTEN 013D CD5001 CALL WRITEHST 0140 3A6201 LDA ERFLAG 0143 C9 RET ; ;***************************************************** ;* * ;* UTILITY SUBROUTINE FOR 16-BIT COMPARE * ;* * ;***************************************************** SEKTRKCMP: ;HL = .UNATRK OR .HSTTRK, COMPARE WITH SEKTRK 0144 EB XCHG 0145 215301 LXI H,SEKTRK 0148 1A LDAX D ;LOW BYTE COMPARE 0149 BE CMP M ;SAME? 014A C0 RNZ ;RETURN IF NOT ; LOW BYTES EQUAL, TEST HIGH 1S 014B 13 INX D 014C 23 INX H 014D 1A LDAX D 014E BE CMP M ;SETS FLAGS 014F C9 RET ; ;***************************************************** ;* * ;* WRITEHST PERFORMS THE PHYSICAL WRITE TO * ;* THE HOST DISK, READHST READS THE PHYSICAL * ;* DISK. * ;* * ;***************************************************** WRITEHST: ;HSTDSK = HOST DISK #, HSTTRK = HOST TRACK #, ;HSTSEC = HOST SECT #. WRITE "HSTSIZ" BYTES ;FROM HSTBUF AND RETURN ERROR FLAG IN ERFLAG. ;RETURN ERFLAG NON-ZERO IF ERROR 0150 C9 RET ; READHST: ;HSTDSK = HOST DISK #, HSTTRK = HOST TRACK #, ;HSTSEC = HOST SECT #. READ "HSTSIZ" BYTES ;INTO HSTBUF AND RETURN ERROR FLAG IN ERFLAG. 0151 C9 RET ; ;***************************************************** ;* * ;* UNITIALIZED RAM DATA AREAS * ;* * ;***************************************************** ; 0152 SEKDSK: DS 1 ;SEEK DISK NUMBER 0153 SEKTRK: DS 2 ;SEEK TRACK NUMBER 0155 SEKSEC: DS 1 ;SEEK SECTOR NUMBER ; 0156 HSTDSK: DS 1 ;HOST DISK NUMBER 0157 HSTTRK: DS 2 ;HOST TRACK NUMBER 0159 HSTSEC: DS 1 ;HOST SECTOR NUMBER ; 015A SEKHST: DS 1 ;SEEK SHR SECSHF 015B HSTACT: DS 1 ;HOST ACTIVE FLAG 015C HSTWRT: DS 1 ;HOST WRITTEN FLAG ; 015D UNACNT: DS 1 ;UNALLOC REC CNT 015E UNADSK: DS 1 ;LAST UNALLOC DISK 015F UNATRK: DS 2 ;LAST UNALLOC TRACK 0161 UNASEC: DS 1 ;LAST UNALLOC SECTOR ; 0162 ERFLAG: DS 1 ;ERROR REPORTING 0163 RSFLAG: DS 1 ;READ SECTOR FLAG 0164 READOP: DS 1 ;1 IF READ OPERATION 0165 WRTYPE: DS 1 ;WRITE OPERATION TYPE 0166 DMAADR: DS 2 ;LAST DMA ADDRESS 0168 HSTBUF: DS HSTSIZ ;HOST BUFFER ; ;***************************************************** ;* * ;* THE ENDEF MACRO INVOCATION GOES HERE * ;* * ;***************************************************** 0368 END 009F ALLOC 0800 BLKSIZ 0000 BOOT 0060 CHKUNA 0050 CPMSPT 0166 DMAADR 0000 DPBASE 0162 ERFLAG 00E3 FILHST 015B HSTACT 0004 HSTBLK 0168 HSTBUF 0156 HSTDSK 0159 HSTSEC 0200 HSTSIZ 0014 HSTSPT 0157 HSTTRK 015C HSTWRT 0100 MATCH 00DC NOMATCH 0098 NOOVF 002C READ 0151 READHST 0164 READOP 0163 RSFLAG 0126 RWMOVE 00A7 RWOPER 0003 SECMSK 0002 SECSHF 0029 SECTRAN 0152 SEKDSK 015A SEKHST 0155 SEKSEC 0153 SEKTRK 0144 SEKTRKCMP 0008 SELDSK 0023 SETDMA 001E SETSEC 0018 SETTRK 015D UNACNT 015E UNADSK 0161 UNASEC 015F UNATRK 0000 WBOOT 0000 WRALL 0001 WRDIR 003C WRITE 0150 WRITEHST 0165 WRTYPE 0002 WRUAL :10000000AF325B01325D01C9793252016F2600299E :1000100029292911000019C96069225301C97932BF :100020005501C96069226601C96069C93E0132642F :10003000013263013E02326501C3A700AF326401A1 :1000400079326501FE02C260003E10325D013A5213 :1000500001325E012A5301225F013A5501326101EA :100060003A5D01B7CA9F003D325D013A5201215EFF :1000700001BEC29F00215F01CD4401C29F003A55DD :1000800001216101BEC29F00347EFE50DA98003625 :10009000002A5F0123225F01AF326301C3A700AFD3 :1000A000325D013C326301AF3262013A5501B71F44 :1000B000B71F325A01215B017E3601B7CAE3003A0D :1000C0005201215601BEC2DC00215701CD4401C2BC :1000D000DC003A5A01215901BECA00013A5C01B75D :1000E000C450013A52013256012A53012257013AB3 :1000F0005A013259013A6301B7C45101AF325C0170 :100100003A5501E6036F26002929292929292911B1 :10011000680119EB2A66010E803A6401B7C2260114 :100120003E01325C01EB1A1377230DC226013A65BA :1001300001FE013A6201C0B7C0AF325C01CD50018F :100140003A6201C9EB2153011ABEC013231ABEC97A :02015000C9C91B :0000000000