Процедура вызывается из другой функции с помощью инструкции

Процедуры

Определение и вызов процедур

Последнее обновление: 02.07.2023

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

Для определения процедуры применяется выражение

proc_name proc

где proc_name — имя процедуры.

Завершается определение процедуры выражением

proc_name endp

где proc_name — также имя процедуры.

Между proc_name proc и proc_name endp идет произвольный набор инструкций. Перед завершением процедуры помещается инструкция
ret, которая передает управление в вызывающий код. Например:

.code
setReg proc     ; начало процедуры setReg
    mov rax, 10
    ret
setReg endp     ; конец процедуры setReg

main proc
    ret
main endp
end

Здесь определены две процедуры — главная функция main и процедура setReg. В процедуре setReg устанавливается значение регистра rax. При компиляции подобной программы (допустим, она находится в файле hello.asm) с помощью команды

ml64 hello.asm /link /entry:main

благодаря флагу /entry:main будет создавать файл, при запуске которого выполняется процедура с именем main.
Но в нашем случае эта процедура пока ничего не делает, а процедура setReg автоматически не выполняется. Чтобы выполнить одну процедуру/функцию в другой, необходимо использовать
инструкцию call, после которой указывается имя выполняемой процедуры:

call proc_name

Инструкция call помещает в стек 64-битный адрес инструкции, которая идет сразу после вызова. Значение, которое вызов помещает в стек, называется
адресом возврата. Когда процедура завершает выполнение, для возвращения к вызывающему коду она выполняет инструкцию ret. Команда
ret извлекает 64-битный адрес возврата из стека и косвенно передает управление на этот адрес.

Например, выполним процедуру setReg в функции main:

.code
setReg proc     ; начало процедуры setReg
    mov rax, 10
    ret
setReg endp     ; конец процедуры setReg

main proc
    call setReg ; вызов процедуры setReg
    ret
main endp
end

Вызываемые процедуры могут, в свою оцередь вызывать другие процедуры. Например:

.code
inner proc
    add rax, 1
    ret
inner endp

outer proc
    call inner
    add rax, 1
    ret
outer endp

main proc
    mov rax, 1
    call outer
    ret
main endp
end

Здесь функция main вызывает процедуру outer, а та вызывает процедуру inner. В итоге к завершению программы в регистре RAX будет число 3.

Стек и процедуры

При работе со стеком в процедурах следует учитывать, что вызов процедуры с помощью инструкции call помещает в стек адрес возврата. При завершении процедуры инструкция
ret извлечет этот адрес возврата из стека и перейдет по этому адресу. Таким образом, выполнение вернется в код, где была вызвана процедура. Поэтому
при вызове инструкции ret (при завершении процедуры) адрес возврата должен быть в верхушке стека.

Но при невнимательности это требование может быть нарушено. Например:

.code
sum proc
    push rbx        ; сохраняем регистр RBX в стек
    add rax, rbx
    ret             ; регистр RBX НЕ восстанавливаем
sum endp

main proc
    mov rax, 1
    mov rbx, 2
    call sum
    ret
main endp
end

Здесь вызывается процедура sum, в которой в стек сохраняется регистр RBX. Однако в конце процедуры регистр RBX не восстанавливается. Поэтому в качестве адреса вохврата будет рассматриваться
значение регистра RBX, которое при вызовае инструкции ret будет находится в верхушке стека. В итоге поведение программы неопределено, и скорее всего она
завершится ошибкой.

Другой пример — извлечение адреса возврата до завершения процедуры:

.code
sum proc
    pop rbx        ; извлекаем данные из стека в регистр RBX
    add rax, rbx
    ret             ; адрес возврата неопределен
sum endp

main proc
    mov rax, 1
    mov rbx, 2
    call sum
    ret
main endp
end

Здесь в регистр RBX извлекаются данные из стека — по сути в него извлекается адрес возврата. В результате опять же поведение программы неопределено.

Поэтому процедура должна извлекать из стека все ранее сохраненные в ней данные и извлекать ровно столько, сколько было сохранено, чтобы адрес возврата сохранялся в стеке и к концу программы
оказался в верхушке стека.

 

Процедура (подпрограмма) — это основная функциональная единица декомпозиции (разделения на несколько частей) некоторой задачи. Процедура представляет собой группу команд для решения конкретной подзадачи и обладает средствами получения управления из точки вызова задачи более высокого приоритета и возврата управления в эту точку. В простейшем случае программа может состоять из одной процедуры. Процедуру можно определить и как правильным образом оформленную совокупность команд, которая, будучи однократно описана, при необходимости может быть вызвана в любом месте программы.
Функция – процедура, способная возвращать некоторое значение.

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

Для описания последовательности команд в виде процедуры в языке ассемблера используются две директивы: PROC и ENDP.

