Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

СПРАВОЧНИК по системе программирования ТУРБО АССЕМБЛЕР 2.0


Оглавление

                 Пример программы на языке Ассемблера
-----------------------------------------------------------------

     Давайте теперь попробуем реализовать все то, что мы узнали в
последних  двух главах, в виде полезного примера программы на Ас-
семблере. Эта программа WCOUNT.ASM подсчитывает число слов в фай-
ле и выводит его на экран.

;
; Программа для подсчета числа слов в файле. Слова разделены
; пробелами, символами табуляции, возврата каретки или перевода
; строки.
;
; Вызов: wc < имя_файла.расш
;
            DOSSEG                      ; выбрать стандартный
                                        ; порядок сегментов
            .MODEL   SMALL              ; код и данные
                                        ; помещаются в 64К
            .STACK   200h               ; стек размером 512
                                        ; байт
            .DATA
Count                DW   0             ; используется для
                                        ; подсчета слов
InWhitespace         DB   ?             ; устанавливается в
                                        ; значение 1, когда
                                        ; последним прочитанным
                                        ; символов является
                                        ; разделитель
TempChar             DB   ?             ; временная память,
                                        ; используемая
                                        ; в GetNextCharacter
Result               DB   'Число слов: ', 5 DUP (?)
                                        ; строка, используемая
                                        ; для вывода результата
CountInsertEnd       LABEL BYTE         ; используется для
                                        ; определения конца
                                        ; области, в которой
                                        ; хранится строка со
                                        ; значением счетчика
                     DB   0dh,0ah,'$'   ; функция DOS 9
                                        ; работает со строками,
                                        ; которые завершаются
                                        ; символом $
                  .CODE
ProgramStart:
                  mov   ax,@Data
                  mov   ds,ax            ; DS указывает на
                                         ; сегмент данных
                  mov   [InWhitespace],1 ; предположим, это
                                         ; разделитель, так как
                                         ; первый отличный от
                                         ; разделителя символ,
                                         ; который мы найдем,
                                         ; будет отмечать начало
                                         ; слова
CountLoop:
                  call GetNextCharacter  ; получить следующий
                                         ; символ для проверки,
                  jz   CountDone         ; если он имеется
                  call IsCharacterWhitespace ; это разделитель?
                  jz   IsWhitespace      ; да
                  cmp  [InWhitespace],0  ; символ не является
                                         ; разделителем - теперь
                                         ; мы в разделителе?
                  jz   CountLoop         ; мы не в разделителе
                                         ; и символ не является
                                         ; разделителем, поэтому
                                         ; с этим символом работа
                                         ; окончена
                  inc  [Count]           ; мы в разделителе и
                                         ; символ не является
                                         ; разделителем, значит
                                         ; мы нашли начало нового
                                         ; слова
                  mov  [InWhitespace],0  ; отметить, что мы боль-
                                         ; ше не в разделителе
                  jmp  CountLoop         ; обработать следующий
                                         ; символ
IsWhitespace:
                  mov  [InWhitespace],1  ; отметить, что мы в
                                         ; разделителе
                  jmp  CountLoop         ; обработать следующий
                                         ; символ
;
; Подсчет завершен - вывести результаты
;
CountDone:
                  mov  ax,[Count]        ; число, которое нужно
                                         ; преобразовать в строку
                  mov  bx,OFFSET CountInsertEnd-1 ; ссылка на
                                         ; конец строки, в
                                         ; которую нужно
                                         ; поместить число
                  mov  cx,5              ; число цифр, которые
                                         ; нужно преобразовать
                  call ConvertNumberToString ; преобразовать
                                         ; число в строку
                  mov  bx,OFFSET Result  ; ссылка на строку
                                         ; результата
                  call PrintString       ; вывести результат
                  mov  ah,4ch            ; функция DOS
                                         ; завершения программы
                  int  21h               ; завершить программу
;
; Подпрограмма получения следующего символа из стандартного
; ввода
;
; Входные данные: нет
;
; Выходные данные:
;     AL = символ, если он был доступен
;     флаг Z = 0 (NZ), если символ доступен,
;            = 1 (Z) при достижении конца строки
;
; Нарушаемые регистры: AH, BX, CX, DX
;
GetNextCharacter       PROC
                  mov  ah,3fh           ; функция DOS
                                        ; чтения из файла
                  mov  bx,0             ; стандартный
                                        ; описатель ввода
                  mov  cx,1             ; считать один символ
                  mov  dx,OFFSET TempChar ; поместить символ
                                        ; в TempChar
                  int  21h              ; получить следующий
                                        ; символ
                  jc   NoCharacterRead  ; если DOS сообщает
                                        ; об ошибке,
                                        ; интерпретировать ее,
                                        ; как конец файла
                  cmp  [TempChar],1ah   ; это Control-Z?
                                        ; (метка конца файла)
                  jne  NotControlZ      ; нет
NoCharacterRead:
                  sub  ax,ax            ; установить флаг Z,
                  and  ax,ax            ; что отражает, был
                                        ; ли считан символ (NZ)
                                        ; или мы достигли
                                        ; конца файла (Z).
                                        ; Обратите внимание,
                                        ; что функция DOS 3fh
                                        ; устанавливает регистр
                                        ; AX в значение числа
                                        ; считанных символов
                  mov  al,[TempChar]    ; возвратить считанный
                                        ; символ
                  ret                   ; выполнено
