Практикум для изучения дисциплины «Основы программирования»



Pdf көрінісі
бет68/81
Дата08.07.2020
өлшемі1,55 Mb.
#74978
түріПрактикум
1   ...   64   65   66   67   68   69   70   71   ...   81
Байланысты:
А.А. Тюгашев

помощью цифр
Здесь,  в  отличие  от  языков  программирования  высокого  уровня,  видна 
особенность  программирования  на  низком  уровне —  многие  вещи 
приходится реализовывать самостоятельно. Итак, напишем подпрограмму 
(назовем  ее  outint),  которая  позволит  выводить  на  экран  целое  число, 
например,  находящееся  в  регистре  AX,  используемом  для  передачи 
аргумента. 
Будем  реализовывать  подпрограмму  сразу  как  универсальную,  что 
является  признаком  хорошего  стиля  в  программировании.  Наша 
подпрограмма сможет выводить число как в десятичном, так и в двоичном, 
и  в  другом  виде —  с  использованием  позиционной  системы  счисления  с 
произвольным  основанием.  Вспомним  правило  записи  чисел  в 
позиционной системе: 
 
N 
= ∑ q
i
g
i
i = 0…M
где M — количество разрядов числа; q
i
 — 
основание системы счисления в 
степени  i,  g
i
 — 
значение  цифры  в  позиции  i,  а  i —  номер  позиции 
(разряда),  начиная  с  нуля  и  справа  налево.  Будем  делить  наше  число  на 
основание системы счисления и накапливать остатки от деления, которые 
и  будут  значениями  цифр.  Далее  приводится  возможный  вариант 
программы. В секции описания данных появится 
schisl  dw 10 ; основание системы счисления 
Chislo  db '      ' ; строка где будет записываться цифрами число 
Здесь мы резервируем место (пустую строку из нескольких пробелов) для 
формирования записи числа, начиная с адреса Chislo в памяти, а кроме 
этого  заносим  по  умолчанию  в  качестве  основания  системы  счисления  в 
ячейку schisl 10. 
Сама подпрограмма может выглядеть следующим образом: 
outint: ; вывод содержимого ax в окне сообщений 


138 
 
        
mov edi,Chislo ; заносим в регистр edi адрес строки для 
записи числа цифрами 
        
add edi,5 ; записывать цифры будем  начиная с правой, 
поэтому переходим к концу строки 
l:      xor dx,dx ; обнуление dx 
        
div [schisl] ; после выполнения div в dl автоматически 
заносится остаток от деления 
        add d
l,'0' ; для получения кода цифры прибавляем к числу код 
нуля 
        
mov [edi],dl ; пересылаем в память, где хранится запись 
числа цифрами, очередную  
        
dec edi ;передвигаемся к следующему байту — идем от конца 
        
or ax,ax ; проверяем ax, где остается частное, на равенство 
нулю, если нет - 
        
jnz l ; продолжаем делить 
         
        
; вызов WinAPI MessageBox для вывода строки 
        invoke  MessageBox,HWND_DESKTOP,Chislo,"
Сумма 
нечетных",MB_OK  
        ret 
Итак,  сначала  мы  заносим  в  регистр  EDI  (расширенная  версия  DI, 
используется  из-за  32-разрядной  архитектуры)  адрес  начала  будущей 
записи числа цифрами в памяти с помощью команды mov edi,Chislo. 
Однако вспомним, что при формировании позиционной записи мы пишем 
остатки  справа  налево —  следовательно,  нужно  перейти  к  концу  строки. 
Поскольку мы отвели пять позиций под запись числа, добавляем 5 к адресу 
командой  add  edi,5  (адресная  арифметика  в  ассемблере).  Следующая 
строка —  начало  цикла,  поэтому  она  помечена  l.  В  ней  первая  команда 
иллюстрирует  программистский  трюк —  для  обнуления  регистра  DX 
используется  xor  значения  самого  с  собой —  команда  выполняется 
быстрее,  нежели  mov  dx,0.  Далее  с  помощью  div  [schisl] 
производится деление солержимого AX на основание системы счисления, 
извлекаемое  из  соответствующей  ячейки  памяти  с  помощью  косвенной 
адресации. Особенностью команды div является то, что в данном случае 
остаток от деления автоматически попадает в младшие биты регистра DX, 
называемые DL. А нам именно этот остаток и нужен! Пересылаем его по 
адресу,  на  который  указывает  EDI  (косвенная  адресация),  однако 
предварительно превращаем остаток, который сам по себе является числом 
от  0  до  9  при  основании  системы  счисления  10,  в  соответствующий  код 
символа.  Сделать  это  несложно  ,  поскольку  в  используемой  кодировке 
коды  цифр  идут  подряд.  Достаточно  с  помощью  команды  add  dl,'0' 
прибавить  код  нуля,  чтобы  получить  необходимый  символ —  цифру.  С 
помощью команды dec edi переходим к предыдущей позиции в памяти. 


139 
 
Как  только  число  будет  исчерпано,  в  качестве  частного  от  деления, 
попадающего  по  умолчанию  в  AX,  мы  получим  ноль,  что  должно  стать 
сигналом  о  завершении  цикла.  Проверку  значения  AX  на  ноль  можно 
осуществить с помощью часто используемой в программах на ассемблере 
логической операции ИЛИ аргумента самого с собой or ax,ax (заметим, 
что  в  ряде  ассемблеров  существует  специальная  команда  тестирования 
содержимого  ячейки  и  установки  флагов,  например  TST).  Продолжаем 
цикл, если это необходимо, с помощью команды условного перехода jnz 
l

После завершения цикла запись числа будет сформирована в виде строки 
по  адресу  Chislo.  C  помощью  системного  вызова  invoke 
MessageBox,HWND_DESKTOP,Chislo,"
Сумма  нечетных",MB_OK 
на  экране  демонстрируется  окно  сообщений  с  соответствующим 
содержимым. 
Последняя  строчка  подпрограммы —  команда  ret  возврата  в 
вызывающую программу. 
Контрольные вопросы 
1. 
Какой  прием  используется  в  рассмотренной  программе  для 
преобразования выводимого на экран числа в строку? 
2. 
Почему команда shr применима для проверки нечетности числа? 
3. 
Где  в  приведенной  программе  используется  косвенная  адресация? 
Поясните механизм косвенной адресации. 
4. 
Можно  ли  использовать  команду  xor  для  обнуления  ячейки  памяти? 
Почему? 
5. 
Зачем  в  программе  используется  команда  ИЛИ  регистра  самого  с 
собой? 
Макросы в ассемблере 
Поскольку,  как  было  продемонстрировано,  при  программировании  на 
языке  ассемблера  многие  вещи  приходится  реализовывать  вручную, 
весьма  активно  применяется  «расширение»  языка  на  основе  аппарата 
макросов. Говоря коротко, макросы позволяют заменять одни фрагменты 
текста  в  программе  другими  (называются  макрорасширениями) —  этот 
процесс  называется  макроподстановкой  (использование  макросов 
аналогично применению директивы #define в языке программирования 
Си).  При  этом  возможно  использование  макросов  с  параметрами,  как 
показано далее: 
<
имя> MACRO <формальные параметры


140 
 
<
тело
ENDM 
При  выполнении  макроподстановки  в  тексте  программы  <имя>  будет 
заменено  на  <тело>  с  подстановкой  в  нем  указываемых  фактических 
параметров  вместо  формальных.  Параметры  макроса  записываются  через 
запятую  или  пробел.  Размещать  макроопределения  в  тексте 
программыследует  до  первой  макрокоманды,  использующей  макрос. 
Макросредства  при  программировании  на  языках  ассемблера  настолько 
популярны, что сам язык иногда называют макроассемблером


Достарыңызбен бөлісу:
1   ...   64   65   66   67   68   69   70   71   ...   81




©engime.org 2024
әкімшілігінің қараңыз

    Басты бет