Синтаксис описания процедуры:

ИмяПроцедуры PROC язык расстояние
; тело процедуры
ИмяПроцедуры ENDP

В заголовке процедуры (директиве PROC) обязательным является только задание имени процедуры. Атрибут расстояние может принимать значения near или far и характеризует возможность обращения к процедуре из другого сегмента кода. По умолчанию атрибут расстояние принимает значение near, и именно это значение используется при выборе плоской модели памяти FLAT.

Процедура может размещаться в любом месте программы, но так, чтобы на нее случайным образом не попало управление. Если процедуру просто вставить в общий поток команд, то микропроцессор будет воспринимать команды процедуры как часть этого потока. Учитывая это обстоятельство, есть следующие варианты размещения процедуры в программе:

  • в начале программы (до первой исполняемой команды);
  • в конце (после команды, возвращающей управление операционной системе);
  • промежуточный вариант — тело процедуры располагается внутри другой процедуры или основной программы;
  • в другом модуле.

Размещение процедуры в начале сегмента кода предполагает, что последовательность команд, ограниченная парой директив PROC и ENDP, будет размещена до метки, обозначающей первую команду, с которой начинается выполнение программы. Эта метка должна быть указана как параметр директивы END, обозначающей конец программы:


.code
myproc proc near
ret
myproc endp
start proc
call myproc

start endp
end start

В этом фрагменте после загрузки программы в память управление будет передано первой команде процедуры с именем start.
Объявление имени процедуры в программе равнозначно объявлению метки, поэтому директиву PROC в частном случае можно рассматривать как форму определения метки в программе.

Размещение процедуры в конце программы предполагает, что последовательность команд, ограниченная директивами PROC и ENDP, будет размещена после команды, возвращающей управление операционной системе.


.code
start proc
call myproc

start endp
myproc proc near
ret
myproc endp
end start

Промежуточный вариант расположения тела процедуры предполагает ее размещение внутри другой процедуры или основной программы. В этом случае требуется предусмотреть обход тела процедуры, ограниченного директивами PROC и ENDP, с помощью команды безусловного перехода jmp:


.code
start proc
jmp ml
myproc proc near
ret
myproc endp
ml:

start endp
end start

Последний вариант расположения описаний процедур — в отдельном модуле — предполагает, что часто используемые процедуры выносятся в отдельный файл. Файл с процедурами должен быть оформлен как обычный исходный файл и подвергнут трансляции для получения объектного кода. Впоследствии этот объектный файл на этапе компоновки объединяется с файлом, в котором эти процедуры используются. Этот способ предполагает наличие в исходном тексте программы еще некоторых элементов, связанных с особенностями реализации концепции модульного программирования в языке ассемблера. Вариант расположения процедур в отдельном модуле используется также при построении Windows-приложений на основе вызова API-функций.

Поскольку имя процедуры обладает теми же атрибутами, что и метка в команде перехода, то обратиться к процедуре можно с помощью любой команды условного или безусловного перехода. Но благодаря специальному механизму вызова процедур можно сохранить информацию о контексте программы в точке вызова процедуры. Под контекстом понимается информация о состоянии программы в точке вызова процедуры. В системе команд микропроцессора есть две команды, осуществляющие работу с контекстом. Это команды call и ret:

  • call ИмяПроцедуры@num — вызов процедуры (подпрограммы).
  • ret число — возврат управления вызывающей программе.

число — необязательный параметр, обозначающий количество байт, удаляемых из стека при возврате из процедуры.

@num – количество байт, которое занимают в стеке переданные аргументы для процедуры (параметр является особенностью использования транслятора MASM).

Объединение процедур, расположенных в разных модулях

Особого внимания заслуживает вопрос размещения процедуры в другом модуле. Так как отдельный модуль — это функционально автономный объект, то он ничего не знает о внутреннем устройстве других модулей, и наоборот, другим модулям также ничего не известно о внутреннем устройстве данного модуля. Но каждый модуль должен иметь такие средства, с помощью которых он извещал бы транслятор о том, что некоторый объект (процедура, переменная) должен быть видимым вне этого модуля. И наоборот, нужно объяснить транслятору, что некоторый объект находится вне данного модуля. Это позволит транслятору правильно сформировать машинные команды, оставив некоторые их поля незаполненными. Позднее, на этапе компоновки настраивает модули и разрешает все внешние ссылки в объединяемых модулях.

Для того чтобы объявить о видимых извне объектах, программа должна использовать две директивы MASM: extern и public. Директива extern предназначена для объявления некоторого имени внешним по отношению к данному модулю. Это имя в другом модуле должно быть объявлено в директиве public. Директива public предназначена для объявления некоторого имени, определенного в этом модуле и видимого в других модулях. Синтаксис этих директив следующий:

extern имя:тип, …, имя:тип
public имя, …, имя

Здесь имя — идентификатор, определенный в другом модуле. В качестве идентификатора могут выступать:

  • имена переменных;
  • имена процедур;
  • имена констант.

Тип определяет тип идентификатора. Указание типа необходимо для того, чтобы транслятор правильно сформировал соответствующую машинную команду. Действительные адреса будут вычислены на этапе компоновки, когда будут разрешаться внешние ссылки. Возможные значения типа определяются допустимыми типами объектов для этих директив:

  • если имя — это имя переменной, то тип может принимать значения byte, word, dword, qword и tbyte;
  • если имя — это имя процедуры, то тип может принимать значения near или far; в компиляторе MASM после имени процедуры необходимо указывать число байтов в стеке, которые занимают аргументы функции:

    extern p1@0:near

  • если имя — это имя константы, то тип должен быть abs.

Пример использования директив extern и public для двух модулей

;Модуль 1
.586
.model flat, stdcall
.data
extern p1@0:near
.code
start proc
call p1@0
ret
start endp
end start

;Модуль 2
.586
.model flat, stdcall
public p1
.data
.code
p1 proc
ret
p1 endp
end

Исполняемый модуль находится в программе Модуль 1, поскольку содержит метку start, с которой начинается выполнение программы (эта метка указана после директивы end в программе Модуль 1). Программа вызывает процедуру p1, внешнюю, содержащуюся в файле Модуль 2. Процедура p1 не имеет аргументов, поэтому описывается в программе Модуль 1 с помощью директивы

extern p1@0:near

@0 – количество байт, переданных функции в качестве аргументов
near – тип функции (для плоской модели памяти всегда имеет тип near).

Вызов процедуры осуществляется командой

call p1@0

Организация интерфейса с процедурой

Аргумент — это ссылка на некоторые данные, которые требуются для выполнения возложенных на модуль функций и размещенных вне этого модуля. По аналогии с макрокомандами рассматривают понятия формального и фактического аргументов. Исходя из этого, формальный аргумент можно рассматривать не как непосредственные данные или их адрес, а как местодержатель для действительных данных, которые будут подставлены в него с помощью фактического аргумента. Формальный аргумент можно рассматривать как элемент интерфейса модуля, а фактический аргумент — это то, что фактически передается на место формального аргумента.

Переменные — это данные размещенные в регистре или ячейке памяти, которые могут в дальнейшем подвергаться изменению.

Константы — данные, значения которых не могут изменяться.

Сигнатура процедуры (функции) — это имя функции, тип возвращаемого значения и список аргументов с указанием порядка их следования и типов.

Семантика процедуры (функции) — это описание того, что данная функция делает. Семантика функции включает в себя описание того, что является результатом вычисления функции, как и от чего этот результат зависит. Обычно результат выполнения зависит только от значений аргументов функции, но в некоторых модулях есть понятие состояния. Тогда результат функции может зависеть от этого состояния, и, кроме того, результатом может стать изменение состояния. Логика этих зависимостей и изменений относится к семантике функции. Полным описанием семантики функций является исполняемый код функции или математическое определение функции.

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

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

  • через регистры;
  • через общую область памяти;
  • через стек;
  • с помощью директив extern и public.

Передача аргументов через регистры – это наиболее простой в реализации способ передачи данных. Данные, переданные подобным способом, становятся доступными немедленно после передачи управления процедуре. Этот способ очень популярен при небольшом объеме передаваемых данных.

Ограничения на способ передачи аргументов через регистры:

  • небольшое число доступных для пользователя регистров;
  • нужно постоянно помнить о том, какая информация в каком регистре находится;
  • ограничение размера передаваемых данных размерами регистра. Если размер данных превышает 8, 16 или 32 бита, то передачу данных посредством регистров произвести нельзя. В этом случае передавать нужно не сами данные, а указатели на них.

Передача аргументов через общую область памяти – предполагает, что вызывающая и вызываемая программы используют некоторую область памяти как общую. Для организации такой области памяти используется атрибут комбинирования сегментов common. Наличие этого атрибута указывает компоновщику, как нужно комбинировать сегменты, имеющие одно имя: все сегменты, имеющие одинаковое имя в объединяемых модулях, будут располагаться компоновщиком, начиная с одного адреса оперативной памяти. Это значит, что они будут перекрываться в памяти и, следовательно, совместно использовать выделенную память. Данные в сегментах common могут иметь одинаковые имена. Главное – структура общих сегментов. Она должна быть идентична во всех модулях использующих обмен данными через общую память.
Недостатком этого способа в реальном режиме работы микропроцессора является отсутствие средств защиты данных от разрушения, так как нельзя проконтролировать соблюдение правил доступа к этим данным.

Передача аргументов через стек наиболее часто используется для передачи аргументов при вызове процедур. Суть этого способа заключается в том, что вызывающая процедура самостоятельно заносит в стек передаваемые данные, после чего передает управление вызываемой процедуре. При передаче управления процедуре микропроцессор автоматически записывает в вершину стека 4 байта. Эти байты являются адресом возврата в вызывающую программу. Если перед передачей управления процедуре командой call в стек были записаны переданные процедуре данные или указатели на них, то они окажутся под адресом возврата.
Стек обслуживается тремя регистрами:

  • SS — указатель дна стека (начала сегмента стека);
  • ESP — указатель вершины стека;
  • EBP — указатель базы.

Микропроцессор автоматически работает с регистрами ESS и ESP в предположении, что они всегда указывают на дно и вершину стека соответственно. По этой причине их содержимое изменять не рекомендуется. Для осуществления произвольного доступа к данным в стеке архитектура микропроцессора имеет специальный регистр EBP. Так же, как и для регистра ESP, использование EBP автоматически предполагает работу с сегментом стека.
Перед использованием этого регистра для доступа к данным стека его содержимое необходимо правильно инициализировать, что предполагает формирование в нем адреса, который бы указывал непосредственно на переданные данные. Для этого в начало процедуры рекомендуется включить дополнительный фрагмент кода. Он имеет свое название — пролог процедуры. Код пролога состоит всего из двух команд:

push ebp
mov ebp, esp

Первая команда сохраняет содержимое ebр в стеке с тем, чтобы исключить порчу находящегося в нем значения в вызываемой процедуре. Вторая команда пролога настраивает ebp на вершину стека. После этого можно не волноваться о том, что содержимое esp перестанет быть актуальным, и осуществлять прямой доступ к содержимому стека.

Конец процедуры также должен содержать действия, обеспечивающие корректный возврат из процедуры. Фрагмент кода, выполняющего такие действия, имеет свое название — эпилог процедуры. Код эпилога должен восстановить контекст программы в точке вызова процедуры из вызывающей программы. При этом, в частности, нужно откорректировать содержимое стека, убрав из него ставшие ненужными аргументы, передававшиеся в процедуру. Это можно сделать несколькими способами:

  • используя последовательность из n команд pop xx. Лучше всего это делать в вызывающей программе сразу после возврата управления из процедуры;
  • откорректировать регистр указателя стека esp на величину 4*n, например, командой

    add esp,NN

    где NN=4*n (n — количество аргументов). Это также лучше делать после возврата управления вызывающей процедуре;

  • используя машинную команду ret n в качестве последней исполняемой команды в процедуре, где n — количество байт, на которое нужно увеличить содержимое регистра esp после того, как со стека будут сняты составляющие адреса возврата. Этот способ аналогичен предыдущему, но выполняется автоматически микропроцессором.

Программа, содержащая вызов процедуры с передачей аргументов через стек:

.586
.model flat, stdcall
.stack 4096
.data
.code
proc_1 proc        ; начало процедуры
push ebp           ; пролог: сохранение EBP
mov ebp, esp       ; пролог: инициализация EBP
mov eax, [ebp+8]   ; доступ к аргументу 4
mov ebx, [ebp+12] ; доступ к аргументу 3
mov ecx, [ebp+16] ; доступ к аргументу 2
pop ebp            ; эпилог: восстановление EBP
ret 12
proc_1 endp
main proc
push 2
push 3
push 4
call proc_1
ret
main endp
end main

Стек программы

Для доступа к аргументу 4 достаточно сместиться от содержимого ebр на 8 байт (4 байта хранят адрес возврата в вызывающую процедуру, и еще 4 байта хранят значение регистра ebр, помещенное в стек данной процедурой), для аргумента 3 — на 12 и т. д.

Пролог и эпилог прогцедуры можно также заменить командами поддержки языков высокого уровня:

  • Команда enter подготавливает стек для обращения к аргументов, имеет 2 операнда :
    первый определяет количество байт в стеке, используемых для хранения локальных идентификаторов процедуры;
    второй определяет уровень вложенности процедуры.
  • Команда leave подготавливает стек к возврату из процедуры, не имеет операндов.

proc_1 proc
enter 0,0
mov eax, [ebp+8]
mov ebx, [ebp+12]
mov ecx, [ebp+16]
leave
ret 12
proc_1 endp

Передача аргументов с помощью директив extern и public используется в случаях, если

  • оба модуля используют сегмент данных вызывающей программы;
  • у каждого модуля есть свой собственный сегмент данных;
  • модули используют атрибут комбинирования сегментов public в директиве сегментации segment.

Рассмотрим пример вывода на экран двух символов, описанных в вызывающей программе. Два модуля используют только сегмент данных вызывающей программы. В этом случае не требуется переопределения сегмента данных в вызываемой процедуре.

;Модуль 1
.586
.model flat, stdcall
.data
STR1    DB «Программа»,0
STR2    db «Меня зовут Лена «,0
extern p1@0:near
public STR1, STR2
.code
start proc
call p1@0
ret
start endp
end start

;Модуль 2
.586
.model flat, stdcall
public p1
extern STR1:BYTE, STR2:BYTE
EXTERN MessageBoxA@16:NEAR

.code
p1 proc
PUSH     0
PUSH     OFFSET STR1
PUSH     OFFSET STR2
PUSH     0
CALL     MessageBoxA@16
ret
p1 endp
end

Способы передачи аргументов в процедуру

В процедуру могут передаваться либо данные, либо их адреса (указатели на данные). В языке высокого уровня это называется передачей по значению и по адресу, соответственно.
Наиболее простой способ передачи аргументов в процедуру — передача по значению. Этот способ предполагает, что передаются сами данные, то есть их значения. Вызываемая программа получает значение аргумента через регистр или через стек. При передаче переменных через регистр или стек на их размерность накладываются ограничения, связанные с размерностью используемых регистров или стека. При передаче аргументов по значению в вызываемой процедуре обрабатываются их копии. Поэтому значения переменных в вызывающей процедуре не изменяются.
Передача аргументов по адресу предполагает, что вызываемая процедура получает не сами данные, а их адреса. В процедуре нужно извлечь эти адреса тем же методом, как это делалось для данных, и загрузить их в соответствующие регистры. После этого, используя адреса в регистрах, следует выполнить необходимые операции над самими данными. В отличие от способа передачи данных по значению, при передаче данных по адресу в вызываемой процедуре обрабатывается не копия, а оригинал передаваемых данных. Поэтому при изменении данных в вызываемой процедуре они автоматически изменяются и в вызывающей программе, так как изменения касаются одной области памяти.

Возврат результата из процедуры

В общем случае программист располагает тремя вариантами возврата значений из процедуры:

  • С использованием регистров. Ограничения здесь те же, что и при передаче данных, — это небольшое количество доступных регистров и их фиксированный размер. Данный способ является наиболее быстрым, поэтому его есть смысл использовать для организации критичных по времени вызова процедур.
  • С использованием общей области памяти. Этот способ удобен при возврате большого количества данных, но требует внимательности в определении областей данных и подробного документирования для устранения неоднозначностей.
  • С использованием стека. Здесь, подобно передаче аргументов через стек, также нужно использовать регистр ebр. При этом возможны следующие варианты:
    — использование для возвращаемых аргументов тех же ячеек в стеке, которые применялись для передачи аргументов в процедуру. То есть предполагается замещение ставших ненужными входных аргументов выходными данными;
    — предварительное помещение в стек наряду с передаваемыми аргументами фиктивных аргументов с целью резервирования места для возвращаемого значения. При использовании этого варианта процедура, конечно же, не должна пытаться очистить стек командой ret. Эту операцию придется делать в вызывающей программе, например командой pop.

Назад: Язык ассемблера

<оператор2> <имя Функции > =<возвращаемоеЗначение>

End Function

Кроме того, что ключевое слово Sub заменяется на Function, в теле процедуры-функции обязательно присутствует оператор присваивания имени функции какого-нибудь значения. Это значение и возвращается функцией. В заголовке функции может быть описан тип возвращаемого значения. Если этот тип не указан, функция возвращает значение Variant. Если такая процедура-функция описана в стандартном модуле, она появляется при работе с мастером функций в категории Определенные пользователем. Ее можно использовать так же, как и другие встроенные функции.

Вызов подпрограмм и функций

Вызов процедуры-подпрограммы отличается от вызова процедуры-функции.

Обычно подпрограмма вызывается из другой подпрофаммы или функции с помощью специального оператора VBA. Если она имеет аргументы, ей передается список фактических параметров. Оператор вызова подпрограммы может использоваться в двух формах:

<имяПроцедуры> <списоиФактическихПараметров>

или

Call <имяПроцедуры>(<списокФаитическихПараметров>)

В первом случае список фактических параметров задается без скобок, во втором — использование скобок обязательно. Но всегда список фактических параметров должен полностью соответствовать списку аргументов, заданному в объявлении подпрограммы. Все фактические параметры для обязательных аргументов должны быть перечислены в том порядке, в каком они присутствуют в описании подпрограммы, после чего могут идти параметры для необязательных аргументов.

Если подпрограмма не имеет аргументов, ее можно вызвать не только из другой процедуры, но и с помощью комбинации клавиш быстрого вызова, команд раскрывающихся меню и кнопок панелей инструментов. Большинство подпрограмм обработки событий также являются подпрограммами без параметров.

