IDEAL MODEL TPASCAL STRUC workarea ; allocated on stack saveds DW ? ; save area for register DS xlen DW ? ; length of translated x string d DW ? ; pointer to beginning of d array on stack x DW ? ; pointer to beginning of x array on stack yi DW ? ; current y letter (translated) dy DW ? ; insert distance for current y letter ENDS CODESEG ; a b c d e f g h i j k l m n o p q r s t u v w x y z dist db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1; db 1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1; a db 1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1; b db 1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1; c db 1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1; d db 1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1; e db 1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1; f db 1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1; g db 1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1; h db 1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1; i db 1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1; j db 1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1; k db 1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1; l db 1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1; m db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1; n db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1; o db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1; p db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1; q db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1; r db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1; s db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1; t db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1; u db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1; v db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1; w db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1; x db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1; y db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0; z PUBLIC EditDistance PROC EditDistance FAR xadr:DWORD,yadr:DWORD LOCAL work:workarea=worklen Mov [work.saveds],DS ; move and translate string x to work area on stack Lds SI,[xadr] Mov DX,SP ;save SP for computation below Dec DX Mov DI,DX Cld LodsB Or AL,AL Jz xnull Xor AH,AH Mov CX,AX Sub SP,AX ;temporarily make room for all of x Add SI,AX Dec SI Mov AX,SS Mov ES,AX Std ;examine x string backwards xloop: LodsB Or AL,20h ;only alphabetic characters need apply Cmp AL,'a' Jl loopx Cmp AL,'z' Jg loopx Sub AL,60h ;normalize to 1..26 StosB loopx: Loop xloop xnull: Mov AX,DX ;compute length of valid x Sub AX,DI Mov [work.xlen],AX Inc DI Mov [work.x],DI Inc AX ;d is 2*Succ(Length(x)) long Shl AX,1 Sub DI,AX Mov [work.d],DI Mov SP,DI Dec SP ; initialize d array (to first row of conceptual 2d array, dd[i,j]) Mov BX,SS Mov ES,BX ;DI still has [work.d] Xor AX,AX Mov DX,AX Cld StosW ;dd[0,0] := 0 Mov CX,[work.xlen] Or CX,CX Jz stepd Mov DS,BX Mov SI,[Work.x] Mov BX,AX iloop: LodsB ;for j := 1 to xlen do Mov BL,AL Mov AL,[dist+BX] Xor AH,AH Add AX,DX StosW ;dd[0,j] := dd[0,j-1] + dist[0,x[j]]; Mov DX,AX ;at end of loop, DX = dd[0,xlen] Loop iloop ; step d array down xy plane (d is a row of conceptual array dd[i,j]) stepd: Lds SI,[yadr] LodsB Or AL,AL Jz done Xor AH,AH Mov CX,AX ;for i := 1 to Length(y) do begin Mov AX,SS Mov ES,AX nexty: LodsB Or AL,20h ;alpha only Cmp AL,'a' Jl loopy Cmp AL,'z' Jg loopy Sub AL,60h ;normalize to 1..26, Mov BL,27 Mul BL ;then multiply by 27 Push DS ; save regs and set up for inner loop Push SI Push CX Mov BX,SS Mov DS,BX Mov DI,[work.d] Mov [work.yi],AX ;yi := y[i]; Mov BX,AX Xor AH,AH Mov AL,[dist+BX] Mov [work.dy],AX ;dy := dist[y[i],0]; Add AX,[Word ES:DI] ;AX := dd[i-1,0] + dy; Mov CX,[work.xlen] ;for j := 1 to xlen do begin Or CX,CX Jz xdone Mov SI,[work.x] nextx: Mov DX,[ES:DI] ;DX := dd[i-1,j-1] StosW ;dd[i,j-1] := AX; LodsB Xor AH,AH Mov BX,AX Mov AL,[dist+BX] Add AX,[ES:DI-2] ;AX := dd[i,j-1] + dist[0,x[j]] Add BX,[work.yi] Mov BL,[dist+BX] Xor BH,BH Add DX,BX ;DX := dd[i-1,j-1] + dist[y[i],x[j]] Mov BX,[ES:DI] Add BX,[work.dy] ;BX := dd[i-1,j] + dist[y[i],0]; Cmp AX,BX ;AX := Min(AX,BX,DX) Jle skip1 Mov AX,BX skip1: Cmp AX,DX Jle skip2 Mov AX,DX skip2: Loop nextx xdone: StosW Pop CX Pop SI Pop DS Mov DX,AX loopy: Loop nexty done: Mov DS,[work.saveds] Mov AX,DX Ret ;function result is in AX ENDP END