Реферат: Трансляция всех модификаций команд add и cmp

                               Введение

         Длянаписания пользователем программ на различных языках программи-

    рованиянеобходимо иметь средства их перевода в машинный язык.  Это вы-

    полняютспециальные программы-переводчики, которые называются транслято-

    рами.  Трансляторы для микроЭВМ преобразуют исходнуюпрограмму на  одном

    из языковпрограммирования в некоторую стандартную форму,    называемую

    объектнойпрограммой. Существует три вида трансляторов: ассемблеры, ком-

    пиляторы иинтерпретаторы.

        Транслятор, преобразующий программу, написанную на языке ассембле-

    ра, в машинныйкод,  называется ассемблером.  При написании программы на

    языкеассемблера программист использует мнемонические обозначения машин-

    ных команд иадресов (имена и метки).  В процессе  трансляции ассемблер

    заменяет всемнемонические обозначения (коды команд и имена) их двоичны-

    ми кодами.  Для сокращения текста при повторенииидентичных частей прог-

    раммы в отдельныеязыки ассемблера введены средства написания и обработ-

    ки макрокоманд.Это позволяет программисту определить некоторую последо-

    вательностькоманд как макроопределение, которое обрабатывается макроас-

    семблером(макропроцессором). Последний представляет тексты макроопреде-

    лений ссоответствующими  фактическими  параметрами макровызова  вместо

    макрокоманд впрограмме.

         Простейшийассемблер является однопроходным и преобразует исходную

    программу заодин просмотр. Но при этом возникают трудности, связанные с

    вычислениемадресов имен,  которые определеныпозже.  Этого можно  избе-

    жать,потребовав, чтобы все имена данных были объявлены заранее, а неоп-

    ределенныеадреса заносились в таблицу,  в которуювводятся ссылки  впе-

    ред. Этатаблица либо используется для модификации команды, либо загруз-

    чиком, которыйможет формировать данный адрес во время загрузки.  Однако

    это не всегдаудобно,  поэтому большинство ассемблероввыполняют  в  два

    прохода.

         Основнаяидея двухпроходного ассемблера проста. На первом  проходе

    все символы(имена, метки) собираются в таблицу символов с соответствую-

    щими значениямиадресов,  на втором генерируетсямашинная  программа  на

    основании построеннойна первом проходе таблицы символов.

         Если языкассемблера включает средства макрорасширений, то макроп-

    роцессорреализуется различными способами.  Онможет быть добавлен к ас-

    семблеру какпрепроцессор для выполнения просмотра исходного текста  пе-

    ред первымпроходом ассемблера.  В результате  препроцессирования  полу-

    чаетсяпрограмма на языке ассемблера,  насодержащая макросов.  При этом

    текстымакроопределений, если они есть в исходной программе,  сохраняют-

    ся, а вместомакровызовов подставляются ассемблерные команды из макрооп-

    ределений.  Возможно также объединение макропроцессора спервым проходом

    ассемблера, чтосокращает время трансляции, но удлиняет текст ассемблера.

<span Courier New";mso-fareast-font-family: Batang;mso-ansi-language:RU;mso-fareast-language:KO;mso-bidi-language:AR-SA">

;█▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀█

;█ -----    ТРАНСЛЯЦИЯВСЕХ МОДИФИКАЦИЙ КОМАНДЫ ADD       — █

;█▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█

      .MODEL TINY

      .CODE

      JUMPS

      ORG 100h

begin:

      jmp   general

;┌──────────────────────────────────────┐

;│ Макрос вывода на экран строки stirng │

;└──────────────────────────────────────┘

Wrt   macrostring

      mov   ah,9              ;Функция вывода строки

      lea   dx,string         ;Загружаем адрес строки

      int   21h               ;Вызов прерывания DOS

endm

;┌──────────────────────────────┐

;│ Основная процедура программы │

;└──────────────────────────────┘

general     proc  near

      push  cs                ;Все

      push  cs                ;   сегменты

      push  cs                ;     приравниваем

      pop   ds                ;     к сегменту

      pop   es                ;          кода

      pop   ss                ;(необходимо для строковых операций)

      Wrt   about             ;Вывод информации о программе

; Начинаем разбор строки параметров

      mov   cl,ds:[80h]       ;Получаем длину строки параметров

      sub   ch,ch             ; Обнуляемch

      cmp   cx,2              ; Смотрим длину строки параметров

      jb    source_error            ;Если она меньше двух — нет вх.файла

      mov   di,82h           ; Заносим в DI адресначала поиска

      mov   path1,di          ;Запоминаем адрес входного файла

      mov   al,' '           ; Искать будем до первогопробела

      repnescasb             ;Запускаем цикл поиска

      jne   dest_error        ;Если не нашли значет нет вых. файла

      mov   byte ptr [di-1],0; Приводим к формату ASCIIZ

      mov   path2,di          ;Запоминаем адрес выходного файла

      mov   cl,ds:[80h]       ;Заносим в cl длину строки поиска

      sub   ch,ch             ; Обнуляемch

      mov   al,13             ; Искать будем до символа CR

      repnescasb             ;Запуск цикла поиска

      jne   dest_error        ;Если не нашли значет нет вых. файла

      mov   byte ptr [di-1],0; Приводим к формату ASCIIZ

      call  Fopen             ;Открываем входной файл

      jc    open_source_error; Если ошибка, выдаем сообщение

      call  Fcreate                 ;Создаем выходной файл

      jc    create_dest_error; Если ошибка, выдаем сообщение

gen1:call  Fread             ;Считываем очередную строку из файла

      jc    read_error        ;Переход если ошибка

      cmp   EOF,1             ;Смотрим признак конца файла

      jne   gen2              ;Если не конец, продолжаем

      cmp   si,0              ;Проверяем длину строки

      jne   gen2              ;Если не 0 символов продолжаем

      jmp   read_error        ;Иначе выводим сообщение об ошибке

gen2:inc   string                  ;Увеличиваем счетчик строк

      mov   strlen,si         ;Запоминаем длину строки

      call  DelSpc                  ;Вызываем процедуру удаления пробелов

      cmp   strlen,2          ;Если длина строки 2 символа, то

      je    gen1              ;переходим на чтение следующей

      lea   di,buffer         ;Загружаем адрес строки

      cmp   byte ptr [di],';'; Если первый символ строки; то

      je    gen1              ;переходим на чтение следующей

      lea   si,command        ;Будем искать строку ADD

      mov   cx,3              ;Длина искомой строки 3 символа

      repe  cmpsb             ;Начинаем поиск

      je    gen3              ;Переход, если ADD найдена

      wrt   error06                 ;Вывод сообщения об ошибке

      call  WrtStr                  ;Вывод ошбочной строки

      mov   was_error,1       ;Устанавливаем флаг ошибки

      jmp   gen1              ;Переход на чтение следующей строки

gen3:call  Coding

      cmp   was_error,0

      jne   gen1

      call  Fwrite

      jnc   gen1

      ret

gen4:mov   bx,dest                 ;Если трансляция проведена успешно

      call  Fclose                  ;Закрываем выходной файл

      Wrt   mes2              ;Вывод сообщения о завершении

      Wrt   mes3              ;Вывод сообщения о строках

      call  WrtStr                  ;Вывод числа обработаных строк

      Wrt   mes1              ; ВыводCR,LF

      ret                     ;ВЫХОД В DOS

; Далее располагаются метки перехода по различным ошибкам

source_error:

      Wrt   error01

      ret

dest_error:

      Wrt   error02

      ret

open_source_error:

      Wrt   error03

      ret

create_dest_error:

      Wrt   error04

      ret

read_error:

      cmp   EOF,1             ;Смотрим был ли конец файла

      je    skip_err_message  ; Если да, то это не ошибка

      Wrt   error05                 ;Иначе выводим сообщение об ошибке

      mov   was_error,1       ;Устанавливаем флаг ошибки

skip_err_message:

      mov   bx,source         ;Заносим дескриптор выходного файла

      call  Fclose                  ;Закрываем выходной файл

      cmp   was_error,0       ;Смотрим флаг ошибки

      je    gen4              ;Если ошибок нет, то переход

      call  Fdel              ;Иначе удаляем выходной файл

      Wrt   mes1              ; ВыводCR,LF

      Wrt   bell              ; Выводсигнала

      ret

general     endp

;┌──────────────────────────────────────────────────────┐

;│  ПереводитзначениерегистраAX вдесятичныйформат     │

;└──────────────────────────────────────────────────────┘

Decimal     proc  near

      call  clear             ; Очищаемстрокувывода

      mov   cx,0010                 ; Заносим в CX делитель

      lea   si,outstr+4       ;Указатель на конец строки

b20:  cmp   ax,0010                 ;Сравниваем AX с 10

      jb    shortb30         ; Переход, если меньше

      xor   dx,dx             ;Обнуляем DX

      div   cx                ;Делем AX на CX

      or    dl,30h                  ;Добавляем 48, чтобы получить 1

      mov   [si],dl                 ;Заносим в выходную строку

      dec   si                ;Движемся влево

      jmp   shortb20         ; Переход на следующий символ

b30:  or    al,30h                  ;Добавляем 48, чтобы получить 1

      mov   [si],al                 ;Заносим в выходную строку

      ret

; Вспомогательная процедура. Очищает строку outstr(забивает нулями)

clearproc  near

      lea   si,outstr         ;Загружаем адрес выходной строки

      mov   cl,48             ;48 — символ нуля

      mov   [si],cl                 ;Забиваем

      mov   [si+1],cl         ;    нулями

      mov   [si+2],cl         ;       все

      mov   [si+3],cl         ;         символы

      mov   [si+4],cl         ;            строки

      ret                     ;Выход

clearendp

outstr      db    '     $'

Decimal     endp

;┌──────────────────────────────┐

;│Процедуравыводачисластрок│

;└──────────────────────────────┘

WrtStr      proc  near

      xor   ax,ax             ; ОбнулениерегистраAX

      mov   al,string         ; В AL число обработанных строк

      call  Decimal                 ;Преобразуем в десятичный формат

      Wrt   outstr                  ;Выводим на экран

      ret                     ; Выход

WrtStr      endp

;┌─────────────────────────────┐

;│ Процедура удаления пробелов │

;└─────────────────────────────┘

DelSpc      proc  near

      cld                     ; Устанавливаем флагнаправления

      lea   si,buffer         ;Заносим в SI адрес буфера

      mov   di,si             ;Дублируем в DI

      mov   cx,strlen         ;В CX длина считанной строки

      xor   bx,bx             ;Обнуляем BX

      mov   dl,1              ; Условие цикла

del1:lodsb                   ; Загружаем в AL один байт

      cmp   al,65             ;A?

      jb    del2              ;Переход если меньше

      cmp   al,90             ;Z?

      ja    del2              ;Переход если больше

      add   al,32             ;Иначе перевод F-f

      xor   dl,dl             ;Обнуляем DL

      jmp   del4              ;Переход на запись символа

del2:cmp   al,''                  ; Пробел?

      je    del3              ; Если да, то переход

      xor   dl,dl             ;Обнуляем DL

      jmp   del4              ;Переход на запись символа

del3:cmp   dl,1              ;DL=1?

      je    del5              ;Если да, то переход

      mov   dl,1              ;Заносим в DL 1

del4:stosb                   ; Запись символа в строку

      inc   bx                ;Увеличиваем счетчик символов

del5:loop  del1              ;Цикл

      mov   strlen,bx         ;Заносим длину преобразованной строки

      ret                     ; Выход

DelSpc      endp

;┌──────────────────────────┐

;│ Процедура открытия файла │

;└──────────────────────────┘

Fopenproc  near

      mov   ah,3dh           ; Функция открытия файла

      xor   al,al             ;Открываем на чтение (AL=0)

      mov   dx,path1          ;Адрес ASCIIZ строки файла

      int   21h               ;Вызов прерывания DOS

      jnc   ok1               ;Переход, если открытие успешно

      stc                     ; Установка флага переноса

      ret                     ; Выход

ok1:  mov   source,ax         ;Запоминаем дескриптор файла

      ret                     ; Выход

Fopenendp

;┌──────────────────────────┐

;│ Процедура создания файла │

;└──────────────────────────┘

Fcreate     proc  near

      mov   ah,3ch           ; Функция создания файла

      xor   cx,cx             ;Заносим атрибут файла в CX

      mov   dx,path2          ;Адрес ASCIIZ строки файла

      int   21h               ;Вызов прерывания DOS

      jnc   ok2               ;Переход, если файл создан успешно

      mov   ah,3ch                  ;Если выходной файл не задан

      xor   cx,cx             ;Устанавливаем по умолчанию

      lea   dx,default        ; ИмяOUT.COM

      int   21h               ; Пытаемся создать файл

      jnc   ok2               ;Если получилось — на выход

      stc                     ; Установка флага переноса

      ret                     ; Выход

ok2:  mov   dest,ax                 ;Запоминаем дескриптор файла

      ret                     ;Выход

default     db    'OUT.COM',0

Fcreate     endp

;┌──────────────────────────┐

;│Процедуразакрытияфайла│

;└──────────────────────────┘

Fclose      proc  near

      mov   ah,3eh            ;Функциязакрытияфайла

      int   21h               ; Вызов прерывания DOS

      jnc   ok3               ;Переход, если файл успешно закрыт

      Wrt   error05          ; Вывод сообщения обошибке

ok3:  ret                     ;Выход

Fclose      endp

;┌────────────────────────┐

;│Процедурачтенияфайла│

;└────────────────────────┘

Freadproc  near

      lea   dx,buffer         ; Загружаем адрес буфера

      mov   di,dx             ;Запоминаем адрес начала буфера в DI

      xor   si,si             ;Обнуляем SI

      mov   bx,source         ;Заносим в BX дескриптор файла

      mov   cx,1              ;Число символов для чтения

frd1:mov   ah,3fh                  ;Функция чтения из файла

      int   21h               ;Вызов прерывания DOS

      jnc   frd2              ;Переход, если нет ошибки

      wrt   error05                 ;Вывод сообщения об ошибке

      stc                     ; Устанавливаем флагпереноса

      ret                     ; Выход

frd2:cmp   ax,0              ;Если AX=0, то достигнут конец файла

      je    end1              ;переход на установку флага EOF

      inc   si                ;Увеличиваем счетчик

      cmp   byte ptr [di],10  ; Смотрим не пустая ли строка

      je    frd3              ;Если да, то переход

      inc   dx                ;Увеличиваем адрес буфера

      inc   di                ;Увеличиваем указатель начала буфера

      jmp   frd1              ;Чтение следующего символа

end1:mov   EOF,1             ;Устанавливаем флаг конца файла

frd3:clc                     ; Сброс флага переноса

      ret                     ; Выход

Freadendp

;┌─────────────────────────┐

;│ Процедура записи в файл │

;└─────────────────────────┘

Fwrite      proc  near

      mov   bx,dest                 ;Заносим в BX дескриптор

      lea   dx,cod                  ;Заносим в DX записываемый код

      mov   cx,2              ;Число байт для записи

      mov   ah,40h                  ;Функция записи в файл

      int   21h               ;Вызов прерывания DOS

      jnc   ok4               ;Переход, если нет ошибки

      Wrt   error10                 ;Вывод сообщения об ошибке

ok4:  ret                     ;Выход

Fwrite      endp

;┌──────────────────────────┐

;│Процедураудаленияфайла│

;└──────────────────────────┘

Fdel  proc  near

      mov   dx,path2          ;Путь к удаляемому файлу

      mov   ah,41h                  ;Функция удаления файла

      int   21h               ;Вызов прерывания DOS

      jnc   ok5               ;Переход, если нет ошибки

      lea   dx,defaul2        ;Пробуем удалить OUT.COM

      mov   ah,41h                  ;Функция удаления файла

      int   21h               ;Вызов прерывания DOS

      jnc   ok5               ;Переход, если нет ошибки

      Wrt   error11                 ;Вывод сообщения об ошибке

ok5:  ret                     ;Выход

defaul2     db    'OUT.COM',0

Fdel  endp

;┌────────────────────────────────┐

;│Процедуракодированияоперации│

;└────────────────────────────────┘

Coding      proc  near

      inc   di                ; Увеличиваемуказательвмассиве

      mov   si,di             ; Заносим в SI адрес первогооперанда

      mov   cod,0             ;Обнулаяем код

      mov   numbop,0          ;Номер операнда — первый

      mov   al,','                  ;Будем искать разделитель операндов

      mov   cx,strlen         ;В CX заносим длину строки

      sub   cx,4              ;Вычитаем длину ADD+пробел

      repnescasb             ;Начало поиска

      je    cod1              ;Переход, если разделитель найден

      Wrt   error07                 ;Выдаем сообщение об ошибке

      call  WrtStr                  ;Выводим адрес ошибочной строки

      mov   was_error,1       ;Устанавливаем флаг ошибки

      ret                     ; Выход

cod1:mov   second,di         ;В second адрес второго операнда

      dec   di                ;Смещаем указатель

      dec   di                ;на конец первого операнда

cod2:mov   dx,di             ;Запоминаем адрес конца первого оп.

      sub   dx,si             ;Выч. из адреса конца адрес начала

      inc   dx                ; Увеличиваем на 1

      cmp   dx,2              ;Смотрим длину первого операнда

      je    cod3              ;Если она равна 2, операнд — регистр

      ja    cod8              ;Если больше, операнд — память

      Wrt   error08                 ;Выдаем сообщение об ошибке

      call  WrtStr                  ;Выводим адрес ошибочной строки

      mov   was_error,1       ;Устанавливаем флаг ошибки

      ret                     ; Выход

; --------------------------------------; операнд — регистр

cod3:mov   dx,16             ;Всего 16 регистров. DX — счетчик

      lea   di,Rtable         ;Загружаем адрес таблицы регистров

newreg:     mov   cx,2              ;Сравниваем два символа

      rep   cmpsb             ;Начало сравнения

      je    regfound          ;Переход, если регистр найден

      inc   di                ;Увеличиваем смещение в таблице на 1

      inc   di                ;Увеличиваем смещение в таблице на 1

      dec   si                ;Указатель на начало перв. операнда

      dec   dx                ;Уменьшаем счетчик на 1

      jnz   newreg                  ;Если еще не все регистры, переход

      Wrt   error08                 ;Если регистр не найден — ошибка

      call  WrtStr                  ;Выводим адрес ошибочной строки

      mov   was_error,1       ;Устанавливаем флаг ошибки

      ret                     ; Выход

regfound:

      mov   ah,[di]                 ;Запоминаем код регистра

      cmp   numbop,0          ;Если это первый операнд

      je    cod7              ;То переход на установку d-бита

      cmp   typeop,1          ;Иначе это второй операнд

      je    cod4              ;Переход, если первый оп. имеет тип m

      xor   al,al             ;Иначе оба операнда регистры

      mov   bx,cod                  ;Заносим в BX код операции

      mov   bh,ah             ;Заносим в BH код регистра

      and   bx,0101h          ;Сравниваем w-биты

      cmp   bh,bl             ;Обоих операндов

      je    cod5              ;Если они равны, то переход

      Wrt   error09                 ;Иначе ошибка — несоответствие типов

      call  WrtStr                  ;Выводим адрес ошибочной строки

      mov   was_error,1       ;Устанавливаем флаг ошибки

      ret                     ; Выход

cod4:mov   al,ah             ;Заносим в AL код команды

      and   al,01h                  ;Устанавливаем в 1 w-бит

      and   ah,00111000b            ;Установка битов в поле reg

      jmp   cod6              ;Переход на следующий операнд

cod5:mov   cl,3              ;Будем сдвигать на 3 бита вправо

      shr   ah,cl             ;Сдвигаем код регистра в поле r/m

      or    ah,0c0h                 ;Установка поля mod в 11

                             ;(т.е. биты r/m определяют регистр)

cod6:or    cod,ax                  ;Накладка установленных битов на код

      inc   numbop                  ;Берем второй операнд

      mov   typeop,0          ;Устанавливаем тип операнда r

      jmp   cod11             ;Переход далее

cod7:mov   al,02h                  ;Установка бита направления (d-бит)

      or    al,ah             ;Накладываем на код

      and   ax,0011100000000011b    ; Установка битов в поле reg и r/m

      mov   cod,ax                  ;Заносим полученное в готовый код

      inc   numbop                  ;Увеличиваем номер операнда

      mov   typeop,0          ;Устанавливаем тип операнда r

      jmp   short cod11       ;Переход далее

;---------------------------------------; операнд — память

cod8:cmp   numbop,0          ;Первый операнд?

      je    cod9              ;Если да — переход

      cmp   typeop,1          ;Тип операнда m?

      jne   cod9              ;Если нет — переход

      Wrt   error10                 ;Иначе ошибка: оба операнда — память

      call  WrtStr                  ;Выводим номер ошибочной строки

      mov   was_error,1       ;Устанавливаем флаг ошибки

      ret                     ; Выход

cod9:cmp   byte ptr [si],'['; Операнд начинается со скобки?

      jne   cod10             ;Если нет — переход на ошибку

      cmp   byte ptr [di],']'; Операнд заканчивается скобкой?

      jne   cod10             ;Если нет — переход на ошибку

      inc   si                ;Пропускаем скобку

      dec   di                ;Отодвигаем указатель назад от скобки

      mov   dx,di             ;Заносим в DX конец операнда

      sub   dx,si             ;Вычитаем из конца начало строки

      inc   dx                ;Увеличиваем на 1

                             ;Т.о. в DX — длина операнда

; — Далее идет установка полей mod и r/m---------------------------

      mov   bx,7              ;Всего 7 типов адресации памяти

      lea   di,ExTabl         ;Адрес таблицы способов адресации

rm1:  push  si                ;Запоминаем адрес начала операнда

      mov   cl,[di]                 ;Заносим в CL длину операнда

      xor   ch,ch             ; ОбнуляемCH

      inc   di                ; Двигаем указатель в ExTabl

      cmp   cx,dx             ;Сравниваем длины операндов

      jne   rm2               ;Переход если не равны

      rep   cmpsb             ;Иначе сравниваем на соответствие

      je    rm3               ;Переход если равны

rm2:  inc   di                ;Двигаем указатель в ExTabl на 1

      add   di,cx             ;Теперь сдвигаем его на 5

      pop   si                ;Восст. адрес начала операнда

      dec   bx                ;Уменьшаем счетчик вариантов

      jnz   rm1               ;Если он не равен нулю — переход

      Wrt   error08                 ;Если счетчик равен 0, а соответствий

      call  WrtStr                  ;не найдено, значит ошибка в операнде

      mov   was_error,1       ;Устанавливаем флаг ошибки

      ret                     ; Выход

rm3:  pop   si                ;Восст. адрес начала операнда

      mov   ah,[di]                 ;Заносим в AH код операции

      xor   al,al             ; Обнуляем<st1:State w:st=«on»><st1:place w:st=«on»>AL</st1:place></st1:State>

      or    cod,ax                  ; Накладываем на код кодоперации

      inc   numbop                  ;Увеличиваем номер операнда

      mov   typeop,1          ;Устанавливаем тип операнда m

      jmp   cod11             ;Переход дальше

cod10:

      Wrt   error08                 ;Выводим сообщение об ошибке

      call  WrtStr                  ;Выводим ошибочную строку

      mov   was_error,1       ;Устанавливаем флаг ошибки

      ret

cod11:      cmp   numbop,1          ;Э

еще рефераты
Еще работы по программированию, базе данных