Сдвиг и округление. Лабораторная работа № 15 «Сдвиг и округление»




Сдвиг и округление

 

 

Методические рекомендации по выполнению лабораторной работы по МДК.01.01 Системное программирование для студентов 2 курса

 

 

Составитель: Токаева Я.Ю.,

преподаватель колледжа

 

 

Сдвиг и округление. Методические рекомендации по выполнению лабораторной работы по МДК.01.01 Системное программирование для студентов 2 курса /Составитель: Токаева Я.Ю./ ‒ Череповец: Череповецкий металлургический колледж имени академика И.П. Бардина, 2019. – 23 с.

 

Рецензенты:

 

 

Данная методическая разработка рассмотрена на заседании цикловой комиссии «Информационные технологии и вычислительная техника» и рекомендована к применению.

Председатель: /Молоткова Л.Н./

__________________2019 г.

Протокол №___

 


 

Содержание

 

 

  Цель работы  
  Средства обучение  
  Теоретическое обоснование  
  Задание  
  Ход работы  
  Рекомендации по оформлению отчета  
  Контрольные вопросы  
  Литература  
  Приложение А – Варианты заданий  

 

 


 

Лабораторная работа № 15 «Сдвиг и округление»

 

1 Цель работы: закрепление на практике принципов обработки двоичных данных в языке Ассемблер на примере операций сдвига и округления.

 

2 Средства обучения:

· ПЭВМ;

· методические рекомендации.

 

Теоретическое обоснование

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

<мнемокод> <операнд>, <непосредственный операнд>

<мнемокод> <операнд>, CL

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

Команды сдвига меняют флаги CF, OF, PF, SF и ZF.

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

При логическом сдвиге «освобождающиеся» биты заполняются нулями. Последний ушедший бит сохраняется во флаге CF.

SHL операнд, количество_сдвигов

SHR операнд, количество_сдвигов

SHL и SHR сдвигают биты операнда (регистр/память) влево или вправо соответственно на один разряд.

Указанное выше действие повторяется количество раз, равное значению второго операнда.

Пример:

; al = 01011011 (двоичное)

shr al, 3

Это означает: сдвиг всех битов регистра al на 3 разряда вправо. Так что al станет 00001011. Биты слева заполняются нулями, а биты справа выдвигаются. Последний выдвинутый бит, становится значением флага переноса cf.

Бит переноса это бит флагового регистра процессора. Этот регистр не такой как eax или ecx, к которому вы можете непосредственно обращаться (хотя есть опкоды, которые это делают), его содержание, зависит от результатов многих команд. Флаг переноса это бит во флаговом регистре и что он может быть установлен (т.е. равен 1) или сброшен (равен 0).

Команда shl такая же, как и shr, но сдвигает влево.

; bl = 11100101 (двоичное)

shl bl, 2

После выполнения команды регистр bl будет равен 10010100 (двоичное). Два последних бита заполнились нулями, флаг переноса установлен, потому, что последний выдвинутый слева бит был равен 1.

Арифметический сдвиг влево эквивалентен логическому сдвигу влево (это одна и та же команда) – «освобождающие» биты заполняются нулями. При арифметическом сдвиге вправо «освобождающиеся» биты заполняются знаковым битом. Последний ушедший бит сохраняется во флаге CF.

SAL операнд, количество_сдвигов

SAR операнд, количество_сдвигов

Команда SAL такая же, как SHL, а вот SAR не совсем такая, как SHR. Команда SAR также, как и SHR сдвигает все биты операнда вправо на один разряд, при этом выдвигаемый справа бит становится значением флага переноса CF. Обратите внимание: одновременно слева в операнд вдвигается не нулевой бит, как в SHR, а значение старшего бита операнда.

Пример:

al = 10100110

sar al, 3

al = 11110100

sar al, 2

al = 11111101

bl = 00100110

sar bl, 3

bl = 00000010

При циклическом сдвиге «освобождающиеся» биты заполняются ушедшими битами. Последний ушедший бит сохраняется во флаге CF.

rol операнд, количество_сдвигов; циклический сдвиг операнда влево

ror операнд, количество_сдвигов; циклический сдвиг операнда вправо

rcl операнд, количество_сдвигов; циклический сдвиг операнда влево через флаг переноса

rcr операнд, количество_сдвигов; циклический сдвиг операнда вправо через флаг переноса

Циклический сдвиг напоминает смещение, выдвигаемые биты, снова вдвигаются с другой стороны

Пример команды ror (циклический сдвиг вправо) представлен на рисунке 1.

 

Рисунок 1 – Команда ROR

 

Как видно из рисунка 1, биты вращаются, то есть каждый бит, который выталкивается снова вставляется с другой стороны. Флаг переноса CF содержит значение последнего выдвинутого бита.

RCL и RCR сдвигают все биты операнда влево (для RCL) или вправо (для RCR) на один разряд, при этом старший (для RCL) или младший (для RCR) бит становится значением флага переноса CF; одновременно старое значение флага переноса CF вдвигается в операнд справа (для RCL) или слева (для RCR) и становится значением младшего (для RCL) или старшего (для RCR) бита операнда. Указанные действия повторяются количество раз, равное значению второго операнда.

ROL и ROR сдвигают все биты операнда влево (для ROL) или вправо (для ROR) на один разряд, при этом старший (для ROL) или младший(для ROR) бит операнда вдвигается в операнд справа (для ROL) или слева (для ROR) и становится значением младшего (для ROL) или старшего (для ROR) бита операнда; одновременно выдвигаемый бит становится значением флага переноса CF. Указанные действия повторяются количество раз, равное значению второго операнда.

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

SHLD <операнд1>, <операнд2>, <количество>; Расширенный сдвиг влево

SHRD <операнд1>, <операнд2>, <количество>; Расширенный сдвиг вправо

Команда SHLD сдвигает влево биты операнда1 на указанное количество позиций. Младшие («освободившиеся») биты операнда1 заполняются старшими битами операнда2. Сам операнд2 не меняется.

Команда SHRD сдвигает вправо биты операнда1 на указанное количество позиций. Старшие («освободившиеся») биты операнда1 заполняются младшими битами операнда2. Сам операнд2 не меняется.

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

Команды расширенного сдвига обычно используют для создания упакованных данных.

Рассмотрим процесс округления числа до двух десятичных знаков после запятой. Если число равно 12,345, то необходимо прибавить 5 к отбрасываемому разряду и сдвинуть число вправо на один десятичный разряд:

Число: 12,345

Плюс 5: +5

------

Округленное число: 12,350 = 12,35

Если округляемое число равно 12,3455, то необходимо прибавить 50 и сдвинуть на два десятичных разряда. Для 12,34555 необходимо прибавить 500 и сдвинуть на три десятичных разряда:

12,3455+50 - - - 12,3505 = 12,35

12,34555+500 - - -12,35055 = 12,35

К числу, имеющему шесть знаков после запятой, необходимо прибавить 5000 и сдвинуть на четыре десятичных разряда и т.д. Поскольку данные представляются в компьютере в двоичном виде, то 12345 выглядит как шест.3039. Прибавляя 5 к 3039, получим 303E, что соответствует числу 12350 в десятичном представлении. Пока все хорошо. Но вот сдвиг на одну двоичную цифру дает в результате шест.181F, или 1675 – т.е. сдвиг на одну двоичную цифру просто делит число пополам. Но нам необходим такой сдвиг, который эквивалентен сдвигу вправо на одну десятичную цифру. Такой сдвиг можно осуществить делением на 10 (шест.A):

Шест.303E: Шест.A = 4D3 или дес.1235

Преобразование шест.4D3 в ASCII-формат дает число 1235. Теперь остается лишь вставить запятую в правильную позицию числа 12,35, и можно выдать на экран округленное и сдвинутое значение.

Таким образом, можно округлять и сдвигать любые двоичные числа. Для трех знаков после запятой необходимо прибавить 5 и разделить на 10, для четырех знаков после запятой: прибавить 50 и разделить на 100. Возможно, вы заметили модель: фактор округления (5, 50, 500 и т.д.) всегда составляет половину фактора сдвига (10, 100, 1000 и т.д.).

Конечно, десятичная запятая в двоичном числе только подразумевается.

Пример: преобразование времени и расценки работ для расчета зарплаты.

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

TITLE SCREMP (EXE) Ввод времени и расценки,

;вывод величины оплаты

; ----------------------------------------------------

STACKSG SEGMENT PARA STACK 'Stack'

DW 32 DUP(?)

STACKSG ENDS

; ----------------------------------------------------

DATASG SEGMENT PARA 'Data'

HRSPAR LABLE BYTE;Список параметров для

; ввода времени:

MAXHLEN DB 6;---------------------

ACTHLEN DB?

HRSFLD DB 6 DUP(?)

RATEPAR LABLE BYTE;Список параметров для

; ввода расценки:

MAXRLEN DB 6;---------------------

ACTRLEN DB?

RATEFLN DB 6 DUP(?)

MESSG1 DB 'Hours worked? ','$'

MESSG2 DB 'Rate of pay? ','$'

MESSG3 DB 'Wage = '

ASCWAGE DB 10 DUP(30H), 13, 10, '$'

ADJUST DW?

ASCHRS DB 0

ASCRATE DB 0

BINVAL DW 00

BINHRS DW 00

BINRATE DW 00

COL DB 00

DECIND DB 00

MULT10 DW 01

NODEC DW 00

ROW DB 00

SHIFT DW?

TENWD DW 10

DATASG ENDS

; ----------------------------------------------------

CODESG SEGMENT PARA 'Code'

BEGIN PROC FAR

ASSUME CS:CODESG,DS:DATASG,SS:STACKSG,ES:DATASG

PUSH DS

SUB AX,AX

PUSH AX

MOV AX,DATASG

MOV DS,AX

MOV ES,AX

MOV AX,0600H

CALL Q10SCR;Очистить экран

CALL Q20CURS;Установить курсор

A20LOOP:

CALL B10INPT;Ввести время и расценку

CMP ACTHLEN,00;Завершить работу?

JE A30

CALL D10HOUR;Получить двоичное время

CALL E10RATE;Получить двоичную расценку

CALL F10MULT;Расчитать оплату

CALL G10WAGE;Преобразовать в ASCII

CALL K10DISP;Выдать результат на экран

JMP A20LOOP

A30:

MOV AX,0600H

CALL Q10SCR;Очистить экран

RET;Выйти из программы

BEGIN ENDP

; Ввод времени и расценки

; ----------------------------------------------------

B10INPT PROC

LEA DX,MESSG1;Запрос для ввода времени

MOV AH,09

INT 21H

LEA DX,HRSPAR;Ввести время

MOV AH,0AH

INT 21H

CMP ACTHLEN,00;Пустой ввод?

JNE B20

RET; да - вернуться A20LOOP

B20:

MOV COL,25;Установить столбец

CALL Q20CURS

LEA DX,MESSG2;Запрос для ввода расценки

MOV AH,09

INT 21H

LEA DX,RATEPAR;Ввести расценку

MOV AH,0AH

INT 21H

RET

B10INPT ENDP

; Обработка времени:

; -----------------

D10HOUR PROC

MOV NODEC,00

MOV CL,ACTHLEN

SUB CH,CH

LEA SI,HRSFLD-1;Установить правую позицию

ADD SI,CX; времени

CALL M10ASBI;Преобразовать в двоичное

MOV AX,BINVAL

MOV BINHRS,AX

RET

D10HOUR ENDP

; Обработка расценки:

; ------------------

E10RATE PROC

MOV CL,ACTRLEN

SUB CH,CH

LEA SI,RATEFLD-1;Установить правую позицию

ADD SI.CX; расценки

CALL M10ASBI;Преобразовать в двоичное

MOV AX,BINVAL

MOV BINRATE,AX

RET

E10RATE ENDP

; Умножение, округление и сдвиг:

; -----------------------------

F10MULT PROC

MOV CX,05

LEA DI,ASCWAGE;Установить формат оплаты

MOV AX,3030H; в код ASCII (30)

CLD

REP STOSW

MOV SHIFT,10

MOV ADJUST,00

MOV CX,NODEC

CMP CL,06;Если более 6 десятичных

JA F40; знаков, то ошибка

DEC CX

DEC CX

JLE F30;Обойти, если менее 3 знаков

MOV NODEC,02

MOV AX,01

F20:

MUL TENWD;Вычислить фактор сдвига

LOOP F20

MOV SHIFT,AX

SHR AX,1;Округлить результат

MOV ADJUST,AX

F30:

MOV AX,BINHRS

MUL BINRATE;Вычислить оплату

ADD AX,ADJUST;Округлить оплату

ADC DX,00

CMP DX,SHIFT;Результат слишком велик

JB F50; для команды DIV?

F40:

SUB AX,AX

JMP F70

F50:

CMP ADJUST,00;Сдвиг нее требуется?

JZ F80

DIV SHIFT;Сдвинуть оплату

F70: SUB DX,DX;Стереть остаток

F80: RET

F10MULT ENDP

; Преобразование в ASCII формат:

; -----------------------------

G10WAGE PROC

LEA SI,ASCWAGE+7;Установить дес. точку

MOV BYTE PTR[SI],'.'

ADD SI,NODEC;Установить правую позицию

G30:

CMP BYTE PTR[SI],'.'

JNE G35;Обойти, если дес.поз.

DEC SI

G35:

CMP DX,00;Если dx:ax < 10,

JNZ G40

CMP AX,0010; то операция завершена

JB G50

G40:

DIV TENWD;Остаток - ASCII-цифра

OR DL,30H

MOV [SI],DL;Записать ASCII символ

DEC SI

SUB DX,DX;Стереть остаток

JMP G30

G50:

OR AL,30H;Записать последний ASCII

MOV [SI],AL; символ

RET

G10WAGE ENDP

; Вывод величины оплаты:

; ---------------------

K10DISP PROC

MOV COL,50;Установить столбец

CALL Q20CURS

MOV CX,09

LEA SI,ASCWAGE

K20:;Стереть лидирующие нули

CMP BYTE PTR[SI],30H

JNE K30; пробелами

MOV BYTE PTR[SI],20H

INC SI

LOOP K20

K30:

LEA DX,MESSG3;Вывод на экран

MOV AH,09

INT 21H

CMP ROW,20;Последняя строка экрана?

JAE K80

INC ROW; нет - увеличить строку

JMP K90

K80:

MOV AX,0601H; да --

CALL Q10SCR; прокрутить и

MOV COL,00; установить курсор

CALL Q20CURS

K90: RET

K10DISP ENDP

; Преобразование ASCII-чисел

; в двоичное представление:

; --------------------------

M10ASBI PROC

MOV MULT10,0001

MOV BINVAL,00

MOV DECIND,00

SUB BX,BX

M20:

MOV AL,[SI];ASCII-символ

CMP AL,'.';Обойти, если дес.точка

JNE M40

MOV DECIND,01

JMP M90

M40:

AND AX,000FH

MUL MULT10;Умножить на фактор

ADD BINVAL,AX;Сложить с дв.значением

MOV AX,MULT10;Вычислить следующий

MUL TENVD; фактор x 10

MOV MULT10,AX

CMP DECIND,00;Десятичная точка?

JNZ M90

INC BX; да - обойти точку

M90:

DEC SI

LOOP M20

;Конец цикла

CMP DECIND,00;Была дес.точка?

JZ M100; да --

ADD NODEC,BX; сложить с итогом

M100: RET

M10ASBI ENDP

; Прокрутка экрана:

; ----------------

Q10SCR PROC NEAR;AX установлен при вызове

MOV BH,30;Цвет (07 для ч/б)

SUB CX,CX

MOV DX,184FH

INT 10H

RET

Q10SCR ENDP

; Установка курсора:

; -----------------

Q20CURS PROC NEAR

MOV AH,02

SUB BH,BH

MOV DH,ROW

MOV DL,COL

INT 10H

RET

Q20CURS ENDP

CODESG ENDS

END BEGIN

Программа содержит следующие процедуры:

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

· D10HOUR. Выполняет преобразование значения времени из ASCII в двоичный формат.

· E10RATE. Выполняет преобразование значения расценки из ASCII в двоичный формат.

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

· G10WAGE. Вставляет десятичную запятую, определяет правую позицию для начала записи ASCII символов и преобразует двоичное значение зарплаты в ASCII-формат.

· K10DISP. Заменяет лидирующие нули на пробелы и выводит результат на экран.

· M10ASBI. Преобразует ASCII в двоичный формат (общая процедура для времени и расценки) и определяет число цифр после запятой в введенном значении.

Первое ограничение в данной программе, состоит в том, что допускает не более шести десятичных знаков после запятой. Другое ограничение – размер самой зарплаты и тот факт, что сдвиг включает деление на число, кратное 10, а преобразование в ASCII-формат включает деление на 10. Если значение времени или расценки содержит больше шести десятичных знаков или зарплата превышает величину около 655350, то программа выдает нулевой результат. На практике программа может предусмотреть в данном случае вывод предупреждающего сообщения или иметь подпрограммы для исключения таких ограничений.

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

Полезной командой для проверки корректности вводимых символов является XLAT.

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

Некоторые применения программ допускают наличие отрицательных величин. Знак минус может устанавливаться после числа, например, 12,34-, или перед числом -12,34. Программа может проверять наличие минуса при преобразовании в двоичный формат. Можно оставить двоичное число положительным, но установить соответствующий индикатор исходной отрицательной величины. После завершения арифметических операций знак минус при необходимости может быть вставлен в ASCII поле.

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

Будьте внимательны при использовании команд IMUL и IDIV для обработки знаковых данных. Для округления отрицательных чисел следует не прибавлять, а вычитать фактор 5.

 

Задание

Привести решения задач, представленных в приложении А, согласно своему варианту.

 

5 Ход работы:

· изучить теоретическое обоснование работы;

· выполнить задание согласно варианту (приложение А);

· ответить на контрольные вопросы;

· сделать выводы по проделанной работе;

· оформить отчет.

 



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2021-12-14 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: