;************************************************************************************* ; MODULE: DECODE64.ASM DATE: JANUARY 27,1997 ; AUTHOR: SEAN M. KESSLER ; TARGET: 32 BIT LAT MODEL ; FUNCTION : BASE64 DECODER ;************************************************************************************* .386 .MODEL FLAT INCLUDE devioctl.inc INCLUDE string.inc INCLUDE openfile.inc DECODEBYTE MACRO index,offset mov al,byte ptr [index+offset] ; get byte at index register + offset sub al,' ' ; subtract space and al,3Fh ; and with 3Fh ENDM .DATA inputFile FileInfo <> outputFile FileInfo <> szBeginLine DB 'begin ',0000h szEndLine DB 'end',0000h szLineData DB 400h DUP(0) numItem DB (0) charByte DB (0) status DD (0) szOutputPathFileName DB 0FFh DUP(0) szInputPathFileName DD ? .CODE _uudecode proc near ; void uudecode(char *szInputPathFileName,char *szPathDecodedFileName) push ebp ; save stack frame mov ebp,esp ; create new frame push esi ; save source index register push edi ; save destination index register push dword ptr[ebp+08h] ; save inputPathFileName pop szInputPathFileName ; restore into szInputPathFileName cmp szInputPathFileName,0000h ; is the file name null je @@errorExit ; if so then we're done FOPEN szInputPathFileName,inputFile,GENERIC_READ,FILE_SHARE_READ,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL cmp eax,INVALID_HANDLE je @@errorExit @@munchLoop: FGETS inputFile,szLineData ; read a line cmp eax,0000h ; did the read succeed ? je @@endRead ; if not then we're done STRNCMP szBeginLine,szLineData ; compare line to signature cmp eax,0001h ; did we find the signature jne @@munchLoop ; if not then keep reading call _getOutputFileName ; get output file name STRCPY [ebp+0Ch],offset szOutputPathFileName ; copy szOutputPathFileName to supplied buffer FOPEN offset szOutputPathFileName,outputFile,GENERIC_WRITE,FILE_SHARE_READ,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL cmp eax,INVALID_HANDLE ; was there a problem creating the output file je @@endRead ; if so then we're done @@readLoop: ; read loop sync address mov esi,offset szLineData ; assign input line address to esi FGETS inputFile,szLineData ; read an input line cmp eax,0000h ; check for read error je @@endDecode ; if there was an error, then we're done xor eax,eax ; clear eax register DECODEBYTE esi,00h ; decode the byte mov numItem,al ; move the decoded item into numItem cmp numItem,0000h ; compare numItem to zero jle @@endDecode ; if it's less than or equal, we're done inc esi ; increment line pointer @@decodeLoop: ; decode loop sync address cmp numItem,0000h ; compare numItem to zero jle @@readLoop ; if it's less than or equal, get another line cmp numItem,0003h ; compare numItem to 3 jge @@handleItemFGE3 ; handle (numItem>=3) cmp numItem,0001h ; compare numItem to 1 jge @@handleItemGE1 ; handle (numItem>=1) @@GE1Ret: ; return sync address cmp numItem,0002h ; compare numItem to 2 jge @@handleItemGE2 ; handle (numItem>=2) @@GE2Ret: ; return sync address cmp numItem,0003h ; compare numItem to 3 jge @@handleItemGE3 ; handle (numItem>=3) @@GE3Ret: ; return sync address add esi,0004h ; increment line pointer sub numItem,0003h ; subtract 3 from numItem jmp @@decodeLoop ; keep going @@handleItemFGE3: ; return sunc address DECODEBYTE esi,00h ; decode the byte mov cl,02h ; move shift value into cl register shl ax,cl ; perform left shift mov charByte,al ; save value into charByte DECODEBYTE esi,01h ; decode the byte mov cl,04h ; move shift value into cl register shr al,cl ; perform right shift or charByte,al ; or result with saved value FWRITE outputFile,charByte ; write out the char DECODEBYTE esi,01h ; decode byte mov cl,04h ; move shift value into cl register shl ax,cl ; perform left shift mov charByte,al ; save value into charByte DECODEBYTE esi,02h ; decode byte mov cl,02h ; move shift value into cl register shr al,cl ; perform right shift or charByte,al ; or result with saved value FWRITE outputFile,charByte ; write out the char DECODEBYTE esi,02h ; decode byte mov cl,06h ; move shift value into cl register shl ax,cl ; perform left shift mov charByte,al ; save value into charByte DECODEBYTE esi,03h ; decode byte or charByte,al ; or result with saved value FWRITE outputFile,charByte ; write out the char jmp @@GE3Ret ; jump back @@handleItemGE1: ; (numItem>=1) sync address DECODEBYTE esi,00h ; decode byte mov cl,02h ; move shift value into cl register shl ax,cl ; perform left shift mov charByte,al ; save result into charByte DECODEBYTE esi,01h ; decode byte mov cl,04h ; mov shift value into cl register shr ax,cl ; perform right shift or charByte,al ; or the result into charByte FWRITE outputFile,charByte ; write out the byte jmp @@GE1Ret ; return @@handleItemGE2: ; (numItem>=2) sync address DECODEBYTE esi,01h ; decode byte mov cl,04h ; move shift value into cl register shl ax,cl ; perform left shift mov charByte,al ; save result into charByte DECODEBYTE esi,02h ; decode byte mov cl,02h ; move shift value into cl register shr ax,cl ; perform right shift or charByte,al ; or result into charByte FWRITE outputFile,charByte ; write out the byte jmp @@GE2Ret ; return @@handleItemGE3: ; (numItem>=3) sync address DECODEBYTE esi,02h ; decode byte mov cl,06h ; move shift value into cl register shl ax,cl ; perform left shift mov charByte,al ; save result into charByte DECODEBYTE esi,03h ; decode byte or charByte,al ; or result with charByte FWRITE outputFile,charByte ; write out the byte jmp @@GE3Ret ; return @@endDecode: ; end decode sync address FGETS inputFile,szLineData ; get final line from input file s/b 'end' STRNCMP szLineData,szEndLine ; compare last line to endLine cmp eax,0000h ; check return je @@setError ; if it's not equal to 'end' we've got an error mov status,0001h ; set success jmp @@endRead ; skip over next instruction(s) @@setError: ; setError sync address mov status,0000h ; set failure @@endRead: ; end read sync address FCLOSE inputFile ; close input file FFLUSH outputFile ; flush output file FCLOSE outputFile ; close output file @@errorExit: ; error exit sync address mov eax,status ; set return code pop edi ; restore destination index register pop esi ; restore source index register pop ebp ; restore previous stack frame retn ; return near to caller _uudecode endp _getOutputFileName proc near push ebp ; save stack frame mov ebp,esp ; create new frame push esi ; save source index register push edi ; save destination index register mov esi,offset szLineData ; move input line address into source index mov edi,offset szOutputPathFileName ; move output file name buffer into destination index xor ecx,ecx ; clear ecx register for counting @@munchLoop: ; munch loop sync address mov al,byte ptr[esi] ; get byte from input line inc esi ; increment esi along input line cmp al,' ' ; did we read a space jne @@munchLoop ; if not then keep reading inc ecx ; increment space counter cmp ecx,0002h ; is this the second space jne @@munchLoop ; if not then keep reading @@copyLoop: ; copy loop sync address mov al,byte ptr[esi] ; get source byte into al register mov byte ptr[edi],al ; copy byte into destination inc esi ; increment along source line inc edi ; increment along destination cmp al,0000h ; compare input byte to zero jne @@copyLoop ; if it's not null then keep going pop edi ; restore destination index register pop esi ; restore source index register pop ebp ; restore stack frame retn ; return near to caller _getOutputFileName endp public _uudecode END