M_Asm2009LS
.pdf
|
add |
DL,'0' |
;5) Перетворення остачі в ASCII |
|
|
|
; символ |
|
mov |
outdecimal[SI],DL ; 6) Запис символу в буфер |
|
|
dec |
SI |
;6 )Підготовка для обробки |
|
|
|
; наступного символу |
|
cmp |
AX,0 |
; 7) |
|
jnz |
n1 |
;7) |
|
mov |
DL,sign |
;8) |
|
cmp |
DL,1 |
;8) |
|
jne |
n2 |
|
|
mov |
outdecimal[SI],’–‘ ;8) |
|
n2: |
mov |
AH,9 |
; |
|
lea |
DX,outdecimal |
|
|
int |
21h |
|
|
pop |
BX |
|
|
pop |
CX |
|
|
pop |
DX |
|
|
pop |
SI |
|
|
ret |
|
|
outinteger endp |
|
|
|
Code |
Ends |
|
|
|
End Main |
|
|
|
Розв’язування задач за тематикою заняття |
||
Задача 1. Розробити програму обчислення виразу: |
|||
|
|
f=a*b-c-d%a+c/b+(a*d)/c, |
|
де |
a = 21, |
b = -30, c = 478, d =1347. |
|
Розв’язання. |
|
||
Data |
Segment |
para 'Data' |
|
a db 21 |
|
|
|
b db -30 |
|
|
|
c dw 478 |
|
|
|
d dw 1347 |
|
|
|
f dw 0 |
|
|
|
Data |
Ends |
|
|
Code |
Segment para 'Code' |
|
|
Assume cs:Code,ds:Data |
|
||
Main |
Proc far |
|
|
push DS |
|
|
81
sub AX,AX |
|
|
push AX |
|
|
mov AX,Data |
|
|
mov DS,AX |
|
|
mov ES,AX |
|
|
mov AL,A |
; Завантажити А в регістр AL. |
|
imul b |
;(AL)*B -> (AX) . |
|
sub AX,C |
; AX-C -> AX. |
|
mov word ptr f,AX ; Зберегти AX в F. F=A*B-C. |
||
mov AL,a |
; Завантажити А в регістр AL. F=F-D % A . |
|
cmp AL,0 |
; Чи в AL не 0, щоб не ділити на 0. |
|
je ErorrExit |
; Якщо AL=0, то вхід із програми. |
|
cbw |
; Розширити вміст AL до слова AX. |
|
mov BX,AX |
; AX -> BX. |
|
mov AX,word ptr d; |
AX <- D. |
|
cwd |
; |
Розширити вміст AX до подвійного слова. |
idiv BX |
; (DX,AX)/BX -> результат у AX, остачу в DX. |
|
sub word ptr f,DX |
; F=F-остача від ділення D/A |
|
jo ErorrExit |
; Якщо переповнення, то вхід з програми. |
|
mov AL,b |
; F=F+C/B. |
|
cmp AL,0 |
; Чи в AL не 0, щоб не ділити на 0. |
|
je ErorrExit |
; Якщо AL=0 вихід з програми. |
|
cbw |
; Розширити вміст AL до слова AX. |
|
mov BX,AX |
; AX -> BX. |
|
mov AX,c |
; AX= C |
|
cwd |
; Розширити вміст AX до подвійного слова. |
|
idiv BX |
;(DX,AX)/BX -> результат у AX. |
|
add word ptr f,AX |
|
|
jo ErorrExit |
; Якщо переповнення, то вихід з програми. |
|
mov AL,a |
; F=F+(A*D)/C. |
|
cbw |
; AL <- A, AL -> AX. |
|
imul word ptr d ; (AX)*D -> (DX,AX). |
||
cmp DX,c |
; C ? ( DX). |
|
jg ErorrExit |
; Якщо C<(DX), то переповнення і вхід |
|
|
; із програми. |
|
idiv c |
; (DX,AX)/BX -> результат у AX. |
add word ptr f,AX ; F=F+(A*D)/C. ErorrExit: nop
ret Endp
82
Code Ends
End Main
Задача 2. Задана послідовність цілих чисел{ai }in=1 . Розробити програму обчислення значення виразу:
|
|
|
n |
|
|
|
|
|
|
|
∑ai |
|
|
||
|
p = |
|
i=1 |
|
}. |
||
|
min{a |
|
, i = |
|
|||
|
i |
1, n |
|||||
Розв’язання. |
|
|
|
|
|
||
Data |
Segment |
para 'Data' |
|||||
n |
dw 10 |
|
|
|
|
|
|
a |
db 13,6,5,4,7 ,5,7,4,10,8 |
||||||
min |
db ? |
|
|
|
|
|
|
summa dw ? |
|
|
|
|
|
||
рr |
dw ? |
|
|
|
|
|
|
perror |
db ‘ min {Ai } =0 ‘,’$’ |
||||||
Data |
Ends |
|
|
|
|
|
|
Code |
Segment |
para 'Code' |
|||||
Assume cs:Code,ds:Data |
|||||||
Main |
Proc far |
|
|
|
|
|
|
|
push DS |
|
|
|
|
|
|
|
sub AX,AX |
|
|
|
|
||
|
push AX |
|
|
|
|
|
|
|
mov AX,Data |
|
|
||||
|
mov DS,AX |
|
|
|
|||
|
mov CX,n |
|
|
; Кількість елементів масиву А.;у CX. |
|||
|
jcxz s4 |
|
|
|
; Немає послідовності. |
||
|
lea SI,a |
|
|
|
; Завантаження відносної адреси масиву А. |
||
|
mov AL,[SI] |
; Завантаження першого елемента масиву |
|||||
|
|
|
|
|
|
; А в AL. |
|
|
inc SI |
|
|
|
; Збільшити на 1 вміст регістра SI. |
||
|
xor AH,AH |
|
; Очистити старшу частину регістра AX. |
||||
|
mov DI,AX |
|
|
; Регістр для накопичення суми членів |
|||
|
|
|
|
|
|
; послідовності. |
|
|
mov BX,AX |
|
; У BX мінімальний член послідовності. |
||||
|
dec CX |
|
|
|
; Зменшити на 1 вміст регістра CX. |
||
|
jcxz s5 |
|
|
|
; Перехід, якщо СХ = 0. |
||
s1: |
mov [SI],AL |
; Завантаження елемента масиву А в AL. |
|||||
|
inc SI |
|
|
|
; Збільшити на 1 вміст регістра SI. |
83
|
|
add DI,AX |
; Підсумування елемента масиву А. |
||
|
|
cmp BL,AL |
; Пошук найменшого елемента масиву А. |
||
|
|
jb s3 |
|
|
|
|
|
mov BX,AX |
|
|
|
|
s3: |
loop s1 |
; Цикл. |
|
|
|
|
cmp BX,0 |
; Перевірка, щоб не ділити на 0. |
||
|
|
jne s2 |
; Мінімальних елемент = 0 |
||
|
s4: |
lea DX,perror |
|
|
|
|
|
int 21h |
|
|
|
|
|
ret |
|
|
|
|
s2: |
mov AX,DI |
; Суму елементів записати в регістр AX. |
||
|
|
cwd |
; Розширити вміст AX до (DX,AX). |
||
|
|
div BX |
; Суму елементів масиву на мінімальний |
||
|
|
|
; елемент. |
|
|
|
|
mov рr,AX |
; Результат присвоїти змінній Рr. |
||
|
|
ret |
|
|
|
|
s5: |
mov AX,1 |
; Якщо масив складається з одного елемента |
||
|
|
mov рr,AX |
; то змінній Рr присвоїти 1. |
||
|
|
ret |
|
|
|
|
Endp |
|
|
|
|
|
Code |
Ends |
|
|
|
|
|
End Main |
|
|
|
|
|
Завдання для самостійної роботи |
|||
|
1. Розробити програму обчислення виразу : |
||||
|
Вираз |
|
Змінні |
|
|
|
f=(d*c-1)/(c*a- |
|
|
|
|
1 |
10)+a*b/c+a*c%d+b/d |
|
a=6fh b=14 c=-93 d=46h |
|
|
2 |
f=a-b*(c+(d/a)*b%(c%d-a)/b)+c/d |
a=58h b=45h c=-66h d=-5fh |
|
||
3 |
f=(a-b+(c+(d-a*b/c*d)/a/b)*c)/d |
a=61 b=19 c=15 d=-44h |
|
||
4 |
f=a-(b/(c*d/a%(b+c*d))/a+b)+c%d |
a=45 b=70 c=-75 d=2eh |
|
||
5 |
f=a-b/c+((d/a+(b/c)*d%a+b*c)+d) |
a=35 b=31 c=1bh d=59 |
|
||
6 |
f=a-b*((c+d/a+(b+c)*d+a)%b)-c-d |
a=60 b=71 c=51h d=-19h |
|
||
7 |
f=a-b*(c%(d+(a-b)/c)+d/a)*b*c/d |
a=47 b=41 c=-1fh d=18 |
|
||
8 |
f=a*(b/c-(d*(a)-b)+c/d/a-b+c+d) |
a=70 b=31 c=-6ah d=-2bh |
|
||
9 |
f=a+(b-c%(d-(a/b-c)*d-a)+b*c)+d |
a=11h b=30 c=47 d=51 |
|
||
10 |
f=(a*(b+c))*d/(a+b/c+d*a%b-c)-d |
a=53h b=1fh c=34 d=-39 |
|
||
11 |
f=(a-b-(c+d)*(a+b)/c%d+a)*b/c+d |
a=72 b=79 c=-15 d=89 |
|
||
12 |
f=a-b+(c-d%(a-b)/(c+d)%a-b+c)*d |
a=53h b=3eh c=-72 d=-73 |
|
||
84 |
|
|
|
|
13 |
f=a/(b+c-(d-a/b+(c*d)+a))*b-c%d |
a=28h b=55 c=67h d=42 |
14 |
f=(a+b*(c-(d+a)/b)%c+d*a-b+c)/d |
a=4fh b=35 c=-18h d=-69 |
15 |
f=a/b*c+((d/(a*b+c-d*a+b)-c))-d |
a=91 b=31h c=54h d=-88 |
16 |
f=a-b*c*d/((a-b)-(c/d+a/b)%c-d) |
a=94 b=38 c=59h d=57 |
17 |
f=a-b%c*(d+((a+b))/c+d)+a-b/c/d |
a=5ah b=66 c=-61h d=-6ch |
18 |
f=(a-b-c*((d-a)/b)%c+d)*a+b/c+d |
a=4fh b=36 c=74 d=39h |
19 |
f=a%(b+c%d+(a-(b/c))+d+a*b)/c+d |
a=6eh b=33 c=-98 d=53 |
20 |
f=a-(b/(c*d+(a/b)/c/d)%a+b+c)*d |
a=46h b=64 c=60 d=-32 |
2. Розробити програму обчислення виразу за введеними з клавіатури значеннями:
|
|
|
|
|
|
a + b −1 |
|
|||||
1) |
a + |
|
|
|
|
|
|
− ab |
, a, b – цілі; |
|||
|
|
a |
2 |
+1 |
||||||||
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
2) |
1 |
+ |
|
|
1 |
|
|
( x + y ) , x, y – цілі; |
||||
|
|
|
|
|
|
|
|
|||||
|
x |
2 |
|
|
||||||||
|
xy |
|
|
+1 |
|
|
|
|||||
|
|
|
n +1 |
|
|
1 |
|
3)n 2 + m 2 +1 − ( m +1)(n +1) , n, m - цілі;
|
|
ab+ (a −b)(a + b)−1 |
− 5 , a, b – цілі; |
||||||||||||
4) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
a |
2 |
+ b |
2 |
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
n +1 |
|
5 |
|
|
||||
|
(n |
|
|
|
|
|
|||||||||
5) |
|
|
|
|
|
+ |
|
|
, n, m – цілі; |
||||||
+ m) |
|
|
|
|
|
|
|||||||||
|
|
|
|
|
|
m+1 |
m |
|
|||||||
|
|
xy + |
x + y 2 + 3 |
|
|||||||||||
6) |
|
|
|
|
|
|
|
|
|
, x, y – цілі; |
|||||
|
|
x |
2 |
+ 5 |
|
||||||||||
|
|
|
|
|
|
||||||||||
|
|
|
|
|
|
|
|
|
|
|
|||||
|
|
3 |
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
||||
7) |
|
|
|
|
|
|
+1 ( m − n) , n, m –цілі; |
||||||||
|
+ m |
2 |
+1 |
||||||||||||
|
n |
|
|
|
|
|
|
|
|
ab
|
|
|
|
|
|
+ |
|
|
|
|
|
8) |
|
a 2 +1 |
b 2 +1 , a, b – цілі; |
||||||||
|
|
|
|||||||||
|
2 |
|
|
|
5 x + y 2 |
|
|
||||
|
( xy) |
|
− |
|
|
|
|
|
|||
9) |
|
|
y 2 +1 , x, y – цілі; |
||||||||
|
|
|
|
|
|
|
|||||
10) |
5 + |
|
|
b |
+ (a − b) |
1 |
, a, b – цілі; |
||||
|
|
|
|
|
|||||||
b |
2 |
+1 |
a + b |
||||||||
|
|
|
|
|
|
|
|
||||
11) |
|
xy 2 + x 2 y |
( x − y) , x, y – дійсні; |
||||||||
|
xy +1 |
||||||||||
|
|
|
|
|
|
85
|
|
|
|
|
|
|
|
|
|
|
|
n +1 |
2 |
|
||||
12) |
|
( m − n) |
|
|
|
|
|
|
− n |
+ 5 , n, m – цілі; |
||||||||
|
n + m +1 |
|||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||
|
|
|
y |
2 |
+ |
4 |
|
|
|
|
|
|||||||
|
|
|
|
|
|
|
|
|
|
|||||||||
13) |
|
|
|
|
|
|
|
|
|
|
|
+1 x |
, x, y – цілі; |
|||||
|
2 |
+2 x +5 |
||||||||||||||||
|
x |
|
|
|
|
|
|
|||||||||||
|
|
|
|
|
1 |
|
|
|
|
|
|
− |
1 |
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14) |
|
a 2 |
|
|
|
|
|
|
|
|
|
b 2 + ab +1 , a, b – цілі; |
||||||
|
+ ab +1 |
|
||||||||||||||||
|
|
|
|
5 |
|
|
|
|
|
|
|
|
|
|
2 |
|
||
15) |
|
|
|
|
|
|
|
( m + n ) |
+ n |
, n, m – цілі. |
||||||||
|
n + m |
2 |
||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
86
Лабораторна робота № 7 Обробка символьних рядків за допомогою ланцюжкових команд
Мета: вивчення можливостей обробки символьних рядків за допомогою ланцюжкових команд.
План заняття.
1.Особливості команд обробки ланцюжків.
2.Напрямок обробки ланцюжків. Команди зміни значення прапорця
DF ( CLD, STD ).
3.Префікси повторення ( REP, REPE, REPZ, REPNE, REPZE ).
4.Команди обробки ланцюжків (MOVS, CMPS, SCAS, LODS, STOS).
Теоретичні відомості
1.Особливості команд обробки ланцюжків
На практиці часто необхідно обробляти дані розміром або байт,
або слово, або подвійне слово декілька разів підряд. Для цього можна використати ланцюжкові команди. Ланцюжок – це набір контекстнопов’язаних байтів, слів, або подвійних слів, які знаходяться в сусідніх комірках пам’яті. В системі команд процесора є п’ять команд, призначених для обробки одного елемента ланцюжка (байта, слова, подвійного слова) і автоматичного переходу до наступного елемента. Таким ланцюжковим командам може передувати префікс повторення, який забезпечує повторну дію команди над наступним елементом (тоді обов’язково використовується лічильник повторення ланцюжкової команди – регістр cx або ecx, який потрібно ініціалізувати перед використанням ланцюжкової команди). Завдяки префіксу ланцюжки обробляються значно швидше, ніж при організації програмного циклу. Повторення розраховано на максимальну довжину ланцюжка (64 Кбайтів для реального режиму, 4 Гбайтів для захищеного режиму) і може призупинятися за декількома умовами. Крім того, повторювані ланцюжкові команди можна переривати і відновлювати їх виконання.
Команди можуть визначати ланцюжок-джерело src, ланцюжокприймач dst або обидва операнди одночасно. Вважається, що операнд джерело знаходиться в поточному сегменті даних, який визначається сегментним регістром DS, але можлива заміна сегмента. Ланцюжокприймач повинен знаходитися тільки в поточному додатковому сегменті даних, який визначається сегментним регістром ES, і заміна сегмента не дозволяється. Можна вказувати операнди ланцюжкових команд для кращої наочності програм, однак процесор і транслятор не
87
використовують їх для адресації ланцюжків. Натомість вміст регістра SI|ESI завжди вважається адресою (зміщенням) поточного елемента ланцюжка-джерела, а вміст регістра DI|EDI – зміщенням поточного елемента ланцюжка-приймача. Ці регістри потрібно відповідно ініціалізувати до виконання ланцюжкової команди.
При виконанні ланцюжкової команди вміст регістрів SI|ESI та DI|EDI автоматично модифікується так, щоб адресувати наступні елементи ланцюжків. Прапорець напрямку DF визначає автоінкремент (df = 0) або автодекремент (df = 1) індексних регістрів. Величина інкремента/декремента залежить від розміру елемента ланцюжка і дорівнює 1, 2 або 4, коли елементами ланцюжка є відповідно байт, слово або подвійне слово.
Якщо ланцюжковій команді передує префікс повторення, то після кожного її виконання здійснюється декремент регістралічильника CX|ECX, що не впливає на стан прапорців. Тому регістр CX|ECX потрібно ініціалізувати на відповідну кількість повторень ланцюжкової команди. Якщо вміст регістра-лічильника CX|ECX такий, що дорівнюює нулеві, керування передається наступній за порядком команді.
2.Напрямок обробки ланцюжків. Команди зміни значення прапорця
DF( CLD, STD )
Напрямок обробки ланцюжка від менших адрес елементів до більших або навпаки, від більших адрес до менших, визначається значенням прапорця df. Якщо значення прапорця df = 0, то напрямок обробки ланцюжка від менших адрес елементів до більших. Якщо значення прапорця df = 1, то напрямок обробки ланцюжка від більших адрес елементів до менших. Для того, щоб установити те або інше значення прапорця df, використовуються команди CLD та STD.
Команда встановлення прапорця df, таким, що дорівнює 1.
Загальний вигляд команди
STD.
Алгоритм роботи: Значення df = 1.
Команда встановлення прапорця df, таким, що дорівнює 0.
Загальний вигляд команди
CLD
Алгоритм роботи: Значення df = 0.
Значення прапорця df потрібно встановити до використання ланцюжкової команди.
3. Префікси повторення ( REP, REPE, REPZ, REPNE, REPZE )
88
Префікси повторення використовуються для циклічного виконання ланцюжкових команд. Наприклад, наявність цього префікса дозволяє передати ланцюжок довільної довжини (довжина якого не перевищує максимальної) при відповідній ініціалізації регістрів DS:[SI|ESI], ES:[DI|EDI] та CX|ECX.
Префікс повторення має п’ять мнемокодів: REP, REPE, REPZ, REPNE і REPNZ. Вони визначають тільки два коди префікса 0f2h та 0f3h і введені для кращої передачі змісту команди.
Префікс REP використовується з командами MOVS і STOS, які не впливають на прапорці. Цей префікс означає: “повторювати, поки не досягнуто кінця ланцюжка”, тобто доти, поки вміст регістра CX|ECX не досягне 0. Префікси REPE|REPZ діють однаково і застосовуються з командами CMPS і SCAS та враховують стан прапорця zf, який модифікується цими командами: операція повторюється, якщо вміст CX|ECX не дорівнює нулеві і zf=1. Префікси REPNE|REPNZ діють однаково, але для повторення операції потрібен ненульовий вміст CX|ECX та zf=0.
5. Команди обробки ланцюжків (MOVS, CMPS, SCAS, LODS, STOS)
Команда передачі ланцюжка MOVS має такий загальний
вигляд:
MOVS dst,src; dst=(src), SI|ESI=(SI|ESI)+h, DI|EDI=(DI|EDI)+h.
Алгоритм роботи: команда передає або байт, або слово, або подвійне слово з ланцюжка src, який адресується регістрами DS:[SI|ESI, в ланцюжок dst, який адресується регістрами ES:[DI|EDI], і коректує вміст регістрів SI|ESI і DI|EDI на величину h, значення якої – число зі знаком, яке залежить від значення прапорця df і може дорівнювати ±1 ,
±2 , ±4 . Якщо використовується префікс повторення, то команда MOVS здійснює блокову передачу пам’ять – пам’ять. В програмі перед командою з префіксом повторення потрібно ініціалізувати регістр-лічильник CX|ECX. Транслятори допускають використання мнемонік з явною специфікацією розміру елементів ланцюжків: MOVSB (byte), MOVSW (word), MOVSD (double word).
Присутність операндів у команді дозволяє застосовувати префікси заміни сегмента, якщо цей префікс допустимий, а також використовується транслятором для визначення типу елементів ланцюжків.
Команда порівняння ланцюжків CMPS має такий загальний
вигляд:
CMPS dst,src; dst=(src)–(dst), SI|ESI=(SI|ESI)+h, DI|EDI=(DI|EDI)+h.
89
Алгоритм роботи: команда віднімає вміст байта, слова або подвійного слова з ланцюжка dst від відповідного елемента ланцюжка src і коректує вміст регістрів SI|ESI і DI|EDI на величину h, значення якої – число зі знаком, яке залежить від значення прапорця DF і може дорівнювати ±1 , ±2 , ±4 . В залежності від результату віднімання модифікуються прапорці, операнди src і dst не змінюються. .Якщо перед командою використовується префікс повторення REPE|REPZ, то команда інтерпретується як “повторювати, поки не досягнуто кінця ланцюжка і поки елементи однакові”. При наявності префікса повторення REPNE|REPNZ операція інтерпретується так: “порівнювати, поки не досягнуто кінця ланцюжка і поки елементи ланцюжка різні”. В програмі перед командою з префіксом повторення потрібно ініціалізувати регістр-лічильник CX|ECX.
Для явної вказівки довжини елементів ланцюжків можливі мнемокоди CMPSB, CMPSW, CMPSD.
Наявність операндів у команді дозволяє застосовувати префікси заміни сегмента, якщо цей префікс допустимий, а також використовується транслятором для визначення типу елементів ланцюжків.
Команда сканування ланцюжка SCAS має такий загальний
вигляд:
SCAS dst; (acc)– (dst), DI|EDI=(DI|EDI)+h.
Алгоритм роботи: команда віднімає елемент ланцюжка dst (байт, слово, подвійне слово) із вмісту акумулятора (відповідно AL, AX, EAX) і регістр-вказівник DI|EDI просувається на наступний елемент ланцюжка. За одержаною різницею модифікуються прапорці, причому операнди – акумулятор acc і приймач dst без зміни. З префіксом повторення REPE|REPZ команду можна використовувати для пошуку елемента ланцюжка зі значенням, відмінним від заданого в акумуляторі. Префікс REPNE|REPNZ дозволяє знайти елемент ланцюжка, значення якого збігається зі значенням в акумуляторі. В програмі перед командою з префіксом повторення потрібно ініціалізувати регістр-лічильник CX|ECX.
Мнемоніки SCASB, SCASW, SCASD використовуються, щоб явно вказати довжину (тип) елементів ланцюжка.
Команда завантаження ланцюжка LODS має такий загальний
вигляд:
LODS src; acc=(src), SI|ESI=(SI|ESI)+h.
Алгоритм роботи: команда завантажує елемент ланцюжка src (байт, слово, подвійне слово) в акумулятор і вміст регістра SI|ESI змінює на
90