Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Call VvodMas ;ввод массива AСтр 1 из 3Следующая ⇒
Практическая работа №5. Тема: Функции BIOS и DOS для работы с экраном и клавиатурой, использование подпрограмм. Материалы и оборудование: листы бумаги А4 или тетрадные, авторучка, персональная ЭВМ с установленным отладчиком «Insight», файловым менеджером (Far, NC, Windows Commander и т.п.), компилятором и компоновщиком Ассемблера версии «Турбо- ассемблер 2.0» (tasm.exe, tlink.exe).
Цель работы – научиться разработке простейших модульных и интерактивных программ на языке Ассемблера.
Выполнение задания 1) Разработать алгоритм решения задачи с использованием модульного программирования.
Без использования подпрограмм (модулей) создание сколь либо сложной программы стало бы титаническим трудом. Представьте, что для того, чтобы посчитать сумму элементов скажем 100 массивов пришлось бы писать программу суммирования массива 100 раз. На самом деле, для подобных целей существуют подпрограммы (модули) – это отдельный участок алгоритма, который вызывается из основной программы (другой подпрограммы) с определенными параметрами. Кроме этого назначения, программирование алгоритма в виде отдельных подпрограмм облегчает восприятие сложных алгоритмов и позволяет использовать эту подпрограмму в других алгоритмах, существенно сокращая время разработки. Технология программирования помощью подпрограмм называется модульным программированием. В данном случае для написания программы алгоритм разделяется на модули (подпрограммы), те в свою очередь также могут разделяться на подпрограммы и так далее, то есть быть вложенными, как и циклы. Затем разрабатывается алгоритм каждого модуля. В данном случае есть два подхода к технологии программирования – нисходящее и восходящее проектирование – при первом подходе сначала составляется общий алгоритм, при этом подпрограммы рассматриваются как «черный ящик», то есть известны данные на входе и на выходе, но неизвестен алгоритм их преобразования. Затем последовательно («сверху-вниз») разрабатываются алгоритмы отдельных модулей. При восходящем проектировании процесс производится в обратном порядке. При структурном программировании (основная технология, применяемая при процедурном программировании, по сути предшественница, но до сих пор актуальная, наиболее популярной в настоящее время технологии объектно-ориентированного программирования).
Состав модулей при модульном программировании отображается на схеме иерархии модулей. Рекомендуется строгая иерархия, то есть чтобы модули не вызывали друг друга на одном уровне иерархии и не «перескакивали» через уровень. Типичная схема иерархии модулей выглядит следующим образом: Пример: Вычислить выражение: . Исходными данными служит n и массивы a,b. Использовать подпрограмму вычисления квадрата числа. Исходные данные должны вводиться вручную, а ответ выводиться на экран. Необходимо учитывать возможность переполнения и выдавать в этом случае соответствующее предупреждение.
Какие основные подпрограммы будут нужны нам для решения данной задачи? Это, во-первых, суммирование элементов массива, ввод массива, вывод числа. Кроме того, при суммировании элементов потребуется подпрограмма вычисления квадрата числа, при вводе массива подпрограмма – подпрограммы ввода и преобразования числа из символьного представления во внутреннее. В языках высокого уровня модули часто разделяются на процедуры и функции. Последние отличаются тем, что возвращают одно значение и могут быть использованы в выражениях. В языке ассемблера разницы между процедурами и функциями нет. Алгоритм основной программы:
В блок-схеме вызов подпрограммы при этом обозначается прямоугольником с двумя дополнительными линиями по краям. После этого разрабатываются алгоритмы подпрограмм. На блок-схемах алгоритмов подпрограмм вместо слов «начало» и «конец» используются «вход» и «выход». Например, блок-схема алгоритма подпрограммы «ввод массива»:
Строгое неравенство здесь обусловлено тем, что индексы в массиве начинаются с 0, соответственно в массиве из 5 элементов последний элемент будет с индексом 4. И так далее. Не всегда обязательно описывать алгоритм каждого модуля именно блок-схемой, в ряде случаев может быть достаточно словесного описания или описания на языке программирования. Например, возведение числа в квадрат блок-схемой описывать не обязательно, куда понятнее просто команда imul ax. Чем сложнее алгоритм, тем более он нуждается в интуитивно более понятном, по исследованиям психологов, графическом описании.
2) Закодировать алгоритм с использованием подпрограмм на языке ассемблера и с использованием ввода-вывода.
Процедуры в языке ассемблера следующим способом:
<идентификатор> proc …. <идентификатор> endp
Команды вызова – CALL Команда возврата – RET
Например: CALL VVOD CALL RASCHET CALL VYVOD RET (Возврат из главной программы)
VVOD PROC …. RET VVOD ENDP ………
Подпрограммы рекомендуется описывать между командой выхода из основной программы и описанием данных. Каждая подпрограмма сама по себе может содержать описание данных, однако они должны быть уникальны по всему тексту программы, то есть являются глобальными. Важно понимать, что директивы proc и endp не являются командами процессора, и для него вся программа всё равно составляет единую последовательность команд в памяти. Поэтому, если Вы, допустим, забудете поставить в конце основной программы команду RET, процессор всё равно начнет выполнять следующую команду, даже записанную в отдельной процедуре, поскольку она следующая расположена в памяти. (Вообще говоря, любое название процедуры можно использовать просто как метку: CALL VVOD …
VVOD: … ret) Точно также и любые данные могут быть интерпретированы процессором как команда и любая команда (её машинный код) может быть использована процессором как данные. Например: Db 0B8h,0,0 эквивалентна команде mov ax,0 и наоборот. Такой принцип, вытекающий из архитектуры Фон-Неймана (архитектуры вычислительной системы, при которой для команд и для данных используется общая память), предоставляет программисту на ассемблере уникальные преимущества по сравнению с языками высокого уровня – например, программа может модифицировать себя в процессе выполнения. Значения всех регистров, используемых при обработке данных внутри подпрограмм, целесообразно сохранять при входе в подпрограмму и восстанавливать после выхода из нее. AA PROC PUSH AX PUSH BX … POP BX POP AX RET AA ENDP
Форматы команды CALL аналогичны форматам команды JMP. Команда CALL выполняется следующим образом – в стек записывается адрес возврата (следующей за CALL команды), после чего происходит передача управления (JMP). Команда RET «достает» из стека сохраненные значения, за счет чего происходит возврат в основную программу и реализуется. Благодаря свойству стека «последний пришел первый ушел» (LIFO) реализуется вложенность подпрограмм и возможность рекурсии (вызова подпрограммой самой себя, рекурсия например может быть использована при вычислении факториала числа). Однако следует помнить, что стек не должен измениться при вызове подпрограммы (то есть количество команд push и pop внутри подпрограммы должно быть одинаковым), иначе команда ret вернет управление совсем не в то место программы, откуда подпрограмма была вызвана.
После описания алгоритма необходимо определить соглашение о параметрах на входе и на выходе из процедуры – то есть что и где передается модулю, и что и где он возвращает. Механизмы передачи параметров модулям в языке ассемблера могут быть – через глобальные переменные (то есть общие для всех процедур), через регистры, через стек. В ассемблере переменные не разделяются на локальные и глобальные средствами языка. Передача параметров через стек обычно осуществляется при компиляции программ с языков высокого уровня (Паскаль, Си и т.д.). Наиболее простым решением является передача параметров через регистры.
Состав входных и выходных параметров может быть изображен в виде HIPO-диаграммы (см. практическую работу №2). Или описан в виде таблицы, или представлен непосредственно в программе в виде комментариев (для простых программ). Если подпрограмма изменяет содержимое каких-нибудь других регистров (не связанных с входными и выходными данными), об этом необходимо также упомянуть в составе выходных параметров. При определении параметров необходимо уже представлять себе используемые в программе команды. Например, адрес памяти должен обязательно передаваться в регистрах, по которым можно адресовать память, если предполагается использовать строковые команды – то надо использовать регистры SI DI, для организации цикла – регистр СХ и т.п.
Для нашего примера:
Затем, когда разработаны алгоритмы процедур, начинаем кодировать их на языке ассемблера, как делали в предыдущих практических работах. Для того, чтобы закодировать вызов подпрограммы, поступаем следующим образом – сначала записываем нужные параметры (входные для неё) в регистры, затем вызываем подпрограмму командой CALL. В самой подпрограмме перед выходом запишем в нужные регистры результаты её работы (сформируем выходные параметры). Естественно, регистры, в которых подпрограмма возвращает результат, сохранять в стеке не надо, иначе никакого результата возвращено не будет. В частности, основная программа будет выглядеть так:
Основная программа: Model tiny Code Org 100h N equ 5 start: Mov di,offset A Mov di,offset B Call SumMas Call SumMas Call vyvod Ret VvodMas proc Ret VvodMas endp SumMas proc Ret Summas endp Vyvod proc Ret Vyvod endp Vvod proc Ret Vvod endp Convab proc Ret Convab endp A db N dup (?) B db N dup (?) End start Директива компилятора EQU обозначает установку константы – символ N будет заменен ассемблером при компиляции на цифру 5. Это компромиссный вариант, позволяющий избежать сложности с обработкой массивов произвольного размера и вместе с тем позволяющий исправить лишь один символ в ней при необходимости изменить её для обработки массивов других размерностей. Остальные процедуры пока не описаны. Затем последовательно приступаем к кодированию остальных процедур. Для того, чтобы программа была интерактивной, то есть осуществляла взаимодействие с пользователем, необходимо организовывать ввод данных с клавиатуры и вывод на экран. Непосредственно работая с ними, как с аппаратными устройствами, это было бы сделать затруднительно – во-первых, разные модели данного периферийного оборудования могут иметь различные версии схем и соответственно интерфейса (соглашения об обмене данными), во-вторых, получались бы довольно громоздкие программы (например, монитора управляется своим контроллером, встроенным в видеоадаптер и имеющим свой процессор и т.д.). Для того, чтобы эффективно работать с периферийным оборудованием, эти функции в основном осуществляются вызовами функций операционных систем – дисковой (DOS) и записанной в постоянной памяти (ПЗУ) компьютера (микропроцессорного устройства) - BIOS. Вызов этих функций осуществляется как вызов некоей подпрограммы, которой передаются параметры (что вывести и куда, или откуда ввести и как). Данная программа операционной системы выполняет требуемые действия и возвращает управление пользовательской программе. В компьютерах на базе микропроцессоров семейства Intel8086 обычно реализуется этот вызов с помощью вызова программного прерывания (будут рассмотрены нами в 7-й работе). Правда, в операционных системах Windows используется обычная команда CALL. Функции операционной системы вызываются следующим образом – в AH записывается номер функции, в другие регистры – необходимые параметры (определяется типом функции), после чего вызывается операционная система командой INT <номер прерывания>. Наиболее часто используются следующие номера прерываний: INT 21h – вызов функций DOS INT 16h – вызов функций BIOS для работы с клавиатурой INT 10h – вызов функций BIOS для работы с экраном INT 1Ah – вызов функций BIOS для работы с таймером.
Mov ah,01 Int 21h; ввод Cmp al,’0’ Jl nov_vvod Cmp al,’9’ Jg nov_vvod Mov [bx],al Inc bx Jmp nov_vvod ……. String db 10 dup (?) Помимо ввода/вывода с клавиатуры программа также может получать данные с командной строки. То, что указывается после имени программы при её запуске, называется параметрами командной строки (они разделяются пробелами). В частности, при использовании нами Tlink.exe параметры командной строки – lab3.obj и /t. Командная строка при запуске программы расположена по адресу DS:0080h в формате Длина строки, строка, заканчивающаяся кодом 0Dh.
Кроме процедур в программе также можно использовать макросы – последовательность команд, на которую компилятор заменяет название макроса (макрокоманды) в тексте программы. Например, чтобы не писать много раз при выводе на экран последовательность из 3-х команд, можно оформить их в виде следующей макрокоманды. Print macro x Mov dx,offset x Mov ah,09 Int 21h Endm Описание макрокоманды делается вначале (после org 100h и перед start:). Тогда, если приходится выводить в программе много разных сообщений, можно каждый раз писать одну команду вместо трех:
Сам машинный код от этого не изменится, просто сократится время набирания программы. Компилятор ассемблера, встретив в тексте Print заменит его на последовательность 3-х команд, описанных в макросе, а «х» (параметр макрокоманды в описании) заменит на msg1. Работа с экраном. Экран (дисплей) с точки зрения программиста на ассемблере – тоже массив цифровой информации. Этот массив хранится в специальной области памяти, называемой видеопамять. Содержимое «текстовой» видеопамяти (то есть отображение экрана в текстовом режиме) начинается с адреса B800:0000, графической A000:0000. Видеоадаптер считывает данные области памяти и отображает на экране информацию в соответствии с режимом работы (текстовым или графическим). Экран для программиста как бы состоит из отдельных ячеек, которые имеют свои координаты, отсчитываемые по горизонтали и вертикали (столбцы и строки). Координаты начинаются с 0. В текстовом режиме в ячейке может быть записан какой-либо символ, всего таких ячеек в зависимости от режима либо 80х25, либо 40х25 (столбцов х строк) в зависимости от режима экрана. В графическом режиме – точка (пиксель), которых опять же в зависимости от режима может быть от 320х200 до 1024х768 и более (по горизонтали х по вертикали). В текстовой видеопамяти за каждую «ячейку» отвечают 2 байта – в первом содержится ASCII-код символа, во второй – байт атрибутов. Байт атрибутов определяет цвет символа и фона. Соответственно по адресу B800:0000 находится ASCII-код первого символа (в верхнем левом углу), B800:0001 – цвет его и фона, B800:0002 – второй символ и т.д. Байт атрибутов организован следующим образом –
Бит интенсивности отвечает за яркость символа (1 – яркий), признак мерцания (1 – символ мерцает на экране). Биты R – red – красный, G – green – зеленый, B – blue – синий отвечают за соответствующие цвета. С помощью их комбинаций (как и в фотографии, где изображение формируется из трех основных цветов) и определяется цвета символа и фона. Например, 001 –синий, 010 – зеленый, 100 – красный, 011 – желтый и т.п. В графической видеопамяти каждый байт (для режимов с количеством цветов до 16, иначе используются несколько байт) отвечает за отдельный пиксель и обозначает его цвет – адресу A000:0000 соответствует цвет точки с координатами (0,0) – левый верхний угол экрана, A000:0001 – точке с координатами (0,1) и т.д.
Установка видеорежима VvodMas proc Push cx;сохраним регистры Push si Mov cx,N Vm1: call vvod Call ConvAb Stosb; запомним в массиве Loop Vm1 Pop si Pop cx Ret VvodMas endp ;______________ Vvod proc Push ax Mov ah,0ah Int 21h Pop ax Ret Vvod endp ;-------------------- ;Процедура преобразования строки ASCII в число byte ;Входные параметры: DS:DX+1 - длина строки, DS:DX+2 - строка ; т.е. совпадает с форматом буфера ввода в функции 0A DOS ConvAb proc Push si Push cx Push dx Mov si,dx Mov dl,0; обнулим сумму Mov mno,1 Lodsb Jg Ext Cbw Dec si Lodsb Jl Ext cmp al,'9' Jg Ext Sub al,30h Mov al,mno Mul des Mov mno,al Cld Mov al,dl Pop dx Pop cx Pop si Ret Mno db 1 ConvAb endp ; выходные параметры: ; AL - число, если произошла ошибка - то, что можно было преобразовать ;----------------- Imul al Ret Sqrr endp ;---------------- SumMas proc Push si Push bx Push cx Mov bx,0; Обнулим сумму Mov cx,N Pop cx Pop bx Pop si Ret Summas endp ;---------------- Vyvod proc Push ax Mov cx,0 New_Delenie: Div desW Mov ah,0eh; вывод символа Int 10h Loop V Pop cx Pop ax Pop dx Ret Vyvod endp Обратите внимания, что при написании программы целесообразно делать отступы в строках для смыслового выделения участков алгоритма и комментариев! Теперь, когда все подпрограммы написаны, приступаем к тестированию программы. Процедуры для ввода и вывода числа вы можете сохранить в отдельном файле (с расширением.asm или.inc) и использовать в дальнейших программах. В этом случае в том месте, где вам надо было писать такие же процедуры, укажите вместо них Include <имя файла> Следует только помнить, что директива компилятора include просто включает текст в исходный файл, поэтому необходимо, чтобы все имена переменных и меток были уникальны для обеих файлов.
3) Протестировать программу. Поскольку программа интерактивна, мы можем уже непосредственно запустить её из командной строки файлового менеджера (FAR) или с помощью команды «выполнить» в меню «пуск» Windows. Для проверки работы программы подберите тестовые данные (лучше несколько комплектов) и последовательно запускайте программу, вводя их. В случае, если программа «зависает» или выдает неверный ответ, воспользуйтесь отладчиком Insight для определения ошибочных команд (или данных), выполняя программу по одной команде и наблюдая за результатами команд и логикой её выполнения. При этом вызов подпрограмм может быть выполнен как одна команда, если использовать в отладчике клавишу F8 вместо F7. Найдя ошибку, исправьте текстовый файл с программой, перекомпилируйте и запустите её заново. Для приведенного примера тестовые данные могут быть например такими – N=5; A db 1,2,3,3,1 B db 2,4,2,3,0 Результат – 1*1 + 2*2 + 3*3 + 3*3 + 1*1 (= 24)+2*2+4*4+2*2+3*3+0*0=57. Остальные варианты работ делаются таким же образом. Практическая работа №5. Тема: Функции BIOS и DOS для работы с экраном и клавиатурой, использование подпрограмм. Материалы и оборудование: листы бумаги А4 или тетрадные, авторучка, персональная ЭВМ с установленным отладчиком «Insight», файловым менеджером (Far, NC, Windows Commander и т.п.), компилятором и компоновщиком Ассемблера версии «Турбо- ассемблер 2.0» (tasm.exe, tlink.exe).
Цель работы – научиться разработке простейших модульных и интерактивных программ на языке Ассемблера.
Выполнение задания 1) Разработать алгоритм решения задачи с использованием модульного программирования.
Без использования подпрограмм (модулей) создание сколь либо сложной программы стало бы титаническим трудом. Представьте, что для того, чтобы посчитать сумму элементов скажем 100 массивов пришлось бы писать программу суммирования массива 100 раз. На самом деле, для подобных целей существуют подпрограммы (модули) – это отдельный участок алгоритма, который вызывается из основной программы (другой подпрограммы) с определенными параметрами. Кроме этого назначения, программирование алгоритма в виде отдельных подпрограмм облегчает восприятие сложных алгоритмов и позволяет использовать эту подпрограмму в других алгоритмах, существенно сокращая время разработки. Технология программирования помощью подпрограмм называется модульным программированием. В данном случае для написания программы алгоритм разделяется на модули (подпрограммы), те в свою очередь также могут разделяться на подпрограммы и так далее, то есть быть вложенными, как и циклы. Затем разрабатывается алгоритм каждого модуля. В данном случае есть два подхода к технологии программирования – нисходящее и восходящее проектирование – при первом подходе сначала составляется общий алгоритм, при этом подпрограммы рассматриваются как «черный ящик», то есть известны данные на входе и на выходе, но неизвестен алгоритм их преобразования. Затем последовательно («сверху-вниз») разрабатываются алгоритмы отдельных модулей. При восходящем проектировании процесс производится в обратном порядке. При структурном программировании (основная технология, применяемая при процедурном программировании, по сути предшественница, но до сих пор актуальная, наиболее популярной в настоящее время технологии объектно-ориентированного программирования). Состав модулей при модульном программировании отображается на схеме иерархии модулей. Рекомендуется строгая иерархия, то есть чтобы модули не вызывали друг друга на одном уровне иерархии и не «перескакивали» через уровень. Типичная схема иерархии модулей выглядит следующим образом: Пример: Вычислить выражение: . Исходными данными служит n и массивы a,b. Использовать подпрограмму вычисления квадрата числа. Исходные данные должны вводиться вручную, а ответ выводиться на экран. Необходимо учитывать возможность переполнения и выдавать в этом случае соответствующее предупреждение.
Какие основные подпрограммы будут нужны нам для решения данной задачи? Это, во-первых, суммирование элементов массива, ввод массива, вывод числа. Кроме того, при суммировании элементов потребуется подпрограмма вычисления квадрата числа, при вводе массива подпрограмма – подпрограммы ввода и преобразования числа из символьного представления во внутреннее. В языках высокого уровня модули часто разделяются на процедуры и функции. Последние отличаются тем, что возвращают одно значение и могут быть использованы в выражениях. В языке ассемблера разницы между процедурами и функциями нет. Алгоритм основной программы:
В блок-схеме вызов подпрограммы при этом обозначается прямоугольником с двумя дополнительными линиями по краям. После этого разрабатываются алгоритмы подпрограмм. На блок-схемах алгоритмов подпрограмм вместо слов «начало» и «конец» используются «вход» и «выход». Например, блок-схема алгоритма подпрограммы «ввод массива»:
Строгое неравенство здесь обусловлено тем, что индексы в массиве начинаются с 0, соответственно в массиве из 5 элементов последний элемент будет с индексом 4. И так далее. Не всегда обязательно описывать алгоритм каждого модуля именно блок-схемой, в ряде случаев может быть достаточно словесного описания или описания на языке программирования. Например, возведение числа в квадрат блок-схемой описывать не обязательно, куда понятнее просто команда imul ax. Чем сложнее алгоритм, тем более он нуждается в интуитивно более понятном, по исследованиям психологов, графическом описании.
2) Закодировать алгоритм с использованием подпрограмм на языке ассемблера и с использованием ввода-вывода.
Процедуры в языке ассемблера следующим способом:
<идентификатор> proc …. <идентификатор> endp
Команды вызова – CALL Команда возврата – RET
Например: CALL VVOD CALL RASCHET CALL VYVOD RET (Возврат из главной программы)
VVOD PROC …. RET VVOD ENDP ………
Подпрограммы рекомендуется описывать между командой выхода из основной программы и описанием данных. Каждая подпрограмма сама по себе может содержать описание данных, однако они должны быть уникальны по всему тексту программы, то есть являются глобальными. Важно понимать, что директивы proc и endp не являются командами процессора, и для него вся программа всё равно составляет единую последовательность команд в памяти. Поэтому, если Вы, допустим, забудете поставить в конце основной программы команду RET, процессор всё равно начнет выполнять следующую команду, даже записанную в отдельной процедуре, поскольку она следующая расположена в памяти. (Вообще говоря, любое название процедуры можно использовать просто как метку: CALL VVOD …
VVOD: … ret) Точно также и любые данные могут быть интерпретированы процессором как команда и любая команда (её машинный код) может быть использована процессором как данные. Например: Db 0B8h,0,0 эквивалентна команде mov ax,0 и наоборот. Такой принцип, вытекающий из архитектуры Фон-Неймана (архитектуры вычислительной системы, при которой для команд и для данных используется общая память), предоставляет программисту на ассемблере уникальные преимущества по сравнению с языками высокого уровня – например, программа может модифицировать себя в процессе выполнения. Значения всех регистров, используемых при обработке данных внутри подпрограмм, целесообразно сохранять при входе в подпрограмму и восстанавливать после выхода из нее. AA PROC PUSH AX PUSH BX … POP BX POP AX RET AA ENDP
Форматы команды CALL аналогичны форматам команды JMP. Команда CALL выполняется следующим образом – в стек записывается адрес возврата (следующей за CALL команды), после чего происходит передача управления (JMP). Команда RET «достает» из стека сохраненные значения, за счет чего происходит возврат в основную программу и реализуется. Благодаря свойству стека «последний пришел первый ушел» (LIFO) реализуется вложенность подпрограмм и возможность рекурсии (вызова подпрограммой самой себя, рекурсия например может быть использована при вычислении факториала числа). Однако следует помнить, что стек не должен измениться при вызове подпрограммы (то есть количество команд push и pop внутри подпрограммы должно быть одинаковым), иначе команда ret вернет управление совсем не в то место программы, откуда подпрограмма была вызвана.
После описания алгоритма необходимо определить соглашение о параметрах на входе и на выходе из процедуры – то есть что и где передается модулю, и что и где он возвращает. Механизмы передачи параметров модулям в языке ассемблера могут быть – через глобальные переменные (то есть общие для всех процедур), через регистры, через стек. В ассемблере переменные не разделяются на локальные и глобальные средствами языка. Передача параметров через стек обычно осуществляется при компиляции программ с языков высокого уровня (Паскаль, Си и т.д.). Наиболее простым решением является передача параметров через регистры. Состав входных и выходных параметров может быть изображен в виде HIPO-диаграммы (см. практическую работу №2). Или описан в виде таблицы, или представлен непосредственно в программе в виде комментариев (для простых программ). Если подпрограмма изменяет содержимое каких-нибудь других регистров (не связанных с входными и выходными данными), об этом необходимо также упомянуть в составе выходных параметров. При определении параметров необходимо уже представлять себе используемые в программе команды. Например, адрес памяти должен обязательно передаваться в регистрах, по которым можно адресовать память, если предполагается использовать строковые команды – то надо использовать регистры SI DI, для организации цикла – регистр СХ и т.п.
Для нашего примера:
Затем, когда разработаны алгоритмы процедур, начинаем кодировать их на языке ассемблера, как делали в предыдущих практических работах. Для того, чтобы закодировать вызов подпрограммы, поступаем следующим образом – сначала записываем нужные параметры (входные для неё) в регистры, затем вызываем подпрограмму командой CALL. В самой подпрограмме перед выходом запишем в нужные регистры результаты её работы (сформируем выходные параметры). Естественно, регистры, в которых подпрограмма возвращает результат, сохранять в стеке не надо, иначе никакого результата возвращено не будет. В частности, основная программа будет выглядеть так:
Основная программа: Model tiny Code Org 100h N equ 5 start: Mov di,offset A call VvodMas;ввод массива A Mov di,offset B
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||
Последнее изменение этой страницы: 2016-12-17; просмотров: 435; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.147.238.70 (0.234 с.) |