GetNextCharacter       ENDP
;
; Подпрограмма, сообщающая, является ли прочитанный символ
; разделителем
;
; Входные данные:
;     AL = проверяемому символу
;
; Выходные данные:
;     флаг Z = 0 (NZ), если символ не является разделителем,
;            = 1 (Z) если символ - разделитель
;
; Нарушаемые регистры: нет
;
IsCharacterWhitespace  PROC
                  cmp  al,09h           ; это символ табуляции?
                  jz   EndIsCharacterWhitespace ; если да, то
                                        ; это разделитель
                  cmp  al,' '           ; это пробел?
                  jz   EndIsCharacterWhitespace ; если да, то
                                        ; это разделитель
                  cmp  al,0dh           ; это возврат каретки?
                  jz   EndIsCharacterWhitespace ; если да, то
                                        ; это разделитель
                  cmp  al,0ah           ; это перевод строки?
                  cmp  al,' '           ; это пробел?
                                        ; если да, то это
                                        ; разделитель,
                                        ; возвратить Z, если
                                        ; нет, то это не
                                        ; разделитель, возвратить
                                        ; NZ (устанавливаться
                                        ; cmp)
EndIsCharacterWhiteSpace:
                  ret
IsCharacterWhiteSpace  ENDP
;
; Подпрограмма, преобразующая двоичное число в текстовую
; строку
;
; Входные данные:
;     AX = число, которое нужно преобразовать
;     DS:BX = указатель на конец строки, в которой
;     сохраняется текст
;
; Выходные данные: нет
;
; Нарушаемые регистры: AX, BX, CX, DX, SI
;
ConvertNumberToString  PROC
                  mov  si,10            ; используется в цикле
                                        ; ConvertLoop
                  sub  dx,dx            ; преобразовать AX в
                                        ; двойное слово в AD:DX
                  div  si               ; разделить число на 10
                                        ; остаток - в DX, это
                                        ; десятичное число из
                                        ; одной цифры; число/10
                                        ; находится в AX
                  add  dl,'0'           ; преобразовать остаток
                                        ; в текстовую строку
                  mov  [bx],dl          ; поместить эту цифру в
                                        ; строку
                  dec  bx               ; ссылка на следующую
                                        ; самую значащую цифру
                  loop ConvertLoop      ; обработать следующую
                                        ; цифру, если она есть
                  ret
ConvertNumberToString  ENDP
;
; Подпрограмма, выводящая строку на экран дисплея
;
; Входные данные:
;     DS:BX = указатель на выводимую строку
;
; Выходные данные: нет
;
; Нарушаемые регистры: нет
;
PrintString            PROC
                   push  ax             ; сохранение регистров
                   push  dx             ; в подпрограмме
                   mov   ah,9           ; функция DOS вывода
                                        ; строки
                   mov   dx,bx          ; установить DS:DX на
                                        ; выводимую строку
                   int   21h            ; вызвать DOS для
                                        ; вывода строки
                   pop   dx             ; восстановить измененные
                   pop   ax             ; регистры
                   ret                  ; возврат управления
PrintString              ENDP
                   END   ProgramStart

     Выполняемый файл WCOUNT.EXE можно запускать в ответ на подс-
казку  DOS, переназначив ввод из файла, в котором вы хотите подс-
читать  слова.  Например,  для  подсчета  числа  слов   в   файле
WCOUNT.ASM нужно в ответ на подсказку DOS ввести:

        wcount <wcount.asm

     Через несколько секунд на экран будет выведен результат:

        Число слов: nnn

(где вместо nnn будет стоять конкретное число).

     Относительно файла WCOUNT.ASM можно сделать несколько  инте-
ресных замечаний. Во-первых, для выполнения различных функций при
чтении символа, проверки символа на  разделитель,  преобразования
числа  слов в строку и вывода строки в файле WCOUNT.ASM использу-
ются подпрограммы. Это позволяет сделать основную программу файла
WCOUNT.ASM небольшой по размеру и простой для понимания.

     Другое преимущество использования подпрограмм заключается  в
простоте,  с  какой  вы можете изменять работу подпрограмм. Если,
например, вам  потребуется  изменить  определение  разделителя  и
включить  в число разделителей знак равенства, вы можете изменить
подпрограмму IsWhitespace, оставив основную программу без измене-
ний.

     Заметим, что подпрограммы GetNextCharacter   и  IsWhitespace
возвращают  информацию  о  состоянии  во влаге нуля (подпрограмма
GetNextCharacter возвращает также информацию в регистре AL). Флаг
нуля  прекрасно  подходит для возврата состояния типа "да/нет", а
регистр AL (или AX) хорошо использовать для возврата значений.

     Наконец, обратим внимание на объем кода на Ассемблере, необ-
ходимый  для  выполнения операций по выводу текста. Чтобы вывести
на экран целое значение (число подсчитанных слов),  нам  пришлось
сначала  преобразовать значение счетчика в текстовую строку (пов-
торно выполняя деление на 10 и добавляя к  остатку  символ  "0").
Только  после  этого вызвали DOS для вывода текстовой строки. Это
сильно отличается от простого оператора на языке Си:

        print("Число слов: dn",count);

     С другой стороны, после того, как вы  напишете  подпрограммы
(такие, как ConvertNumberToString), вы можете повторно их исполь-
зовать. Если сформировать библиотеку полезных подпрограмм, то это
может  в последующем существенно облегчить и упростить разработку
программ.


Оглавление

Оставить комментарий

Комментарий:
можно использовать BB-коды
Максимальная длина комментария - 4000 символов.
 
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог