Помощь - Поиск - Пользователи - Календарь
Полная версия: Конвертор Ascii->win
Форум «Всё о Паскале» > Современный Паскаль и другие языки > Ассемблер
GLuk
Вот, предлагаю версию 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                ;
GLuk
Part II


;;; Типа, экран помощи;;;
@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                          ;
GLuk
Ну не будем мусолить... поищу - есть некоторые люди... а больше паг не по сабжу не постить (личная просьба модера).

2Clane: Вишь ли в моем понятии МОДЕР - это человек, понимающий несколько больше, чем остальные в своем топике... но т.к. ты тех людей не знаешь - no comment's
Bitterman
Извиняюсь за офтопик. Помогите, пожалуйчта, новичку!!! Нужно на АСМе написать программу, которая при вводе любой буквы покажет первую цифру ее ASCII кода. Заранее огромное спасибо!!!
FreeMan
.model tiny          ; модель
.code                               ;тут начинается секция кода
org 100h ;грузим со смещения 100h, так как с 0 по 100h идут всякие структуры
start:                               ;метка начала кода
xor ah,ah
int 16h                             ;получаем в al код символа
cmp al,27                         ;это esc?
je exit                              ;да - валим
pechat:
mov cl,4                           ;shr al,4 на 8086 не проходит вроде
shr al,cl                     ;делаем через cl, что вроде как лучше и наглядней div
cmp al,0ah                        ;сравниваем
ja bol6e
add al,30h                         ;если меньше, то имеем дело с числом
jmp pechats
bol6e:
add al,37h               ;если больше, то с буквой (разницу ищи в таблице ascii)
pechats:
mov digits,al                      ;полученный символ пихаем подальше
mov ah,9h                         ;функция вывода строки
mov dx, offset dannie         ;ds:dx - указывают на строку
int 21h                              ;выводим
jmp start                           ;повторяем
exit:
ret                                    ;в стеке лежит 0 (не веришь - в отладчик), то есть
;это всё равно, что jmp 0, а по смещению 0 лежит команда int 20h - выход

dannie db 'First digit is: '
digits db 0h,0ah,0dh,'$'

end start
Вот. Компилить
ml asd.asm /AT
Dark
На будущее, Freeman, просьба писать коментраии =), и немного пожалуйста по блокам дели, для удобства чтения
.model tiny
.code
org 100h

start:

xor ah,ah
int 16h; ah - SCAN code al - ASCII
cmp al,27; ESC?
je exit; аха
jmp pechat; идем печатать

dal6e:; ???

pechat:
mov cl,4;???  не проще было бы shr al,4? т.е. al=al div 16
shr al,cl; 
cmp al,0ah

; тут я кое что переделал, на один jmp меньше.

add al,30h; цифра =)
jmp pechats

bol6e:
add al,7; цифра больше чем 10. Для букв от 0A до 0F

pechats:
mov digits,al
mov ah,9h
mov dx, offset dannie
int 21h
jmp start
exit:
ret
dannie db 'First digit is: '
digits db 0h,0ah,0dh,'$'
end start
FreeMan
Коментарии сделаем. Писалось на скорую руку, не очень оптимально. Перевод числа в символ, кстати, можно проще сделать
cmp al,0ah
sbb al,69h
das
но ведь нормальный человек начнёт задавать вопрос: почему так?
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.