Вызов подпрограммы-функции имеет следующий вид:

<имяПеременной>= <имяФункции>(<списокФактическихПараметров>)

29.Локальные сети: назначение, структура, аппаратные и программные средства.

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

тельная сеть (ЛВС).

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

Локальная сеть — (LAN — Local Area Network), данное название соответствует объединению компьютеров, расположенных на сравнительно небольшой территории(одного предприятия, офиса, одной комнаты). Существующие стандарты для ЛВС обеспечивают связь между компьютерами на расстоянии от

2,5 км до 6 км (Ethernet и ARCNET, соответственно).

ЛВС — набор аппаратных средств и алгоритмов, обеспечивающих соединение компьютеров, других периферийных устройств (принтеров, дисковых контроллеров и т.п.) и позволяющих им совместно использовать общую дисковую память, периферийные устройства, обмениваться данными.

Основное назначение ЛВС — в распределении ресурсов ЭВМ: программ, совместимости периферийных устройств, терминалов, памяти. Следовательно, ЛВС должна иметь надежную и быструю систему передачи данных, стоимость которой должна быть меньше по сравнению со стоимостью подключаемых рабочих станций. Иными словами, стоимость передаваемой единицы информации должна быть значительно ниже стоимости обработки информации в рабочих станциях. Исходя из этого ЛВС, как система распределенных ресурсов, должна основываться на следующих принципах:

единой передающей среды;

единого метода управления;

единых протоколов;

гибкой модульной организации;

информационной и программной совместимости.

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

рый поддерживается конкретной сетевой операционной системой, выделяют два типа сетей:

иерархические сети;

сети клиент/сервер.

70

В иерархических сетях все задачи, связанные с хранением, обработкой данных, их представлением пользователям, выполняет центральный компьютер. Пользователь взаимодействует с центральным компьютером с помощью терминала. Операциями ввода/вывода информации на экран управляет центральный компьютер.

Достоинства иерархических систем:

отработанная технология обеспечения отказоустойчивости, сохранности данных;

надежная система защиты информации и обеспечения секретности.

Недостатки:

высокая стоимость аппаратного и программного обеспечения, высокие эксплуатационные расходы;

быстродействие и надежность сети зависят от центрального компьютера.

Всистемах клиент/сервер обработка данных разделена между двумя объектами: клиентом и сервером. Клиент — это задача, рабочая станция, пользователь. Он может сформировать запрос для сервера: считать файл, осуществить поиск записи и т.п. Сервер — это устройство или компьютер, выполняющий обработку запроса. Он отвечает за хранение данных, организацию доступа к этим данным и передачу данных клиенту. В системах клиент/сервер нагрузка по обработке данных распределена между клиентом и сервером, поэтому требования к производительности компьютеров, используемых в качестве клиента и сервера, значительно ниже, чем в иерархических системах.

По организации взаимодействия принято выделять два типа систем, использующих метод клиент/сервер:

равноправная сеть;

сеть с выделенным сервером.

Равноправная сеть — это сеть, в которой нет единого центра управления взаимодействием рабочих станций, нет единого устройства хранения данных. Операционная система такой сети распределена по всем рабочим станциям, поэтому каждая рабочая станция одновременно может выполнять функции как сервера, так и клиента. Пользователю в такой сети доступны все устройства (принтеры, жесткие диски и т.п.), подключенные к другим рабочим станциям.

Достоинства: низкая стоимость (используются все компьютеры, подключенные к сети, и умеренные цены на программное. обеспечение для работы сети); высокая надежность (при выходе из строя одной рабочей станции, доступ прекращается лишь к некоторой части информации).

Недостатки: работа сети эффективна только при количестве одновременно работающих станций не более 10; трудности организации эффективного управления взаимодействием рабочих станций и обеспечение секретности информации; трудности обновления и изменения ПО рабочих станций.

Сеть с выделенным сервером— здесь один из компьютеров выполняет функции хранения данных общего пользования, организации взаимодействия между рабочими станциями, выполнения сервисных услуг — сервер сети. На таком компьютере выполняется операционная система, и все разделяемые устройства (жесткие диски, принтеры, модемы и т.п.) подключаются к нему, выполняет хранение данных, печать заданий, удаленная обработка заданий. Рабочие станции взаимодействуют через сервер, поэтому логическую организацию такой сети можно представить топологией»звезда», где центральное устройство — сервер.

Достоинства: выше скорость обработки данных(определяется быстродействием центрального компьютера, и на сервер устанавливается специальная сетевая операционная система, рассчитанная на обработку и выполнение запросов, поступивших одновременно от нескольких пользователей); обладает надежной системой защиты информации и обеспечения секретности; проще в управлении по сравнению с равноправными.

Недостатки: такая сеть дороже из-за отдельного компьютера под сервер; менее гибкая по сравнению с равноправной.

Для соединения узлов сети используется специальное оборудование:

Сетевые кабели (коаксиальные, состоящие из двух изолированных между собой концентрических проводников, из которых внешний имеет вид трубки; оптоволоконные; кабели на витых парах, образованные двумя переплетёнными друг с другом проводами, и др.).

Коннекторы (соединители) для подключения кабелей к компьютеру; разъёмы для соединения отрезков кабеля.

Сетевые интерфейсные адаптеры для приёма и передачи данных. В соответствии с определённым протоколом управляют доступом к среде передачи данных. Размещаются в системных блоках компьютеров, подключенных к сети. К разъёмам адаптеров подключается сетевой кабель.

Наряду с аппаратными средствами ЛВС должны иметь в своем составе и сложное программное и информационное обеспечение.

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

71

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]

  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #

VBA поддерживает два типа подпрограмм: процедуры и функции.

  • Функция — это подпрограмма, которая возвращает результат. Вызов функции является выражением, и может использоваться в других выражениях или в правой части оператора присваивания.
  • Процедура — это любая подпрограмма, которая не является функцией. Любой макрос VBA является подпрограммой типа «процедура».

Для объявления процедуры в VBA используется ключевое слово Sub:

Sub <имяПроцедуры> [(<списокПараметров>)] <операторы> End Sub 
где:
<имяПроцедуры> – любой допустимый идентификатор VBA;
<списокПараметров> – список формальных параметров процедуры, если он пуст, то такая процедура является макросом;
<операторы> — любая последовательность операторов VBA.

Листинг №.13 Пример объявления процедуры

' Процедура выводит в отладчик максимальное из трех чисел Sub sMax3(A As Long, B As Long, C As Long) If (A > B) And (A > C) Then Debug.Print "Max is "; A ElseIf (B > A) And (B > C) Then Debug.Print "Max is "; B Else Debug.Print "Max is "; C End If End Sub 

Синтаксис объявления функции несколько сложнее, чем синтаксис процедуры:

Function <имяФункции> [(<списокПараметров>)] [As <типФункции>] <операторы> . . . <имяФункции> = <возвращаемое_значение> [<операторы>] End Function 
где:
<имяФункции> — любой допустимый идентификатор;
<списокПараметров> – список формальных параметров процедуры;
<типФункции> — имя любого поддерживаемого VBA типа данных;
<операторы> — любая последовательность операторов VBA.
<возвращаемое_значение> — результат, передаваемый в вызывающую программу.

Листинг №14. Пример объявления функции

' Функция возвращает максимальное из трех чисел Function fMax3(A As Long, B As Long, C As Long) As Long If (A > B) And (A > C) Then fMax3 = A ElseIf (B > A) And (B > C) Then fMax3 = B Else fMax3 = C End If End Function 

Передача параметров в подпрограммы

Подпрограммы VBA могут принимать для обработки формальные параметры, указываемые при объявлении. При вызове они заменяются фактическими параметрами, т.е. реально используемыми в вызывающей программе. В VBA список формальных параметров подпрограммы представляет имена переменных, разделенных запятой. При этом желательно указать тип каждой переменной:

Function | Sub <имяПроцедуры> (<параметр1> As <тип>, _ <параметр2> As <тип>, ..., <параметрN> As <тип>)

Если тип данных параметра не указан, то автоматически будет использован тип Variant. Список параметров может быть пустым как для процедуры, так и для функции. В этом случае после имени процедуры ставятся пустые круглые скобки.

При передаче фактических параметров в подпрограмму может использоваться один из двух различных способов:

  • передача по значению;
  • передача по ссылке.

При передаче по значению, в подпрограмме создается копия полученного фактического параметра. Все действия внутри подпрограммы выполняются над этой копией и при выходе из подпрограммы все изменения теряются. Если переменная
передается по ссылке, то процедуре или функции будет передан адрес этой переменной. Тем самым вызываемая процедура может изменить значение фактического параметра: если будет измен формальный параметр процедуры, то переданный при вызове ей фактический параметр тоже изменит свое значение.

Способ передачи указывается при описании параметров в строке объявления подпрограммы. Имени параметра может предшествовать один из явных описателей способа передачи:

  • ByRef – задает передачу по ссылке;
  • ByVal – задает передачу по значению.

По умолчанию выполняется передача по ссылке.

Листниг 15. Передача параметров в подпрограмму

' sample10 - вызывающая программа (макрос) ' ByValByRefDemo - вызываемая процедура Sub sample10() Dim a As Long, b As Long, c As Long ' фактические параметры a = 10 b = 10 c = 10 ByValByRefDemo a, b, c ' передача фактических параметров Debug.Print "2: " & "a = " & a & "; b = " & b & "; c = " & c End Sub Sub ByValByRefDemo(x As Long, ByVal y As Long, ByRef z As Long) ' выполнение действий над формальными параметрами x = x * 2 y = y * 3 z = z * 4 Debug.Print "1: " & "x = " & x & "; y = " & y & "; z = " & z End Sub 

Здесь объявлены две процедуры: sample10 и ByValByRefDemo. Процедура sample10 вызывает процедуру ByValByRefDemo и передает ей предварительно инициализированные переменные a, b и c. Процедура ByValByRefDemo получает значения переменных a, b и c в виде формальных параметров x, y и z соответственно, выполняет над ними указанные действия, выводит результат и завершается. После возврата из подпрограммы процедура sample10 выводит значения переменных a, b, c в окно отладчика (рис. 4).

Рис. 4. Передача параметров в подпрограмму

Именованные параметры

При вызове подпрограмм в VBA параметры необходимо передавать в определенном порядке. Отсутствующие необязательные параметры отмечаются запятыми. Нарушение этого правила часто приводит к ошибкам – легко пропустить или поменять местами параметры. Чтобы избежать этих проблем, в VBA можно использовать
именованные параметры функций. Для этого в вызове подпрограммы явно указываются имена параметров (как это было задано при объявлении подпрограммы), каждому из которых присваивается требуемое значение с помощью оператора «:=» («двоеточие_равно»). При использовании именованных параметров можно не обозначать отсутствующие параметры и, кроме того, порядок перечисления параметров может быть произвольным.

Следующий пример показывает два обращения к функции MsgBox, которые имеют один и тот же результат:

...
' обычный вызов MsgBox "Здравствуй, мир!", , "Окно приветствия" ...
' вызов, с использованием именованных параметров MsgBox Prompt:= "Здравствуй, мир!", Title:= "Окно приветствия" 

Вызов подпрограмм

Подпрограммы из программ на VBA могут быть вызваны различными способами:

  • Процедуру (Sub)с непустым списком параметров можно вызвать только из другой процедуры или функции так:
    <имяПроцедуры> <списокПараметров> 

    Или так:

    Call <имяПроцедуры> (<списокПараметров>) ’использована инструкция Call. 
  • Процедура с пустым списком параметров рассматривается VBA как командный макрос. Ее также можно вызвать двумя способами:

    • из другой процедуры или функции;
    • с помощью комбинации клавиш быстрого вызова, команд меню или кнопок панелей инструментов.
  • Функцию
    (Function) можно вызывать точно так же, как и процедуру, в виде отдельного оператора. В этом случае возвращаемое функцией значение игнорируется.

Листинг №16. Вызов процедуры

Sub sample11() ' вызывающий макрос Dim usr As String usr = InputBox("Login") Hello usr ' вызов процедуры Helloбез Call Call Hello(usr) ' использование инструкции Call End Sub ' процедура принимает один параметр, формирует строку сообщения, ' выводит сообщение в окно отладчика Sub Hello(usrname As String) Debug.Print "Hello, " & usrname & "!" End Sub 

Если в проекте используется несколько подпрограмм с одинаковыми названиями (это возможно, если они в разных модулях), то при их вызове перед именем подпрограммы надо указывать (через точку) имя модуля, в котором процедура расположена:

<имяМодуля>.<имяПроцедуры> <списокФактическихПараметров> 

Например

MyModule.MySub fArg, sArg ' вызов процедуры из модуля MyModule 

Для вызова общих (Public) подпрограмм из другого проекта дополнительно к именам модуля и подпрограммы указывается имя проекта:

<имяПроекта>.<имяМодуля>.<имяПроцедуры> <списокФактическихПараметров> 

Например

someVal = MyProject.MyModule.MyFunc(fArg, sArg) ' вызов функции из проекта MyProject 

Прерывание подпрограммы

В случае необходимости, выполнение процедуры или функции может быть прервано досрочно. Для этого нужно использовать инструкцию прерывания Exit Sub. В этом случае синтаксис объявления примет следующий вид (на примере объявления процедуры):

Sub <имяПроцедуры> [(<списокпараметров>)] <операторы> Exit Sub <операторы> End Sub 

CC-BY-CA Анатольев А.Г., 29.09.2012

Понравилась статья? Поделить с друзьями:

Это тоже интересно:

  • Процедура выкупа долга у банка пошаговая инструкция
  • Процедура выделения ооо из ооо пошаговая инструкция
  • Процедура внесения изменений в должностную инструкцию работника
  • Процедура банкротства юридического лица пошаговая инструкция последствия
  • Процедура банкротства юридического лица пошаговая инструкция 2023

  • Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии