kopilkaurokov.ru - сайт для учителей

Создайте Ваш сайт учителя Курсы ПК и ППК Видеоуроки Олимпиады Вебинары для учителей

Арифметические операции

Нажмите, чтобы узнать подробности

Обработка двоичных данныхНесмотря на то, что мы привыкли к десятичной арифметике (база 10), компьютер работает только с двоичной арифметикой (база 2). Кроме того, ввиду ограничения, накладываемого 16-битовыми регистрами, большие величины требуют специальной обработки.Сложение
Вы уже знаете о суперспособностях современного учителя?
Тратить минимум сил на подготовку и проведение уроков.
Быстро и объективно проверять знания учащихся.
Сделать изучение нового материала максимально понятным.
Избавить себя от подбора заданий и их проверки после уроков.
Наладить дисциплину на своих уроках.
Получить возможность работать творчески.

Просмотр содержимого документа
«Арифметические операции»

Лекция 4. Арифметические операции

Лекция 4. Арифметические операции

Обработка двоичных данных Несмотря на то, что мы привыкли к десятичной арифметике (база 10), компьютер работает только с двоичной арифметикой (база 2). Кроме того, ввиду ограничения, накладываемого 16-битовыми регистрами, большие величины требуют специальной обработки. Сложение и вычитание Команды ADD и SUB выполняют сложение и вычитание байтов или слов, содержащих двоичные данные. Вычитание выполняется в компьютере по методу сложения с двоичным дополнением: для второго операнда устанавливаются обратные значения бит и прибавляется 1, а затем происходит сложение с первым операндом. Во всем, кроме первого шага, операции сложения и вычитания идентичны. Поскольку прямой операции память-память не существует, данная oперация выполняется через регистр. В следующем примере к содержимому слова WORDB прибавляется содержимое слова WORDA, описанных как DW: MOV AX,WORDA ADD AX,WORDB MOV WORDB,AX
  • Обработка двоичных данных
  • Несмотря на то, что мы привыкли к десятичной арифметике (база 10), компьютер работает только с двоичной арифметикой (база 2). Кроме того, ввиду ограничения, накладываемого 16-битовыми регистрами, большие величины требуют специальной обработки.
  • Сложение и вычитание
  • Команды ADD и SUB выполняют сложение и вычитание байтов или слов, содержащих двоичные данные. Вычитание выполняется в компьютере по методу сложения с двоичным дополнением: для второго операнда устанавливаются обратные значения бит и прибавляется 1, а затем происходит сложение с первым операндом. Во всем, кроме первого шага, операции сложения и вычитания идентичны.
  • Поскольку прямой операции память-память не существует, данная oперация выполняется через регистр. В следующем примере к содержимому слова WORDB прибавляется содержимое слова WORDA, описанных как DW:
  • MOV AX,WORDA
  • ADD AX,WORDB
  • MOV WORDB,AX
Переполнения Опасайтесь переполнений в арифметических операциях. Один байт содержит знаковый бит и семь бит данных, то есть, значения от -128 до +127. Результат арифметической операции может легко превзойти емкость однобайтового регистра. Например, результат сложения в регистре AL, превышающий его емкость, автоматически не переходит в регистр AH. Предположим, что регистр AL содержит шест.60, тогда результат команды ADD AL,20H генерирует в AL сумму — шест.80. Но операция также устанавливает флаг переполнения и знаковый флаг в состояние «отрицательно». Причина заключается в том, что шест.80 или двоичное 1000 0000 является отрицательным числом, то есть, в результате, вместо +128, мы получим -128. Так как регистр AL слишком мал для такой операции и следует воспользоваться регистром AX.
  • Переполнения
  • Опасайтесь переполнений в арифметических операциях. Один байт содержит знаковый бит и семь бит данных, то есть, значения от -128 до +127.
  • Результат арифметической операции может легко превзойти емкость однобайтового регистра. Например, результат сложения в регистре AL, превышающий его емкость, автоматически не переходит в регистр AH.
  • Предположим, что регистр AL содержит шест.60, тогда результат команды
  • ADD AL,20H
  • генерирует в AL сумму — шест.80. Но операция также устанавливает флаг переполнения и знаковый флаг в состояние «отрицательно». Причина заключается в том, что шест.80 или двоичное 1000 0000 является отрицательным числом, то есть, в результате, вместо +128, мы получим -128.
  • Так как регистр AL слишком мал для такой операции и следует воспользоваться регистром AX.
В следующем примере команда CBW (Convert Byte to Word — преобразовать байт в слово) преобразует шест.60 в регистре AL в шест.0060 в регистре AX, передавая при этом знаковый бит (0) через регистр AH. Команда ADD генерирует теперь в регистре AX правильный результат: шест.0080, или +128: CBW ;Расширение AL до AX ADD AX,20H ;Прибавить к AX Но полное слово имеет также ограничение: один знаковый бит и 15 бит данных, что соответствует значениям от -32768 до +32767.
  • В следующем примере команда CBW (Convert Byte to Word — преобразовать байт в слово) преобразует шест.60 в регистре AL в шест.0060 в регистре AX, передавая при этом знаковый бит (0) через регистр AH.
  • Команда ADD генерирует теперь в регистре AX правильный результат: шест.0080, или +128:
  • CBW ;Расширение AL до AX
  • ADD AX,20H ;Прибавить к AX
  • Но полное слово имеет также ограничение: один знаковый бит и 15 бит данных, что соответствует значениям от -32768 до +32767.
Беззнаковые и знаковые данные Многие числовые поля не имеют знака, например, номер абонента, aдрес памяти. Некоторые числовые поля предлагаются всегда положительные, например, норма выплаты, день недели, значение числа промежуточного итога. Другие числовые поля являются знаковые, так как их содержимое может быть положительным или отрицательным. Например, долговой баланс покупателя, который может быть отрицательным при переплатах, или алгебраическое число. Для беззнаковых величин все биты являются битами данных и вместо ограничения +32767 регистр может содержать числа до +65535. Для знаковых величин левый байт является знаковым битом. Команды ADD и SUB не делают разницы между знаковыми и беззнаковыми величинами, они просто складывают и вычитают биты. В следующем примере сложения двух двоичных чисел, первое число содержит единичный левый бит.
  • Беззнаковые и знаковые данные
  • Многие числовые поля не имеют знака, например, номер абонента, aдрес памяти. Некоторые числовые поля предлагаются всегда положительные, например, норма выплаты, день недели, значение числа промежуточного итога. Другие числовые поля являются знаковые, так как их содержимое может быть положительным или отрицательным. Например, долговой баланс покупателя, который может быть отрицательным при переплатах, или алгебраическое число.
  • Для беззнаковых величин все биты являются битами данных и вместо ограничения +32767 регистр может содержать числа до +65535. Для знаковых величин левый байт является знаковым битом.
  • Команды ADD и SUB не делают разницы между знаковыми и беззнаковыми величинами, они просто складывают и вычитают биты.
  • В следующем примере сложения двух двоичных чисел, первое число содержит единичный левый бит.
Для беззнакового числа биты представляют положительное число 249, для знакового — отрицательное число -7: Беззнаковое Знаковое  1111 1001 249 -7  + + + +  0000 0010 2 +2  ----------------------------------------------  1111 1011 251 -5 Двоичное представление результата сложения одинаково для беззнакового и знакового числа. Однако, биты представляют +251 для беззнакового числа и -5 для знакового. Таким образом, числовое содержимое поля может интерпретироваться по разному. Состояние «перенос» возникает в том случае, когда имеется пеpенос в знаковый разряд.
  • Для беззнакового числа биты представляют положительное число 249, для знакового — отрицательное число -7:
  • Беззнаковое Знаковое

1111 1001 249 -7

+ + + +

0000 0010 2 +2

----------------------------------------------

1111 1011 251 -5

  • Двоичное представление результата сложения одинаково для беззнакового и знакового числа.
  • Однако, биты представляют +251 для беззнакового числа и -5 для знакового. Таким образом, числовое содержимое поля может интерпретироваться по разному.
  • Состояние «перенос» возникает в том случае, когда имеется пеpенос в знаковый разряд.
Состояние «переполнение» возникает в том случае, когда перенос в знаковый разряд не создает переноса из разрядной сетки или перенос из разрядной сетки происходит без переноса в знаковый разряд. При возникновении переноса при сложении беззнаковых чисел, результат получается неправильный. При возникновении переполнения при сложении знаковых чисел, результат получается неправильный. При операциях сложения и вычитания может одновременно возникнуть и переполнение, и перенос.
  • Состояние «переполнение» возникает в том случае, когда перенос в знаковый разряд не создает переноса из разрядной сетки или перенос из разрядной сетки происходит без переноса в знаковый разряд.
  • При возникновении переноса при сложении беззнаковых чисел, результат получается неправильный.
  • При возникновении переполнения при сложении знаковых чисел, результат получается неправильный.
  • При операциях сложения и вычитания может одновременно возникнуть и переполнение, и перенос.
Умножение Операция умножения для беззнаковых данных выполняется командой MUL, а для знаковых — IMUL (Integer MULtiplication — умножение целых чисел). Ответственность за контроль над форматом обрабатываемых чисел и за выбор подходящей команды умножения лежит на самом программисте. Существуют две основные операции умножения: Байт на байт Множимое находится в регистре AL, а множитель в байте памяти или в однобайтовом регистре. После умножения произведение находится в регистре AX. Операция игнорирует и стиpает любые данные, которые находились в регистре AH.
  • Умножение
  • Операция умножения для беззнаковых данных выполняется командой MUL, а для знаковых — IMUL (Integer MULtiplication — умножение целых чисел).
  • Ответственность за контроль над форматом обрабатываемых чисел и за выбор подходящей команды умножения лежит на самом программисте. Существуют две основные операции умножения:
  • Байт на байт
  • Множимое находится в регистре AL, а множитель в байте памяти или в однобайтовом регистре. После умножения произведение находится в регистре AX. Операция игнорирует и стиpает любые данные, которые находились в регистре AH.
Слово на слово Множимое находится в регистре AX, а множитель — в слове памяти или в регистре. После умножения произведение находится в двойном слове, для которого требуется два регистра: старшая (левая) часть произведения находится в регистре DX, а младшая (правая) часть в регистре AX. Операция игнорирует и стирает любые данные, которые находились в регистре DX. В единственном операнде команд MUL и IMUL указывается множитель. Рассмотрим следующую команду: MUL MULTR В случае, если поле MULTR определено как байт (DB), то операция предполагает умножение содержимого AL на значение байта из поля MULTR. В случае, если поле MULTR определено как слово (DW), то операция предполагает умножение содержимого AX на значение слова из поля MULTR. В случае, если множитель находится в регистре, то длина регистра определяет тип операции, как это показано ниже: MUL CL ;Байт-множитель: множимое в AL, произвед. в AX MUL BX ;Слово-множитель:множимое в AX, произвед. в DX:AX
  • Слово на слово
  • Множимое находится в регистре AX, а множитель — в слове памяти или в регистре. После умножения произведение находится в двойном слове, для которого требуется два регистра: старшая (левая) часть произведения находится в регистре DX, а младшая (правая) часть в регистре AX. Операция игнорирует и стирает любые данные, которые находились в регистре DX.
  • В единственном операнде команд MUL и IMUL указывается множитель. Рассмотрим следующую команду:
  • MUL MULTR
  • В случае, если поле MULTR определено как байт (DB), то операция предполагает умножение содержимого AL на значение байта из поля MULTR. В случае, если поле MULTR определено как слово (DW), то операция предполагает умножение содержимого AX на значение слова из поля MULTR. В случае, если множитель находится в регистре, то длина регистра определяет тип операции, как это показано ниже:
  • MUL CL ;Байт-множитель: множимое в AL, произвед. в AX
  • MUL BX ;Слово-множитель:множимое в AX, произвед. в DX:AX
Беззнаковое умножение: Команда MUL Команда MUL (MULtiplication — умножение) умножает беззнаковые числа. Знаковое умножение: Команда IMUL Команда IMUL (Integer MULtiplication — умножение целых чисел) умножает знаковые числа. Команда MUL рассматривает шест.80 как +128, а команда IMUL — как -128. В результате умножения -128 на +64 получается -8192 или шест.E000. Если множимое и множитель имеет одинаковый знаковый бит, то команды MUL и IMUL генерируют одинаковый результат. Но, если сомножители имеют разные знаковые биты, то команда MUL вырабатывает положительный результат умножения, а команда IMUL — отрицательный.
  • Беззнаковое умножение: Команда MUL
  • Команда MUL (MULtiplication — умножение) умножает беззнаковые числа.
  • Знаковое умножение: Команда IMUL
  • Команда IMUL (Integer MULtiplication — умножение целых чисел) умножает знаковые числа.
  • Команда MUL рассматривает шест.80 как +128, а команда IMUL — как -128. В результате умножения -128 на +64 получается -8192 или шест.E000.
  • Если множимое и множитель имеет одинаковый знаковый бит, то команды MUL и IMUL генерируют одинаковый результат. Но, если сомножители имеют разные знаковые биты, то команда MUL вырабатывает положительный результат умножения, а команда IMUL — отрицательный.
Повышение эффективности умножения При умножении на степень числа 2 (2,4,8 и так далее) более эффективным является сдвиг влево на требуемое число битов. Сдвиг более чем на 1 требует загрузки величины сдвига в регистр CL. В следующих примерах предположим, что множимое находится в регистре AL или AX: Умножение на 2: SHL AL,1 Умножение на 8: MOV CL,3 SHL AX,CL
  • Повышение эффективности умножения
  • При умножении на степень числа 2 (2,4,8 и так далее) более эффективным является сдвиг влево на требуемое число битов. Сдвиг более чем на 1 требует загрузки величины сдвига в регистр CL. В следующих примерах предположим, что множимое находится в регистре AL или AX:
  • Умножение на 2:
  • SHL AL,1
  • Умножение на 8:
  • MOV CL,3
  • SHL AX,CL
Многословное умножение Обычно умножение имеет два типа: «байт на байт» и «слово на слово». Как уже было показано, максимальное знаковое значение в слове ограничено величиной +32767. Умножение больших чисел требует выполнения некоторых дополнительных действий. Рассматриваемый подход предполагает умножение каждого слова отдельно и сложение полученных результатов.
  • Многословное умножение
  • Обычно умножение имеет два типа: «байт на байт» и «слово на слово».
  • Как уже было показано, максимальное знаковое значение в слове ограничено величиной +32767. Умножение больших чисел требует выполнения некоторых дополнительных действий. Рассматриваемый подход предполагает умножение каждого слова отдельно и сложение полученных результатов.
Рассмотрим следующее умножение в десятичном формате:
  • Рассмотрим следующее умножение в десятичном формате:

1365

х

12

------

2730

1365

------

16380

Представим, что десятичная арифметика может умножать только двузначные числа. Тогда можно умножить 13 и 65 на 12 раздельно, cледующим образом:
  • Представим, что десятичная арифметика может умножать только двузначные числа. Тогда можно умножить 13 и 65 на 12 раздельно, cледующим образом:

13 65

х х

12 12

--- ---

26 130

13 65

--- ---

156 780

Следующим шагом сложим полученные произведения, но поскольку число 13 представляло сотни, то первое произведение в действительности будет 15600: 15600 +  780 ------- 16380 Ассемблерная программа использует аналогичную технику за исключением того, что данные имеют размерность слов (четыре цифры) в шестнадцатеричном формате.
  • Следующим шагом сложим полученные произведения, но поскольку число 13 представляло сотни, то первое произведение в действительности будет 15600:

15600

+

780

-------

16380

  • Ассемблерная программа использует аналогичную технику за исключением того, что данные имеют размерность слов (четыре цифры) в шестнадцатеричном формате.
Умножение двойного слова на слово Процедура E10XMUL умножает двойное слово на слово. Множимое, MULTCND, состоит из двух слов, содержащих соответственно шест.3206 и шест.2521. Определение данных в виде двух слов (DW) вместо двойного слова (DD) обусловлено необходимостью правильной адресации для команд MOV, пересылающих слова в регистр AX. Множитель MULTPLR содержит шест.6400. Область для записи произведения, PRODUCT, состоит из трех слов. Первая команда MUL перемножает MULTPLR и правое cлово поля MULTCND; произведение — шест.0E80 E400 записывается в PRODUCT+2 и PRODUCT+4. Вторая команда MUL перемножает MULTPLR и левое слово поля MULTCND, получая в результате шест. 138A 5800.
  • Умножение двойного слова на слово
  • Процедура E10XMUL умножает двойное слово на слово. Множимое, MULTCND, состоит из двух слов, содержащих соответственно шест.3206 и шест.2521. Определение данных в виде двух слов (DW) вместо двойного слова (DD) обусловлено необходимостью правильной адресации для команд MOV, пересылающих слова в регистр AX. Множитель MULTPLR содержит шест.6400.
  • Область для записи произведения, PRODUCT, состоит из трех слов. Первая команда MUL перемножает MULTPLR и правое cлово поля MULTCND; произведение — шест.0E80 E400 записывается в PRODUCT+2 и PRODUCT+4. Вторая команда MUL перемножает MULTPLR и левое слово поля MULTCND, получая в результате шест. 138A 5800.
Далее выполняется сложение двух произведений следующим образом: Произведение 1: 0000 0E80 E400 Произведение 2: 138A 5800 — Результат: 138A 6680 E400 Так как первая команда ADD может выработать перенос, то второе cложение выполняется командой сложения с переносом ADC (ADd with Carry). В силу обратного представления байтов в словах, область PRODUCT в действительности будет содержать значение 8A13 8066 00E4. Программа предполагает, что первое слово в области PRODUCT имеет начальное значение 0000.
  • Далее выполняется сложение двух произведений следующим образом:
  • Произведение 1: 0000 0E80 E400
  • Произведение 2: 138A 5800
  • Результат: 138A 6680 E400
  • Так как первая команда ADD может выработать перенос, то второе cложение выполняется командой сложения с переносом ADC (ADd with Carry).
  • В силу обратного представления байтов в словах, область PRODUCT в действительности будет содержать значение 8A13 8066 00E4. Программа предполагает, что первое слово в области PRODUCT имеет начальное значение 0000.
Умножение двойного слова на двойное слово Умножение двух двойных слов включает следующие четыре операции умножения: Множимое Множитель слово 2 слово 2 слово 2 слово 1 слово 1 слово 2 слово 1 слово 1 Каждое произведение в регистрах DX и AX складывается с соответствующим словом в окончательном результате. Хотя логика умножения двойных слов аналогична умножению двойного слова на слово, имеется одна особенность, после пары команд сложения ADD/ADC используется еще одна команда ADC, которая прибавляет 0 к значению в итоговом поле. Это необходимо потому, что первая команда ADC сама может вызвать перенос, который последующие команды могут стереть. Поэтому вторая команда ADC прибавит 0, если переноса нет, и прибавит 1, если перенос есть. Финальная пара команд ADD/ADC не требует дополнительной команды ADC, так как область итога достаточно велика для генерации окончательного результата и переноса на последнем этапе не будет.
  • Умножение двойного слова на двойное слово
  • Умножение двух двойных слов включает следующие четыре операции умножения:
  • Множимое Множитель
  • слово 2 слово 2
  • слово 2 слово 1
  • слово 1 слово 2
  • слово 1 слово 1
  • Каждое произведение в регистрах DX и AX складывается с соответствующим словом в окончательном результате.
  • Хотя логика умножения двойных слов аналогична умножению двойного слова на слово, имеется одна особенность, после пары команд сложения ADD/ADC используется еще одна команда ADC, которая прибавляет 0 к значению в итоговом поле.
  • Это необходимо потому, что первая команда ADC сама может вызвать перенос, который последующие команды могут стереть. Поэтому вторая команда ADC прибавит 0, если переноса нет, и прибавит 1, если перенос есть.
  • Финальная пара команд ADD/ADC не требует дополнительной команды ADC, так как область итога достаточно велика для генерации окончательного результата и переноса на последнем этапе не будет.
Сдвиг регистровой пары DX:AX Следующая подпрограмма может быть полезна для сдвига содержимого pегистровой пары DX:AX вправо или влево. Можно придумать более эффективный метод, но данный пример представляет общий подход для любого числа циклов (и, соответственно, сдвигов) в регистре CX. Заметьте, что сдвиг единичного бита за разрядную сетку устанавливает флаг переноса. Сдвиг влево на 4 бита MOV CX,04 ;Инициализация на 4 цикла C20: SHL DX,1 ;Сдвинуть DX на 1 бит влево SHL AX,1 ;Сдвинуть AX на 1 бит влево ADC DX,00 ;Прибавить значение переноса LOOP C20 ;Повторить Сдвиг вправо на 4 бита MOV CX,04 ;Инициализация на 4 цикла D20: SHR AX,1 ;Сдвинуть AX на 1 бит вправо SHR DX,1 ;Сдвинуть DX на 1 бит вправо JNC D30 ;В случае, если есть перенос, OR AH,10000000B ; то вставить 1 в AH D30: LOOP D20 ;Повторить
  • Сдвиг регистровой пары DX:AX
  • Следующая подпрограмма может быть полезна для сдвига содержимого pегистровой пары DX:AX вправо или влево. Можно придумать более эффективный метод, но данный пример представляет общий подход для любого числа циклов (и, соответственно, сдвигов) в регистре CX. Заметьте, что сдвиг единичного бита за разрядную сетку устанавливает флаг переноса.
  • Сдвиг влево на 4 бита
  • MOV CX,04 ;Инициализация на 4 цикла C20:
  • SHL DX,1 ;Сдвинуть DX на 1 бит влево
  • SHL AX,1 ;Сдвинуть AX на 1 бит влево
  • ADC DX,00 ;Прибавить значение переноса
  • LOOP C20 ;Повторить Сдвиг вправо на 4 бита
  • MOV CX,04 ;Инициализация на 4 цикла D20:
  • SHR AX,1 ;Сдвинуть AX на 1 бит вправо
  • SHR DX,1 ;Сдвинуть DX на 1 бит вправо
  • JNC D30 ;В случае, если есть перенос,
  • OR AH,10000000B ; то вставить 1 в AH D30:
  • LOOP D20 ;Повторить
Ниже приведен более эффективный способ для сдвига влево, не требующий организации цикла. В этом примере фактор сдвига записывается в регистр CL. Пример написан для сдвига на 4 бита, но может быть адаптирован для других величин сдвигов: MOV CL,04 ;Установить фактор сдвига SHL DX,CL ;Сдвинуть DX влево на 4 бита MOV BL,AH ;Сохранить AH в BL SHL AX,CL ;Сдвинуть AX влево на 4 бита SHL BL,CL ;Сдвинуть BL вправо на 4 бита OR DL,BL ;Записать 4 бита из BL в DL
  • Ниже приведен более эффективный способ для сдвига влево, не требующий организации цикла. В этом примере фактор сдвига записывается в регистр CL.
  • Пример написан для сдвига на 4 бита, но может быть адаптирован для других величин сдвигов:
  • MOV CL,04 ;Установить фактор сдвига
  • SHL DX,CL ;Сдвинуть DX влево на 4 бита
  • MOV BL,AH ;Сохранить AH в BL
  • SHL AX,CL ;Сдвинуть AX влево на 4 бита
  • SHL BL,CL ;Сдвинуть BL вправо на 4 бита
  • OR DL,BL ;Записать 4 бита из BL в DL
Деление Операция деления для беззнаковых данных выполняется командой DIV, a для знаковых — IDIV. Ответственность за подбор подходящей команды лежит на программисте. Существуют две основные операции деления: Деление слова на байт Делимое находится в регистре AX, а делитель — в байте памяти или а однобайтовом регистре. После деления остаток получается в регистре AH, а частное — в AL. Так как однобайтовое частное очень мало (максимально +255 (шест.FF) для беззнакового деления и +127 (шест.7F) для знакового), то данная операция имеет ограниченное использование.
  • Деление
  • Операция деления для беззнаковых данных выполняется командой DIV, a для знаковых — IDIV. Ответственность за подбор подходящей команды лежит на программисте.
  • Существуют две основные операции деления:
  • Деление слова на байт
  • Делимое находится в регистре AX, а делитель — в байте памяти или а однобайтовом регистре. После деления остаток получается в регистре AH, а частное — в AL. Так как однобайтовое частное очень мало (максимально +255 (шест.FF) для беззнакового деления и +127 (шест.7F) для знакового), то данная операция имеет ограниченное использование.
Деление двойного слова на слово Делимое находится в регистровой паре DX:AX, а делитель — в слове памяти или а регистре. После деления остаток получается в регистре DX, а частное в регистре AX. Частное в одном слове допускает максимальное значение +32767 (шест.FFFF) для беззнакового деления и +16383 (шест.7FFF) для знакового. В единственном операнде команд DIV и IDIV указывается делитель. Рассмотрим следующую команду: DIV DIVISOR В случае, если поле DIVISOR определено как байт (DB), то операция предполагает деление слова на байт. В случае, если поле DIVISOR определено как слово (DW), то операция предполагает деление двойного слова на слово. При делении, например, 13 на 3, получается результат 4 1/3. Частное есть 4, а остаток — 1. Заметим, что ручной калькулятор выдает в этом случае результат 4,333.... Значение содержит целую часть (4) и дробную часть (,333). Значение 1/3 и 333... есть дробные части, в то время как 1 есть остаток от деления.
  • Деление двойного слова на слово
  • Делимое находится в регистровой паре DX:AX, а делитель — в слове памяти или а регистре. После деления остаток получается в регистре DX, а частное в регистре AX. Частное в одном слове допускает максимальное значение +32767 (шест.FFFF) для беззнакового деления и +16383 (шест.7FFF) для знакового.
  • В единственном операнде команд DIV и IDIV указывается делитель. Рассмотрим следующую команду:
  • DIV DIVISOR
  • В случае, если поле DIVISOR определено как байт (DB), то операция предполагает деление слова на байт. В случае, если поле DIVISOR определено как слово (DW), то операция предполагает деление двойного слова на слово.
  • При делении, например, 13 на 3, получается результат 4 1/3. Частное есть 4, а остаток — 1. Заметим, что ручной калькулятор выдает в этом случае результат 4,333.... Значение содержит целую часть (4) и дробную часть (,333). Значение 1/3 и 333... есть дробные части, в то время как 1 есть остаток от деления.
Беззнаковое деление: Команда DIV Команда DIV делит беззнаковые числа. Знаковое деление: Команда IDIV Команда IDIV (Integer DIVide) выполняет деление знаковых чисел. Повышение производительности При делении на степень числа 2 (2, 4, и так далее) более эффективным является сдвиг вправо на требуемое число битов. В следующих примерах предположим, что делимое находится в регистре AX: Деление на 2: SHR AX,1 Деление на 8: MOV CL,3 SHR AX,CL
  • Беззнаковое деление: Команда DIV
  • Команда DIV делит беззнаковые числа.
  • Знаковое деление: Команда IDIV
  • Команда IDIV (Integer DIVide) выполняет деление знаковых чисел.
  • Повышение производительности
  • При делении на степень числа 2 (2, 4, и так далее) более эффективным является сдвиг вправо на требуемое число битов. В следующих примерах предположим, что делимое находится в регистре AX:
  • Деление на 2:
  • SHR AX,1
  • Деление на 8:
  • MOV CL,3
  • SHR AX,CL
Переполнения и прерывания Используя команды DIV и особенно IDIV, очень просто вызвать пеpеполнение. Прерывания приводят (по крайней мере в системе, используемой при тестировании этих программ) к непредсказуемым результатам. В операциях деления предполагается, что частное значительно меньше, чем делимое. Деление на ноль всегда вызывает прерывание. Но деление на 1 генерирует частное, которое равно делимому, что может также легко вызвать прерывание. Рекомендуется использовать следующее правило: если делитель — байт, то его значение должно быть меньше, чем левый байт (AH) делителя: если делитель — слово, то его значение должно быть меньше, чем левое слово (DX) делителя. При использовании команды IDIV необходимо учитывать тот факт, что либо делимое, либо делитель могут быть отрицательными, а так как сравниваются абсолютные значения, то необходимо использовать команду NEG для временного перевода отрицательного значения в положительное.
  • Переполнения и прерывания
  • Используя команды DIV и особенно IDIV, очень просто вызвать пеpеполнение. Прерывания приводят (по крайней мере в системе, используемой при тестировании этих программ) к непредсказуемым результатам. В операциях деления предполагается, что частное значительно меньше, чем делимое.
  • Деление на ноль всегда вызывает прерывание. Но деление на 1 генерирует частное, которое равно делимому, что может также легко вызвать прерывание.
  • Рекомендуется использовать следующее правило: если делитель — байт, то его значение должно быть меньше, чем левый байт (AH) делителя: если делитель — слово, то его значение должно быть меньше, чем левое слово (DX) делителя.
  • При использовании команды IDIV необходимо учитывать тот факт, что либо делимое, либо делитель могут быть отрицательными, а так как сравниваются абсолютные значения, то необходимо использовать команду NEG для временного перевода отрицательного значения в положительное.
Деление вычитанием В случае, если частное слишком велико, то деление можно выполнить с помощью циклического вычитания. Метод заключается в том, что делитель вычитается из делимого и в этом же цикле частное увеличивается на 1. Вычитание продолжается, пока делимое остается больше делителя. В cледующем примере, делитель находится в регистре AX, а делимое — в BX, частное вырабатывается в CX: SUB CX,CX ;Очистка частного C20: CMP AX,BX ;В случае, если делимое JB C30 ; то выйти SUB AX,BX ;Вычитание делителя из делимого INC CX ;Инкремент частного JMP C20 ;Повторить цикл С30: RET ;Частное в CX, остаток в AX В конце подпрограммы регистр CX будет содержать частное, а AX — oстаток. Пример умышленно примитивен для демонстрации данной техники деления. В случае, если частное получается в регистровой паре DX:AX, то необходимо сделать два дополнения: 1. В метке C20 сравнивать AX и BX только при нулевом DX. 2. После команды SUB вставить команду SBB DX,00. Примечание:
  • Деление вычитанием
  • В случае, если частное слишком велико, то деление можно выполнить с помощью циклического вычитания.
  • Метод заключается в том, что делитель вычитается из делимого и в этом же цикле частное увеличивается на 1.
  • Вычитание продолжается, пока делимое остается больше делителя. В cледующем примере, делитель находится в регистре AX, а делимое — в BX, частное вырабатывается в CX:
  • SUB CX,CX ;Очистка частного C20:
  • CMP AX,BX ;В случае, если делимое
  • JB C30 ; то выйти
  • SUB AX,BX ;Вычитание делителя из делимого
  • INC CX ;Инкремент частного
  • JMP C20 ;Повторить цикл С30:
  • RET ;Частное в CX, остаток в AX
  • В конце подпрограммы регистр CX будет содержать частное, а AX — oстаток. Пример умышленно примитивен для демонстрации данной техники деления. В случае, если частное получается в регистровой паре DX:AX, то необходимо сделать два дополнения:
  • 1. В метке C20 сравнивать AX и BX только при нулевом DX.
  • 2. После команды SUB вставить команду SBB DX,00.
  • Примечание: очень большое частное и малый делитель могут вызвать тысячи циклов.
Преобразование знака Команда NEG обеспечивает преобразование знака двоичных чисел из положительного в отрицательное и наоборот. Практически команда NEG устанавливает противоположные значения битов и прибавляет 1. Примеры: NEG AX NEG BL NEG BINAMT ;(байт или слово в памяти) Преобразование знака для 35-битового (или большего) числа включает больше шагов. Предположим, что регистровая пара DX:AX содержит 32-битовое двоичное число. Так как команда NEG не может обрабатывать два регистра одновременно, то ее использование приведет к неправильному результату. В следующем примере показано использование команды NOT: NOT DX ;Инвертирование битов NOT AX ;Инвертирование битов ADD AX,1 ;Прибавление 1 к AX ADC DX,0 ;Прибавление переноса к DX Остается одна незначительная проблема: над числами, представленными в двоичном формате, удобно выполнять арифметические операции, если сами числа определены в программе. Данные, вводимые в программу с дискового файла, могут также иметь двоичный формат. Но данные, вводимые с клавиатуры, представлены в ASCII-формате.
  • Преобразование знака
  • Команда NEG обеспечивает преобразование знака двоичных чисел из положительного в отрицательное и наоборот. Практически команда NEG устанавливает противоположные значения битов и прибавляет 1. Примеры:
  • NEG AX
  • NEG BL
  • NEG BINAMT ;(байт или слово в памяти)
  • Преобразование знака для 35-битового (или большего) числа включает больше шагов. Предположим, что регистровая пара DX:AX содержит 32-битовое двоичное число. Так как команда NEG не может обрабатывать два регистра одновременно, то ее использование приведет к неправильному результату. В следующем примере показано использование команды NOT:
  • NOT DX ;Инвертирование битов
  • NOT AX ;Инвертирование битов
  • ADD AX,1 ;Прибавление 1 к AX
  • ADC DX,0 ;Прибавление переноса к DX
  • Остается одна незначительная проблема: над числами, представленными в двоичном формате, удобно выполнять арифметические операции, если сами числа определены в программе. Данные, вводимые в программу с дискового файла, могут также иметь двоичный формат. Но данные, вводимые с клавиатуры, представлены в ASCII-формате.
Хотя ASCII-коды удобны для отображения и печати, они требуют специальных преобразований в двоичный формат для арифметических вычислений. Важно:
  • Хотя ASCII-коды удобны для отображения и печати, они требуют специальных преобразований в двоичный формат для арифметических вычислений.
  • Важно:
  • u Будьте особенно внимательны при использовании однобайтовых pегистров. Знаковые значения здесь могут быть от -128 до +127.
  • u Для многословного сложения используйте команду ADC для учета переносов от предыдущих сложений. В случае, если операция выполняется в цикле, то используя команду CLC, установите флаг переноса в 0.
  • u Используйте команды MUL или DIV для беззнаковых данных и команды IMUL или IDIV для знаковых.
  • u При делении будьте осторожны с переполнениями. В случае, если нулевой делитель возможен, то обеспечьте проверку этой операции. Кроме того, делитель должен быть больше содержимого регистра AH (для байта) или DX (для слова).
  • u Для умножения или деления на степень двойки используйте cдвиг. Сдвиг вправо выполняется командой SHR для беззнаковых полей и командой SAR для знаковых полей. Для сдвига влево используются идентичные команды SHL и SAL.
  • u Будьте внимательны при ассемблировании по умолчанию. Например, если поле FACT определено как байт (DB), то команда MUL FACT полагает множимое в регистре AL, а команда DIV FACT полагает делимое в регистре AX. В случае, если FACT определен как слово (DW), то команда MUL FACT полагает множимое в регистре AX, а команда DIV FACT полагает делимое в регистровой паре DX:AX.
Обработка данных в форматах ASCII и BCD Для получения высокой производительности компьютер выполняет aрифметические операции над числами в двоичном формате. Этот формат не вызывает особых трудностей, если данные определены в самой программе. Во многих случаях новые данные вводятся программой с клавиатуры в виде ASCII символов в деcятичном формате. Аналогично вывод информации на экран осуществляется в кодах ASCII. Например, число 23 в двоичном представлении выглядит как 00010111 или шест.17; в коде ASCII на каждый cимвол требуется один байт и число 25 в ASCII-коде имеет внутpеннее представление шест.3235. При программировании на языках высокого уровня для обозначения порядка числа или положения десятичной запятой (точки) можно положиться на компилятор. Однако, компьютер не распознает десятичную запятую (точку) в арифметических полях. Так как двоичные числа не имеют возможности установки десятичной (или двоичной) запятой (точки), то именно программист должен подразумевать и определить порядок обрабатываемых чисел.
  • Обработка данных в форматах ASCII и BCD
  • Для получения высокой производительности компьютер выполняет aрифметические операции над числами в двоичном формате. Этот формат не вызывает особых трудностей, если данные определены в самой программе. Во многих случаях новые данные вводятся программой с клавиатуры в виде ASCII символов в деcятичном формате. Аналогично вывод информации на экран осуществляется в кодах ASCII. Например, число 23 в двоичном представлении выглядит как 00010111 или шест.17; в коде ASCII на каждый cимвол требуется один байт и число 25 в ASCII-коде имеет внутpеннее представление шест.3235.
  • При программировании на языках высокого уровня для обозначения порядка числа или положения десятичной запятой (точки) можно положиться на компилятор. Однако, компьютер не распознает десятичную запятую (точку) в арифметических полях. Так как двоичные числа не имеют возможности установки десятичной (или двоичной) запятой (точки), то именно программист должен подразумевать и определить порядок обрабатываемых чисел.
  • ASCII-формат
  • Данные, вводимые с клавиатуры, имеют ASCII-формат, например, буквы SAM имеют в памяти шестнадцатеричное представление 53414D, цифры 1234 — шест.31323334. Во многих случаях формат алфавитных данных, например, имя человека или описание статьи, не меняется в программе. Но для выполнения арифметических операций над числовыми значениями, такими как шест.31323334, требуется специальная обработка.
  • С помощью следующих ассемблерных команд можно выполнять арифметические операции непосредственно над числами в ASCII-формате:
  • AAA (ASCII Adjust for Addition — коррекция для сложения ASCII-кода)
  • AAD (ASCII Adjust for Division — коррекция для деления ASCII-кода)
  • AAM (ASCII Adjust for Multiplication — коррекция для умножения ASCII-кода)
  • AAS (ASCII Adjust for Subtraction — коррекция для вычитания ASCII-кода)
  • Эти команды кодируются без операндов и выполняют автоматическую коррекцию в регистре AX. Коррекция необходима, так как ASCII-код представляет так называемый распакованный десятичный формат, в то время, как компьютер выполняет арифметические операции в двоичном формате.
  • Сложение многобайтовых ASCII-чисел требует организации цикла, который выполняет обработку справа налево с учетом переноса.
Вычитание в ASCII-формате Команда AAS (ASCII Adjust for Subtraction — коррекция для вычитания ASCII-кодов) выполняется aналогично команде AAA. Команда AAS проверяет правую шест. цифру (четыре бита) в регистре AL. В случае, если эта цифра лежит между A и F или флаг AF равен 1, то из регистра AL вычитается 6, а из регистра AH вычитается 1, флаги AF и CF устанавливаются в 1. Во всех случаях команда AAS устанавливает в 0 левую шест.цифру в регистpе AL.
  • Вычитание в ASCII-формате
  • Команда AAS (ASCII Adjust for Subtraction — коррекция для вычитания ASCII-кодов) выполняется aналогично команде AAA. Команда AAS проверяет правую шест. цифру (четыре бита) в регистре AL. В случае, если эта цифра лежит между A и F или флаг AF равен 1, то из регистра AL вычитается 6, а из регистра AH вычитается 1, флаги AF и CF устанавливаются в 1. Во всех случаях команда AAS устанавливает в 0 левую шест.цифру в регистpе AL.
  • Умножение в ASCII-формате
  • Команда AAM (ASCII Adjust for Multiplication — коррекция для умножения ASCII-кодов) выполняет корректировку результата умножения ASCII-кодов в регистре AX. Однако, шест. цифры должны быть очищены от троек и полученные данные уже не будут являться действительными ASCII-кодами. Например, число в ASCII-формате 31323334 имеет распакованное десятичное представление 01020304. Кроме этого, надо помнить, что коррекция осуществляется только для одного байта за одно выполнение, поэтому можно умножать только oдно-байтовые поля; для более длинных полей необходима организация цикла.
  • Команда AAM делит содержимое регистра AL на 10 (шест.0A) и записывает частное в регистр AH, а остаток в AL. Предположим, что в регистре AL содержится шест.35, а в регистре CL — шест.39. Следующие команды умножают содержимое регистра AL на содержимое CL и преобразуют результат в ASCII-формат:
  • AX: AND CL,0FH ;Преобразовать CL в 09
  • AND AL,0FH ;Преобразовать AL в 05 0005
  • MUL CL ;Умножить AL на CL 002D
  • AAM ;Преобразовать в распак.дес. 0405
  • OR AX,3030H ;Преобразовать в ASCII-ф-т 3435
  • Команда MUL генерирует 45 (шест.002D) в регистре AX, после чего команда AAM делит это значение на 10, записывая частное 04 в регистр AH и остаток 05 в регистр AL. Команда OR преобpазует затем распакованное десятичное число в ASCII-формат.
Деление в ASCII-формате Команда AAD (ASCII Adjust for Division — коррекция для деления ASCII-кодов) выполняет корректировку ASCII-кода делимого до непосредственного деления. Однако, прежде необходимо очистить левые тройки ASCII-кодов для получения распакованного десятичного формата. Команда AAD может оперировать с двухбайтовыми делимыми в регистре AX. Предположим, что регистр AX содержит делимое 3238 в ASCII-формате и регистр CL содержит делитель 37 также в ASCII-формате. Следующие команды выполняют коррекцию для последующего деления: AX: AND CL,0FH ;Преобразовать CL в распак.дес. AND AX,0F0FH ;Преобразовать AX в распак.дес. 0208 AAD ;Преобразовать в двоичный 001C DIV CL ;Разделить на 7 0004 Команда AAD умножает содержимое AH на 10 (шест.0A), прибавляет pезультат 20 (шест.14) к регистру AL и очищает регистр AH. Значение 001C есть шест. представление десятичного числа 28. Делитель может быть только однобайтовый от 01 до 09.
  • Деление в ASCII-формате
  • Команда AAD (ASCII Adjust for Division — коррекция для деления ASCII-кодов) выполняет корректировку ASCII-кода делимого до непосредственного деления. Однако, прежде необходимо очистить левые тройки ASCII-кодов для получения распакованного десятичного формата. Команда AAD может оперировать с двухбайтовыми делимыми в регистре AX. Предположим, что регистр AX содержит делимое 3238 в ASCII-формате и регистр CL содержит делитель 37 также в ASCII-формате. Следующие команды выполняют коррекцию для последующего деления:
  • AX: AND CL,0FH ;Преобразовать CL в распак.дес.
  • AND AX,0F0FH ;Преобразовать AX в распак.дес. 0208
  • AAD ;Преобразовать в двоичный 001C
  • DIV CL ;Разделить на 7 0004
  • Команда AAD умножает содержимое AH на 10 (шест.0A), прибавляет pезультат 20 (шест.14) к регистру AL и очищает регистр AH. Значение 001C есть шест. представление десятичного числа 28. Делитель может быть только однобайтовый от 01 до 09.
Двоично-десятичный формат (BCD) В предыдущем примере деления в ASCII-формате было получено частное 00090204. В случае, если сжать это значение, сохраняя только правые цифры каждого байта, то получим 0924. Такой формат называется двоично-десятичным (BCD — Binary Coded Decimal) (или упакованным). Он содержит только десятичные цифры от 0 до 9. Длина двоично-десятичного представления в два раза меньше ASCII-представления. Заметим, однако, что десятичное число 0924 имеет основание 10 и, будучи преобразованным в основание 16 (то есть, в шест. представление), даст шест.039C. Можно выполнять сложение и вычитание чисел в двоично-десятичном представлении (BCD-формате). Для этих целей имеются две корректиpующих команды: u DAA (Decimal Adjustment for Addition — десятичная коррекция для сложения) u DAS (Decimal Adjustment for Subtraction — десятичная коррекция для вычитания) Обработка полей также осуществляется по одному байту за одно выполнение.
  • Двоично-десятичный формат (BCD)
  • В предыдущем примере деления в ASCII-формате было получено частное 00090204. В случае, если сжать это значение, сохраняя только правые цифры каждого байта, то получим 0924. Такой формат называется двоично-десятичным (BCD — Binary Coded Decimal) (или упакованным). Он содержит только десятичные цифры от 0 до 9. Длина двоично-десятичного представления в два раза меньше ASCII-представления.
  • Заметим, однако, что десятичное число 0924 имеет основание 10 и, будучи преобразованным в основание 16 (то есть, в шест. представление), даст шест.039C.
  • Можно выполнять сложение и вычитание чисел в двоично-десятичном представлении (BCD-формате).
  • Для этих целей имеются две корректиpующих команды:
  • u DAA (Decimal Adjustment for Addition — десятичная коррекция для сложения)
  • u DAS (Decimal Adjustment for Subtraction — десятичная коррекция для вычитания)
  • Обработка полей также осуществляется по одному байту за одно выполнение.
Преобразование ASCII-формата в двоичный формат Выполнение арифметических операций над числами в ASCII или BCD форматах удобно лишь для коротких полей. В большинстве случаев для арифметических операций используется преобразование в двоичный формат. Практически проще преобразование из ASCII-формата непосредственно в двоичный формат, чем преобразование из ASCII- в BCD-формат и, затем, в двоичный формат: Метод преобразования базируется на том, что ASCII-формат имеет основание 10, а компьютер выполняет арифметические операции только над числами с основанием 2. Процедура преобразования заключается в следующем: 1. Начинают с самого правого байта числа в ASCII-формате и обрабатывают справа налево. 2. Удаляют тройки из левых шест.цифр каждого ASCII-байта. 3. Умножают ASCII-цифры на 1, 10, 100 (шест.1, A, 64) и так далее и складывают результаты.
  • Преобразование ASCII-формата в двоичный формат
  • Выполнение арифметических операций над числами в ASCII или BCD форматах удобно лишь для коротких полей. В большинстве случаев для арифметических операций используется преобразование в двоичный формат.
  • Практически проще преобразование из ASCII-формата непосредственно в двоичный формат, чем преобразование из ASCII- в BCD-формат и, затем, в двоичный формат: Метод преобразования базируется на том, что ASCII-формат имеет основание 10, а компьютер выполняет арифметические операции только над числами с основанием 2. Процедура преобразования заключается в следующем:
  • 1. Начинают с самого правого байта числа в ASCII-формате и обрабатывают справа налево.
  • 2. Удаляют тройки из левых шест.цифр каждого ASCII-байта.
  • 3. Умножают ASCII-цифры на 1, 10, 100 (шест.1, A, 64) и так далее и складывают результаты.
Преобразование двоичного формата в ASCII-формат Для того, чтобы напечатать или отобразить на экране арифметический pезультат, необходимо преобразовать его в ASCII-формат. Данная операция включает в себя процесс обратный предыдущему. Вместо умножения используется деление двоичного числа на 10 (шест.0A) пока результат не будет меньше 10. Остатки, которые лежат в границах от 0 до 9, образуют число в ASCII-формате.
  • Преобразование двоичного формата в ASCII-формат
  • Для того, чтобы напечатать или отобразить на экране арифметический pезультат, необходимо преобразовать его в ASCII-формат. Данная операция включает в себя процесс обратный предыдущему. Вместо умножения используется деление двоичного числа на 10 (шест.0A) пока результат не будет меньше 10. Остатки, которые лежат в границах от 0 до 9, образуют число в ASCII-формате.


Получите в подарок сайт учителя

Предмет: Прочее

Категория: Презентации

Целевая аудитория: Прочее

Скачать
Арифметические операции

Автор: Агафонова Елена Михайловна

Дата: 13.10.2022

Номер свидетельства: 614923

Похожие файлы

object(ArrayObject)#863 (1) {
  ["storage":"ArrayObject":private] => array(6) {
    ["title"] => string(99) "Арифметические операции в двоичной системе счисления"
    ["seo_title"] => string(57) "arifmeticheskie_operatsii_v_dvoichnoi_sisteme_schisleniia"
    ["file_id"] => string(6) "511557"
    ["category_seo"] => string(11) "informatika"
    ["subcategory_seo"] => string(11) "presentacii"
    ["date"] => string(10) "1558408723"
  }
}
object(ArrayObject)#885 (1) {
  ["storage":"ArrayObject":private] => array(6) {
    ["title"] => string(108) "Арифметические операции в позиционных системах счисления "
    ["seo_title"] => string(69) "arifmietichieskiie-opieratsii-v-pozitsionnykh-sistiemakh-schislieniia"
    ["file_id"] => string(6) "103015"
    ["category_seo"] => string(11) "informatika"
    ["subcategory_seo"] => string(5) "uroki"
    ["date"] => string(10) "1402563562"
  }
}
object(ArrayObject)#863 (1) {
  ["storage":"ArrayObject":private] => array(6) {
    ["title"] => string(52) "Арифметические операции в CC "
    ["seo_title"] => string(34) "arifmietichieskiie-opieratsii-v-cc"
    ["file_id"] => string(6) "175980"
    ["category_seo"] => string(11) "informatika"
    ["subcategory_seo"] => string(11) "presentacii"
    ["date"] => string(10) "1424347219"
  }
}
object(ArrayObject)#885 (1) {
  ["storage":"ArrayObject":private] => array(6) {
    ["title"] => string(154) "Учебное домино  по теме «Арифметические операции с двоичными числами» для ИД Smart Board "
    ["seo_title"] => string(99) "uchiebnoie-domino-po-tiemie-arifmietichieskiie-opieratsii-s-dvoichnymi-chislami-dlia-id-smart-board"
    ["file_id"] => string(6) "231341"
    ["category_seo"] => string(11) "informatika"
    ["subcategory_seo"] => string(5) "uroki"
    ["date"] => string(10) "1442477777"
  }
}
object(ArrayObject)#863 (1) {
  ["storage":"ArrayObject":private] => array(6) {
    ["title"] => string(141) "Арифметические операции в двоичной системе счисления (сложение и умножение) "
    ["seo_title"] => string(91) "arifmietichieskiie-opieratsii-v-dvoichnoi-sistiemie-schislieniia-slozhieniie-i-umnozhieniie"
    ["file_id"] => string(6) "124682"
    ["category_seo"] => string(11) "informatika"
    ["subcategory_seo"] => string(5) "uroki"
    ["date"] => string(10) "1414767019"
  }
}


Получите в подарок сайт учителя

Видеоуроки для учителей

Курсы для учителей

ПОЛУЧИТЕ СВИДЕТЕЛЬСТВО МГНОВЕННО

Добавить свою работу

* Свидетельство о публикации выдается БЕСПЛАТНО, СРАЗУ же после добавления Вами Вашей работы на сайт

Удобный поиск материалов для учителей

Проверка свидетельства