1. Заголовок или название темы должно быть информативным 2. Все тексты программ должны помещаться в теги [CODE=asm] [/CODE] 3. Прежде чем задавать вопрос, см. "FAQ",если там не нашли ответа, воспользуйтесь ПОИСКОМ, возможно, такую задачу уже решали! 4. Не предлагайте свои решения на других языках, кроме Ассемблера. Исключение только с согласия модератора. 5. НЕ используйте форум для личного общения! Все, что не относиться к обсуждению темы - на PM! 6. Проверяйте программы перед тем, как выложить их на форум!!
Вот, предлагаю версию 1.0, никому не нужного перекодировщика из ASCII в WIN и наоборот написанного на асме с использованием самодифицирующегося кода, впрочем выигрыш от его использования минимальный... Жду огромное кол-во комментариев, оваций или хоть чего-нибудь...
.MODEL TINY .386 .CODE ORG 100h Start: cld mov di,80h ; DS:DI - количество символов, введенных ; в командной строке после имени проги. ; DS - сегмент PSP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Минимум : a. b. - т.е. 10 символов включая 0Dh & возм. пробелы ;;;;; ; Максимум: maximum1.max maximum2.max = 27 + возм. пробелы -> 35.;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + параметр -> 4 space's mov cl,[di] ; ;cmp cl,10 ; ;jb @PrintHelp ; ;cmp cl,80 ; Сверим пределы, если что - выводим ;ja @PrintHelp ; справку mov ch,0 ; Инициализируем счетчик символов inc di ; inc di ; DS:DI, собственно, сами символы... push di ; Сохр. смещение к началу первого имени mov al,' ' ; Ищем первый пробел repne scasb ; ищем, ищем... je @SpaceFound ; ...нашли! jmp @PrintHelp ; ...не нашли выводим справку об исп-ии : ( @SpaceFound: mov byte ptr [di-1],0 ; Ставим ноль (формат имени -> ASCIIZ) push di ; Сохр. смещение начала второго имени mov al,0Dh ; repne scasb ; Ищем конец строки, т.е. символ с кодом 13 je @EndFound ; jmp @PrintHelp ; @EndFound: ; dec di ; cmp word ptr [di-2],'# ' ; Смотрим нет ли параметра jne @NoParam ; dec di ; В случае присутствия -> меняем код dec di ; процедуры перекодировщика ;;; Чиста выиграл 39-22= целых 17 байт; Было 3 варианта:;;; I;;;; ;push di ; 1 ;lea di,@FirstModified+1 ; 3 ;mov al,80h ; 2 ;stosb ; 1 ;add di,3 ; 3 ;mov al,0AFh ; 2 ;stosb ; 1 ;mov al,4 ; 2 ;add di,4 ; 3 ;stosb ; 1 ;lea di,@@@@@ ; 3 ;stosb ; 1 ;sub di,4 ; 3 ;mov al,0E0h ; 2 ;stosb ; 1 ;pop di ; 1;;; Как итог - 30 байт, не пойдет : ( ;;;; II;;; ;mov byte ptr [@FirstModified+1],80h ;mov byte ptr [@FirstModified+5],0AFh ;mov byte ptr [@FirstModified+8],4 ;mov byte ptr [@NextRange+1],0E0h ;mov byte ptr [@NextRange+4],4;;; Как итог - 25 байт, тож говно ; );;;; III ;;;;;;; Вот он - лучший и неповторимый!!! 8-);;;
lea si,@FirstModified+1 ; Смещение к первому байту изменяемого кода mov byte ptr [si],80h ; Пределы первого диапазона mov byte ptr [si+4],0AFh ; mov byte ptr [si+7],4 ; Код сложения mov byte ptr [si+12],0E0h ; Второй диапазон mov byte ptr [si+15],4 ; !!!ONLY 22 bytes!!! @NoParam: mov byte ptr [di],0 ; Ставим ноль в конце второго имени mov ax,3D02h ; Пробуем открыть файл для записи... pop dx ; DS:DX - имя выходного файла int 21h jnc @AlreadyExist ; Если такого нету... mov ah,3Ch ; ...пробуем создать mov cx,20h ; Атрибут - архивный (включен бит 5) int 21h ; jc @PrintError ; mov OutHandle,ax ; Сохраняем дескриптор созданного файла jmp @TryOpenAnother ; Открываем следующий файл @AlreadyExist: ; mov OutHandle,ax lea dx,Question ; Спрашиваем о возможности перезаписи mov ah,9 ; файла, т.к. он уже существует int 21h mov ah,0 ; Ждем ввода int 16h cmp ax,1C0Dh ; Нажата клавиша Enter? je @TryOpenAnother jmp @PrintHelp ; При нажатии любой другой клавиши... @TryOpenAnother: pop dx ; Смещение к первому параметру mov ax,3D02h ; Открыть для чтения... int 21h jc @PrintError mov InHandle,ax ; Сохраняем дескриптор;;;; Основной цикл чтения/записи;;; lea bp,InHandle ; Адресуем дескрипторы через сегмент стека push ds ; Сохр. DS, хотя надо-ли?? mov ax,ds add ax,1001h mov ds,ax @ReadNext: mov bx,word ptr [bp] ; Дескриптор xor dx,dx ; DS:DX - буфер для чтения mov cx,dx ; dec cx ; CX -> 0FFFFh ~64Kb mov al,'.' int 29h ; Контроль кол-ва 64Кб блоков mov ah,3Fh ; Читать... int 21h ; ...пока не уср1мся jc @PrintError ; Контролируем... cmp ax,0 ; je @ConvertComplete ; Проверяем на EoF mov si,dx ; или xor si,si по совести mov cx,ax ; Кол-во реально прочитанных байт;;; call WIN2ASCII mov bx,word ptr [bp-2] ; Дескриптор mov ah,40h ; Записываем int 21h jc @PrintError jmp @ReadNext @ConvertComplete: pop ds ; Восстанавливаем сегмент данных mov ah,40h ; mov bx,OutHandle ; xor cx,cx ; Записать 0 байт int 21h ; Обрезаем файл - на всякий случай jc @PrintError ; mov ah,3Eh ; Закрываем оба файла int 21h ; jc @PrintError mov bx,InHandle ; int 21h ; jc @PrintError jmp @EndOfProg ;
;;; Типа, экран помощи;;; @PrintHelp: mov ah,9 lea dx,HelpMes int 21h jmp @EndOfProg;;; Ошибка -> выводим код, завершаем работу;;; @PrintError: push cs pop es lea di,DOSErrorCode call Bin2Hex push es pop ds mov ah,9 lea dx,ErrorMes int 21h;;; @EndOfProg: mov ax,4C01h int 21h WIN db 0 OutHandle dw ? InHandle dw ? ErrorMes db 13,10,' -> Ошибка DOS #: ' DOSErrorCode db ' ','$' Question db 'Выходной файл уже существует, переписать? (Enter = Да):$' HelpMes db 13,10,'Эта прога представляет собой лишь очередной ремейк конвертора из ASCII в WIN.',13,10 db 'Использование: convert.com <входной.файл> <выходной.файл> [#]',13,10 db 'При указании параметра # происходит перевод из WIN в ASCII без него - наоборот.' db 13,10,13,10,13,10 db '>>> Copyright by GLuk <<<','$' db 'complete!$'
Bin2Hex Proc;; На входе ES:DI - адрес приемника; AL - число;;; Сохраняем используемые регистры push ax push cx push di mov ah,al shr al,4 ; Выделяем старший полубайт, сдвигом на 4 бита вправо;
@StartModify: add al,30h ; Преобразуем до ASCII-цифры cmp al,39h ; jbe $+4 ; Если это буква add al,7 ; добавляем еще 7 stosb ; Запоминаем @Change: mov al,ah ; Восстанавливаем исх. значение and al,0Fh ; Выделяем младший полубайт;;;;;;;;;;;;;;;;;;;;;;;;; mov word ptr @Change,00AEBh; jmp $+0Ah jmp @StartModify ; Преобразуем ее @Done:mov word ptr @Change,0C48Ah; Восстанавливаем исх. код pop di pop cx pop ax ret Bin2Hex EndP;;; Собственно, сам перекодировщик WIN->WIN;;; WIN2ASCII Proc push ax push ds push si push cx pushf ; Сохр. регистр флагов cld ; Очищаем флаг направления (6) @NextByte: ; lodsb ; Получаем байт в AL cmp si,cx ; Может это конец? je @Stop ; @FirstModified: cmp al,0C0h ; Проверяем первый диапазон jb @NextByte ; cmp al,0EFh ja @NextRange sub al,64 ; Инкремент/Декремент на этот случай jmp @Store ; @NextRange: ; cmp al,0F0h ; Следующий диапазон 0F0h-0FFh jb @NextByte ; sub al,16 ; @Store: mov [si-1],al ; jmp @NextByte ; @Stop: ; popf pop cx pop si pop ds pop ax ret ; 39 байт WIN2ASCII EndP END Start ;