МИНОБРНАУКИ РОССИИ
Санкт-Петербургский государственный
электротехнический университет
«ЛЭТИ» им. В.И. Ульянова (Ленина)
Кафедра МО ЭВМ
отчет
по лабораторной работе №7
по дисциплине «Организация ЭВМ и систем»
Тема: Использование арифметических операций над целыми числами и процедур в Ассемблере
|
Студент гр. 8383 |
|
Ларин А. |
|
Преподаватель |
|
Ефремов М.А, |
Санкт-Петербург
2019
Цель работы.
Научится обрабатывать целые числа пир помощи арифметических операций на языке ассемблера. Научится представлять числа в строковом виде в выбранной системе счисления. Научится реализовывать функции для обработки чисел используя разные методы передачи аргументов
Задание
Разработать на языке Ассемблер процессора IntelX86 две процедуры:
одна – выполняет прямое преобразование целого числа, заданного в регистре АХ ( или в паре регистров DХ:АX) в строку, представляющую его символьное изображение в заданной системе счисления (с учетом или без учета знака в зависимости от варианта задания);
другая - обратное преобразование строки, представляющей символьное изображение числа в заданной системе счисления в целое число, помещаемое в регистр АХ ( или в пару регистров DХ:АX)
Строка должна храниться в памяти, а также выводиться на экран для индикации.
Отрицательные числа при представлении с учетом знака должны в памяти храниться в дополнительном коде, а на экране изображаться в прямом коде с явным указанием знака или в символьном виде со знаком.
Пример для однобайтовых чисел:
Десятичное число в символьном виде Двоично-десятичное упакованное число
+ 35 00110101
- 35 11001011
Варианты заданий для выполнения преобразования определяются шифром, выбираемым по табл.7 и состоящим из 3-х цифр:
1-я цифра задает длину целого числа:
16 бит, 2- 32 бита;
2-я цифра задает вид представления числа:
1- с учетом знака, 2- без учета знака;
3-я цифра задает систему счисления для символьного изображения числа:
1- двоичная, 2- восьмеричная, 3-десятичная, 4- шестнадцатиричная.
Таблица 7
|
№ бригады |
Шифр Задания |
№ бригады |
Шифр Задания |
|
1 |
2.1.1 |
7 |
1.1.4 |
|
2 |
2.2.1 |
8 |
2.2.4 |
|
3 |
1.2.3 |
9 |
2.1.3 |
|
4 |
1.1.3 |
10 |
2.2.3 |
|
5 |
2.2.2 |
11 |
2.1.4 |
|
6 |
1.1.2 |
12 |
1.1.1 |
Написать простейшую головную программу для иллюстрации корректности выполнения заданных преобразований. При этом вызываемые процедуры могут быть одного из следующих типов:
1 - near, 2 – far (в данном сегменте), 3 – far (в другом сегменте).
Связь по данным между основной программой и подпрограммами может осуществляться следующими способами:
А - только через РОНы;
B - через РОНы и общедоступные переменные;
C - через кадр стека.
Шифры, определяющие типы процедур и способы связи по данным, приведены в табл.8.
Таблица 8
|
№ бригады |
Шифр Задания |
№ бригады |
Шифр Задания |
|
1 |
1А2В |
7 |
2С1А |
|
2 |
1В3С |
8 |
2А3В |
|
3 |
1С2В |
9 |
1А3В |
|
4 |
2А1В |
10 |
1С2А |
|
5 |
2В2А |
11 |
1А3С |
|
6 |
2В3С |
12 |
2С3В |
Выполнение
Вариант 1 (13)
32 бита, с учетом знака, двоичная система
1-я процедура — near, аргументы через РОНы,
2-я процедура — far, один сегмент, РОНы и общие переменные.
Программа содержит две процедуры — dtob для перевода числа в строку в двоичнe. системе счисления и btod для обратного преобразования.
DTOB PROC NEAR; DX:AX - Number; DX - Final binary string
Переводит 32-битное число записанное в регистрах DX:AX в строку в двоичном виде с явным указанием знака в прямом коде и возвращает ее смещение через DX.
В начале проверяется знак числа. Если число отрицательное, то оно превращается в положительное, а первым символом в строку записывает знак '-'. В противном случае записывается '+'. Задается двоичная маска. В SI устанавливается активный регистр — DX. Далее в цикле слева пропускаются все незначимые нулевые разряды, маска сдвигается вправо. При пропуске всего регистра активным регистром задается AX( т. е. В SI помещается значение AX). Когда первый значимый разряд найден происходит обход числа в цикле, каждый разряд извлекается при помощи битовой маски и записывается в строку. Если один регистр пройден процесс повторяется со вторым. В регистр DX записывается смещение результирующей строки, выполняется возврат.
BTOD PROC FAR;TPL - string to process; DX:AX - result number
Переводит строку из сегмента данных с меткой TPL содержащую двоичные число в прямом коде с явным указанием знака в 32-битное целое число, записанное в регистры DX:AX.
В начале по первому символу определяется является ли число отрицательным, для этого в функции есть флаг NEGT DB. Далее считается длинна строки, индекс SI устанавливается в ее конец и начинается ее обход от младших разрядов к старшим. Каждый символ сравнивается с символом '1', '0'. соответствующий разряд устанавливается в соответсвующий регистр при помощи битовой маски. Процедура повторяется для каждым регистром. В результате в регистрах DX:AX хранится результирующее число. Происходит возврат управления в вызвавшую программу.
Написана головная программа для тестирования написанных функций. В ней заданные регистру переводятся в строки первой функцией, затем результирующей функцией строки переводятся обратно в числа, что позволяет оценить правильность работы функций.
Тестирование.
|
DX:AX |
DX = TPL = DTOB(DX:AX) |
DX:AX = BTOD(TPL) |
|
51080821h |
-101110111101111111011111011111 |
51080821h |
|
D1080821h |
+1010001000010000000100000100001 |
D1080821h |
|
00000020h |
+100000 |
00000020h |
|
00000000h |
0 |
00000000h |
|
80000000h |
-100000000000000000000000000000000 |
80000000h |
Выводы.
В результате работы были разобраны некоторые базовые концепции языка ассемблера. Были изучены методы работы с целочисленными данными. Была написана рабочая программа для перевода чисел в строковое представление.
Приложение
LR7.ASM
STACKSG SEGMENT PARA STACK 'Stack'
DW 512 DUP(?)
STACKSG ENDS
DATASG SEGMENT PARA 'Data' ;SEG DATA
KEEP_CS DW 0 ;
TPL DB '-0123456789abcdef0123456789abcdefG$'
DATASG ENDS ;ENDS DATA
CODE SEGMENT ;SEG CODE
ASSUME DS:DataSG, CS:Code, SS:STACKSG
DTOB PROC NEAR; DX:AX - Number; DX - Final binary string
jmp dtob_start
BASE DW 1;Keep track of registers order
dtob_start:
mov BASE,1;
mov DI,0h
mov TPL[DI],'+'
cmp DX,0
mov BX,8000h;bit mask
jge posit
;negative
mov TPL[DI],'-'
add DI,1
;neg
not DX;
not AX;
add AX,1;
jnc no_carry
add DX,1;
no_carry:
jmp scan
reg_skip:;skept register
cmp BASE,1
jne ZERO_OR_OVERFLOW
mov SI,AX
sub BASE,1
mov BX,8000h
jmp kostyl;Like not_yet but no initial bit skip
;positive
posit:
mov TPL[0],'+'
add DI,1
;DX
;WHILE FIRST NON-ZERO DIGIT NOT FOUND
scan:
mov SI,DX
not_yet:
shr BX,1
kostyl:;Like not_yet but no initial bit skip
cmp BX,0
je reg_skip
mov CX,BX;CX <- mask
and CX,SI;CX <- digit of SI
cmp CX,0
je not_yet;LOOP DIGIT SKIP
;CX - first left nonzero digit
digit_loop:;SI - REGISTER TO PROCESS
mov CX,BX; CX <- mask
and CX,SI; CX <- digit of SI
cmp CX,0; if zero digit
je zero_digit
;non-zero digit
mov TPL[DI],'1'
inc DI;
jmp digit_fi
zero_digit:
mov TPL[DI],'0'
inc DI;
jmp digit_fi
digit_fi:;endif
shr BX,1
cmp BX,0
jne digit_loop
;some register processed
cmp BASE,1
jne loop_end;AX register processed, we're done
mov SI,AX;AX not processed
sub BASE,1
mov bx,8000h;
jmp digit_loop
loop_end:
mov TPL[DI],'$'
jmp dtob_end
ZERO_OR_OVERFLOW:
mov SI,0
cmp TPL[SI],'-'
jne EZERO
;OVERFLOW
inc SI
mov TPL[SI],'1'
mov CX,32
OF_LOOP:
mov SI,CX;
add SI,1;
mov TPL[SI],'0'
loop OF_LOOP
mov SI,33
mov TPL[SI],'$'
EZERO:
mov TPL[SI],'0'
inc SI
mov TPL[SI],'$'
dtob_end:
mov DX,offset TPL
ret
DTOB ENDP
BTOD PROC FAR;TPL - string to process; DX:AX - result number
jmp btod_start
NEGT DB 0
REGN DB 1; REg number: 1, then 0
btod_start:
mov AX,0
mov DX,0
mov SI,0;Si-index in str
cmp TPL[SI],'-'
jne positive;
;negative
mov NEGT,1
inc SI;
positive:
;cld
sub ax,ax;
mov SI,0
sub SI,1
len_loop:
add SI,1
cmp TPL[SI],'$'
jne len_loop
;start parsing
mov REGN,1
cmp SI,22h;Max len => -(2^32)
je max_d
cmp SI,1;Min len
je zero_d
mov DI,AX ;DI - active register
mov BX,1;BX - bit mask
parse_loop:
dec SI
cmp SI,0
jle parse_fi
parse_cont:
;parse_if
cmp TPL[SI],'1'
jne parse_zero
;parse_one
or DI,BX;set one by mask BX
jmp parse_fi
parse_zero:
not BX;set zero by inverted mask BX
and DI,BX;
not BX;
parse_fi:
shl BX,1
cmp BX,0
je parse_overflow
;;BX == 0 - overflow
cmp BX,8000h
jb parse_loop
;BX 8000 or more (or overflow)
parse_overflow:
cmp REGN,0;
je parse_pool;;EXIT CONDITION HERE
;regn 1
;check 8000h as well
cmp BX,8000h
je parse_loop
mov AX,DI;Set processed register
mov DI,0;Reset active register
mov REGN,0;Set 0 register number(DX)
mov BX,1;Reset bit mask
jmp parse_loop
parse_pool:
mov DX,DI;Set processed register
jmp btod_check_neg
max_d:;max negative number
mov AX,0
mov DX,8000h;
jmp btod_end
zero_d:;Zero number
mov AX,0;
mov DX,0;
jmp btod_end
btod_check_neg:
cmp NEGT,0
je btod_end
;btod_neg
not DX;
not AX;
add AX,1;
jnc btod_end;no carry
add DX,1;
;no carry
;btod_pos
btod_end:
ret
BTOD ENDP
Main PROC FAR
mov ax, DATASG ;ds setup
mov ds, ax
;51080821_16 1359480865_10 1010001000010000000100000100001_2
;D1080821_16 3506964513_10 11010001000010000000100000100001_2 -101110111101111111011111011111
mov DX,0000h
mov AX,0821h
call DTOB
mov ah,09h;
int 21h;
mov ax,0
mov dx,0
call BTOD;
;---
mov DX,8000h
mov AX,0000h
call DTOB
mov ah,09h;
int 21h;
mov ax,0
mov dx,0
call BTOD;
;---
mov DX,0000h
mov AX,0020h
call DTOB
mov ah,09h;
int 21h;
mov ax,0
mov dx,0
call BTOD;
;---
mov ah,4Ch;