Практикум_СП
.pdf;Приклади безумовних переходів.
;Модулі mod1 і mod2 асемблюються окремо.
NAMEmod1 Dseg SEGMENT
Addr_JN DW Go_Nxt |
|
|
;адреса переходу Offset Addr.JF DD Start_0 адреса |
|
;переходу Seg Offset |
|
|
|
|
Tabl_JN DW Fadd, Fsub, Fmul, Fdiv |
;таб.адр. переходу Offset |
|||
Tabl_JF DD Dadd.Dsub.Dmul.Ddiv ;те ж, але у вигляді Seg:Qffset |
||||
SwitchDW ? |
|
|
;перемикач: 0, 1, 2 або 3 |
|
Dseg |
ENDS |
|
|
|
Cseg1 SEGMENT 'CODE' |
|
|
|
|
|
EXTRN Begin:FAR |
|
|
|
Start |
PROC FAR |
|
|
|
|
PUSH DS |
|
;підготуватися |
|
|
SUB AX, AX |
|
;до повернення |
|
|
PUSH AX |
|
;у DOS |
|
; Приклади внутрішньосегментних переходів |
||||
Start_0: |
|
|
|
|
JMP SHORT Cont |
;короткий перехід в сегменті |
|||
Go_Nxt: |
|
|
|
|
MOV SI, Switch |
|
|
|
|
|
SHL SI,1 |
|
|
;підготувати покажчик в таблиці |
|
JMP Tabl_JN[Sl] |
|
|
;непрямий перехід в сегменті |
|
... |
|
|
|
|
JMP Addr_JN |
|
|
;непрямий перехід на Go_Nxt |
|
... |
|
|
|
|
JMP Tabl_JN + 4 |
|
|
;непрямий перехід на Fmul |
|
... |
|
|
|
|
MOV BX,Tabl_JN[Sl] |
|
;ВК = адреса з таблиці |
|
|
JMP ВХ |
|
|
;непрямий перехід за адресою у ВХ |
|
... |
|
|
|
|
LEA BX,Tabl_JN |
|
|
;ВК = база таблиці |
|
JMP NEAR PTR [ВХ] |
|
;непрямий перехід на Fadd |
|
|
... |
|
|
|
|
JMP NEAR PTR [BX][SI] |
|
;непрямий перехід за адресою з таблиці Tabl_JN, |
|
;який визначається перемикачем в S1 |
|
|||
|
JMP Go_Nxt |
|
|
;прямий перехід в сегменті типу NEAR |
; Приклади міжсегментних переходів |
|
|||
|
JMP Begin |
|
|
;прямий міжсегментний по зовнішній мітці |
|
... |
|
|
|
|
JMP DSUB |
|
|
;прямий міжсегментний по мітці типу F |
|
... |
|
|
|
|
JMP Tabl_JF + 8 |
|
;непрямий міжсегментний на Dmul |
|
|
... |
|
|
|
|
MOV SI,Switch |
|
;перемикач адреси дальнього переходу SHL SI.1 |
|
|
SHL SI.1 |
|
;4*S1 = 0, 4, 8 або 12 |
|
|
JMP Tabl_JF[SI] |
|
;непрямий міжсегментний по таблиці |
|
|
... |
|
|
|
|
LEA BX,Tabl_JF |
|
;ВХ = база таблиці |
51
|
JMP |
FAR PTR [BX] |
;непрямий міжсегментний на Da |
|
|
... |
|
|
|
|
JMP |
FAR PTR [ВX][SI] |
;непрямий міжсегментний за адресою з таблиці Tabl_JF, |
|
;який визначається перемикачем |
|
|||
|
... |
|
|
|
|
RET |
|
|
;повернення в DOS |
Cseg1 ENDS |
|
|
|
|
Cseg2 SEGMENT 'CODE' NAME mod2 |
||||
Cseg3 SEGMENT 'CODE' |
|
|||
Dadd |
LABEL FARPUBLIC Begin |
|
||
Fadd: . |
. |
|
|
|
Begin: |
. |
|
|
. |
|
|
|
|
|
Dsub LABEL FAR . |
|
|||
Fsub . Cseg3 ENDS |
|
|
||
|
. |
END |
|
|
; |
. |
|
|
|
|
|
|
|
|
Dmul |
LABEL |
FAR |
|
|
Fmul: . |
|
|
|
|
|
. |
|
|
|
; |
. |
|
|
|
|
|
|
|
|
Ddiv |
LABEL |
FAR |
|
|
Fdiv: . |
|
|
|
|
|
. |
|
|
|
|
. |
|
|
|
|
JMP Addr_JF |
;непрямий міжсегментний за адр. у пам'яті |
||
Cseg2 ENDS |
|
|
|
|
; |
END |
Start |
|
|
|
|
|
Приклад програми, яка наочно демонструє виконання переходів. Наберіть текст у будь-якому текстовому редакторі, скомпілюйте і скомпонуйте файл у виконуваний та запустіть на виконання.
IDEAL |
|
MODEL small |
|
Stack 256 |
|
DATASEG |
;Сегмент даних |
Promt DB'Vze den? (Yes/No - y/n)$'
GoodMorning DB 13,10,'Dobroe utro!',13,10,'$'
GoodAfternoon DB 13,10,'Dobryi den!',13,10,'$'
TiZavtrakal DB 13,10,'Ti uje zavtrakal? (Yes/No - y/n)$'
TiObedal DB 13,10,'Ti uje obedal? (Yes/No - y/n)$'
Zavtrakal DB 13,10,'Horosho, chto pozavtrakal =)$'
Obedal DB 13,10,'Horosho, chto poobedal =)$'
NeZavtrakal DB 13,10,'Priyatnogo appetita k zavtraku!!!$'
NeObedal DB 13,10,'Priyatnogp appetita k obedu!!!$'
CODESEG ;Сегмент коду
52
START: |
|
mov ax,@data |
|
mov ds,ax |
|
mov dx,OFFSET Promt |
|
mov ah,9 |
|
int 21h |
|
mov ah,1 |
|
int 21h |
|
cmp al,'y' |
;якщо натиснута клавіша Y, то |
jz IsAfternoon |
;Команда переходу |
cmp al,'n' |
|
jz IsMorning
IsAfternoon:mov dx,OFFSET TiObedal mov ah,9
int 21h mov ah,1 int 21h cmp al,'y' jz IsObedal cmp al,'n'
jz IsNeObedal IsObedal:
mov dx,OFFSET Obedal jmp SHORT Disp IsNeObedal:
mov dx,OFFSET NeObedal mov ah,9
int 21h
mov ax,4C00h int 21h IsMorning:
mov dx,OFFSET TiZavtrakal mov ah,9
int 21h mov ah,1 int 21h cmp al,'y'
jz IsZavtrakal cmp al,'n'
jz IsNeZavtrakal IsZavtrakal:
mov dx,OFFSET Zavtrakal jmp SHORT Disp IsNeZavtrakal:
mov dx,OFFSET NeZavtrakal Disp:
mov ah,9 int 21h Exit:
mov ax,4C00h int 21h
END Start
53
Окрім розглянутих вище команд безумовного переходу, в системі команд х86 є 17 команд умовного переходу, які, як і команда JMP SHORT label, забезпечують короткий перехід в сегменті в діапазоні -128 ... +127 байтів щодо адреси наступної команди. Всі вони мають 2-байтний формат; причому в другому байті міститься зсув (ціле із знаком), який розширюється знаковим розрядом до слова і складається з вмістом IP, якщо на момент виконання команди задана її мнемокодом умова виконана, інакше цей зсув не додається до IP і, отже, перехід не здійснюється. Мнемокоди команд умовних переходів описані в додатку 1, при цьому слід враховувати, що деякі команди умовних переходів мають два, а то і 3 різних мнемокодів, наприклад, команди JB, JNAE і JC мають абсолютно ідентичний машинний код, але надають різне контекстне "забарвлення" програмі:
JB |
label |
; |
перехід, якщо "нижче" (CF=l) |
дорівнює" |
|
JNAE label |
; |
перехід, |
якщо "не вище і не |
||
(CF=1) |
label |
;перехід, |
якщо |
виникло |
|
JC |
перенесення/займання, тобто (CF=1)
Програміст вибирає з цих трьох рівноцінних команд ту, яка на його думку краще відображає умову переходу. Команди умовного переходу використовуються після арифметичних, логічних і інших команд, що впливають на прапорці, для галуження алгоритму залежно від результату виконання команди. Особливо важливо правильно використовувати команди умовних переходів після команди порівняння, оскільки розшукуєтся відмінність між порівнянням чисел із знаком і без знаку:
СМР ор1,ор2 |
|
;ор1 і ор2 |
числа із знаком або без знаку |
|||||
перехід, якщо |
op1 > ор2 |
JG |
(JNLE) |
JA |
(JNBE) |
|||
ор1 >= ор2 |
JGE |
(JNL) |
JAE |
(JNB, JNC) |
|
|
||
opi < ор2 |
JL |
(JNGE) |
JB |
(JNAE, JC) |
|
|
||
ор1 |
<= ор2 |
JLE |
(JNG) JBE |
(JNA) |
|
|
||
ор1 |
= ор2 |
JE |
(JZ) |
|
JE |
(JZ) |
|
|
ор1 |
<> ор2 |
JNE |
(JNZ) |
JNE |
(JNZ) |
|
|
Якщо потрібно здійснити умовний внутрішньосегментний довгий або навіть міжсегментний умовний перехід, то застосовується наступний прийом.
Jcc |
No_Jump |
;обхід JMP по протилежній умові |
JMP |
NEAR PTR або JMP FAR PTR ;по необхідній умові |
|
No_Jump |
... ;продовжити, якщо потрібна умова не виконана. |
Наприклад, якщо за умови АН > AL (без знаку) потрібно перейти на мітку Too_Big в іншому сегменті, то це можна запрограмувати так:
СМР AH,AL |
;порівняти операнди |
|
|
JBE |
Cont |
;обійти перехід, якщо АН <= AL |
|
JMP |
FAR PTR Too_Big ;перейти, якщо АН > |
AL |
54
Cont |
... |
;продовження, якщо немає переходу по |
умові
Використовуючи команди умовних і безумовних переходів, можна реалізувати різні види галуження в програмі, у тому числі і цикли. Але для реалізації циклів з певним числом повторень в системі команд х86 є спеціальні команди управління циклами, кожна з яких при виконанні зменшує на 1 вміст CX, а потім використовує його нове значення для ухвалення рішення про перехід:
LOOP |
label |
;продовжити з label, якщо СХ не рівний 0 |
|
LOOPE label |
;продовжити з label, якщо СХ не рівний 0 і |
;ZF-1, т .е. повторення циклу припиняється якщо СХ = 0 або ZF |
||
;стане рівний 0 |
;продовжити з label, якщо СХ не рівний 0 |
|
|
LOOPNE label |
|
;і ZF = 0, тобто |
повторення циклу припиняється |
|
;якщо СХ = 0 або |
ZF стане рівний 1 |
Для команди LOOPE є еквівалент LOOPZ, а для команди LOOPNE - LOOPNZ. Очевидно, що перед входом в цикл потрібно підготувати лічильник циклів в СХ, для запобігання входу в цикл з нульовим значенням СХ корисно використовувати команду короткого переходу.
JCXZ |
label |
;перехід, якщо СХ = 0 |
При використанні умовних команд управління циклом в тілі циклу повинні бути команди, що впливають на прапор ZF.
;Фрагмент програми підрахунку кількості додатних (SI) і ;від’ємних (DI) елементів в масиві цілих чисел ARR (слова) ;кількість елементів масиву міститься в СХ.
;Підрахунок припиняється, якщо виявиться нульовий елемент в масиві
SUB |
BX,BX;підготовка |
покажчика елементів |
масиву |
MOV |
||
SI,BX |
DI,BX |
|
|
|
|
|
MOV |
|
|
|
|
||
JCXZ |
Exit ;обхід, якщо нульова кількість елементів |
з |
||||
Again: |
CMP |
Агг[BX],0 |
;порівняти |
черговий |
елемент |
|
нулем |
Exit |
|
;завершити, |
якщо |
нульовий |
|
JE |
|
|||||
елемент |
Great |
;> 0 |
|
|
|
|
JG |
|
|
|
|||
INC |
DI |
|
;підрахунок від’ємних |
|
|
|
JMP |
SHORT Next |
;підрахунок додатних |
|
|
||
Great |
INC |
SI |
|
|
||
Next: |
ADD |
BX,2 |
;покажчик на наступний елемент |
|||
LOOP Again |
;продовжити, |
якщо |
не |
всі |
||
оброблено |
... |
|
|
|
|
|
EXIT |
|
|
|
|
|
55
Контрольні питання
1.Від чого залежить довжина команд безумовного переходу?
2.Яка інформація про перехід міститься в команді для безумовного переходу усередині сегменту?
3.На які групи можна розділити команди умовних переходів?
4.Які способи адресації можна використовувати для непрямого внутрішньосегментного переходу?
5.Які існують можливості для здійснення прямого міжсегментного
переходу?
Індивідуальні завдання
1.Написати програму перетворення рядкових букв заданого рядка символів в прописні букви.
2.Написати програму ущільнення тексту за рахунок заміни двох і більш пропусків одним пропуском.
3.Реалізувати програмно наступну конструкцію вибору
dо case X mod 4
Y = 3 * (X + 437) / (Z - 4128) ; Y = (Х - Z +1289) / X ;
Y = (X - 654) / (4 * Z) ;
Y = 255 * X / (X + Z - 12985) ; end
4.Написати програму впорядковування в алфавітному порядку таблиці, що містить десять 2-символьних слів.
5.Написати програму підсумовування чисел масиву (20 елементів), що належать діапазону від MIN до МАХ. Числа в масиві розглядаються як беззнакові величини (слова), результат додавання реалізувати у вигляді подвійного слова.
6.Програмно реалізувати сортування після убування масиву цілих чисел із знаком (15 слів), застосовуючи алгоритм "бульбашкового" сортування по схемі ПОВТОРЮВАТИ – ПОКИ :
repeat
послідовність дії until (вираз)
7.Написати програму, яка перетворює рядки мнемокодів команд
MOVSB, MOVSW, LODSB, LODSW, STOSB, STOSW, SCASB, SCASW, CMPSW (у довільному порядку) у відповідні двійкові коди машинних команд.
8.Написати програму, яка виконує функцію реасемблювання машинних кодів, приведених в завданні 7 команд, у відповідні мнемокоди.
9.Написати програму, яка сканує символи з рядка, перевіряє їх на належність 16-ковим цифрам і до тих пір, поки не з'явиться символ, відмінний від 16-кової цифри, формує з кожної пари цифр відповідне двійкове значення і записує його в байтовий масив
56
10.Написати програму пошуку заданого ланцюжка символів в деякому текстовому масиві, ознакою завершення якого є код 1Ah.
11.Написати програму підсумовування елементів масиву (20 слів в беззнаковому поданні), яка зупиняє свою роботу, якщо сума перевищила значення 65535 або якщо оброблені всі елементи масиву (суму формувати у вигляді подвійного слова) Використовувати схему
do while (вираз)
послідовність дій end
12.Написати програму, яка переставляє в зворотному напрямку букви
всловах заданого рядка в ASCIIZ-форматі.
13.Написати програму, яка підраховує частоту використання букв в деякому заданому тексті, представленому в ASCIIZ-формате.
14.Написати програму, яка в заданому рядку визначає число слів (роздільники слів. пропуск, кома, крапка, крапка з комою, тире) і встановлює довжину найбільш довгого слова в рядку.
Додаток 6.1 Приклади виконання індивідуальних завдань. Програма-діалог «Добра порада!», створена студентом 411-ОКС групи
Дроновим Олександром.
|
|
ideal |
small |
|
|
|
model |
||
|
|
Stack |
256 |
|
|
|
Dataseg |
|
|
Promt |
db |
13,10,'Здоров друже! Хочеш добру пораду? (Так/Нi - y/n)$' |
||
VitNo |
db |
13,10,'Як знаєш. Бувай!$' |
||
VitYes |
db |
13,10,'Ти жiночої статi? (Так/Нi - y/n)$' |
||
Man |
db |
13,10,'Гаразд, ти навчаєшся? (Так/Нi - y/n)$' |
||
ManNo |
|
db |
13,10,'Ти працюєш? (Так/Нi - y/n)$' |
|
ManNo1 |
db |
13,10,'Ти пенсiонер? (Так/Нi - y/n)$' |
||
ManPor |
db |
13,10,'Ось тобi порада, ЛЕДАЦЮГА!!! Якщо не будеш працювати,',13,10,'то |
швидко "полетиш" за грати! Нiхто тебе не пригадає,',13,10,'нi теплим словом привiтає. Якщо ж ти будеш працювати,',13,10,'тебе всi будуть поважати, дорба i щастя вам бажати!!!$' ManYes db 13,10,'Якщо ти добре будеш працювати, то грошенят багато будеш мати,',13,10,'з грошима ти в життi не згинеш, до неба з думкою про них полинеш,',13,10,'Але не задирай ти високо свiй нiс! Бо повезуть тебе в багажнику у лiс!$'
ManNAV db 13,10,'Повинен зараз добре ти навчатись, щоб потiм до дiвчат з вiршами залицятись,',13,10,'дiвчата люблять слухати вiршi, тому одраз до серця будеш линути їм ти!$' ManPen db 13,10,'В країнi нашiй ти на пенсiю не проживеш!',13,10,'Скорiш за все ти ноги передчасно простягнеш,i з вдачею такою у тей свiт минеш!',13,10,'Ото ж вставай, шукай собi роботу, поки не задзвонили родичi в "СКОРБОТУ"!$'
Woman |
db |
13,10,'О... Це добре! Ти навчаєшся? (Так/Нi - y/n)$' |
|
WomNo |
db |
13,10,'Ти працюєш? (Так/Нi - y/n)$' |
|
WomNo1 |
db |
13,10,'Ти вродлива? (Так/Нi - y/n)$' |
|
WomNAV |
db |
13,10,'Якщо ти незалежна хочеш бути, i нареченого свого у чоботи |
обути,',13,10,'всi сили ти повинна зараз на навчання вiддавати, щоб потiм гiдно працювати!$' WomYes db 13,10,'Якщо ти працюватимеш ти на славу, то витягнеш зi звалища державу.',13,10,'Тобi пiдвладнi будуть всi кордони, й не заважатимуть нiякi перепони!$'
57
WomWro db 13,10,'Тобi на свiтi легко жити, ти можеш хлопцям голову дурити,',13,10,'але цей час мине колись, нiчого ти не вдiєш, як ти не крутись!',13,10,'Та щоб в iсторiї залишити свiй слiд, повинна ти за розум взятися як слiд!$'
WomPor db |
13,10,'Всiм крокодилам у життi не пощастило, нi розуму нi красоти, а тiльки |
сила!',13,10,'В |
життi тобi не легко буде жити, але не дай собi над цим весь час |
тужити!',13,10,'Та прийде час i вже не будеш ти тужити - бо будеш в всесвiтi найкраще жити!$'
Codeseg
START:
mov ax,@data mov ds,ax
mov dx,OFFSET Promt |
;Привiт друже, хочеш добру пораду? |
|
mov ah,9 |
|
|
int 21h |
|
|
mov ah,1 |
|
|
int 21h |
|
|
cmp al,'y' |
;Так |
|
jz VitYesOK |
;Стрибок на "Ти жiночої статi?" |
|
cmp al,'n' |
;Нi |
|
jz exitOZ |
;Стрибок на "Як знаєш, бувай!" |
|
exitOZ: |
|
|
mov dx,offset VitNo |
|
|
mov ah,9 |
|
|
int 21h |
|
|
mov ax,4c00h |
|
|
int 21h |
|
|
VitYesOK: |
|
|
mov dx,OFFSET VitYes |
;Ти жiночої статi? |
|
mov ah,9 |
|
|
int 21h |
|
|
mov ah,1 |
|
|
int 21h |
|
|
cmp al,'y' |
;Так |
|
jz WomanOK |
;Стрибок на "О... Це добре! Ти навчаєшся?" |
|
cmp al,'n' |
;Нi |
|
jz ManOK |
;Стрибок на "Гаразд, ти навчаєшся?" |
|
WomanOK: |
|
|
mov dx,OFFSET Woman ;О... Це добре! Ти навчаєшся?
mov ah,9 |
|
int 21h |
|
mov ah,1 |
|
int 21h |
|
cmp al,'y' |
;Так |
jz WomNAVOK |
;Стрибок на "Ти незалежна хочеш бути... |
cmp al,'n' |
;Нi |
jz WomNoOK |
;Стрибок на "Ти працюєшь?" |
ManOK:
mov dx,OFFSET Man mov ah,9
int 21h mov ah,1
58
int 21h cmp al,'y'
jz ManNavOK cmp al,'n'
jz ManNOOK WomNoOK:
mov dx,OFFSET WomNo mov ah,9
int 21h mov ah,1 int 21h cmp al,'y'
jz WomNAVOK cmp al,'n'
jz WomNo1OK WomNo1OK:
mov dx,OFFSET WomNo1 mov ah,9
int 21h mov ah,1 int 21h cmp al,'y'
jz WomWroOK cmp al,'n'
jz WomPorOK ManNoOK:
mov dx,OFFSET ManNo mov ah,9
int 21h mov ah,1 int 21h cmp al,'y'
jz ManYesOK cmp al,'n'
jz ManNo1OK ManNo1OK:
mov dx,OFFSET ManNo1 mov ah,9
int 21h mov ah,1 int 21h cmp al,'y'
jz ManPenOK cmp al,'n'
jz ManPorOK
WomNAVOK:
mov dx,OFFSET WomNAV mov ah,9
int 21h mov ah,1 jz Exit
59
ManNAVOK:
mov dx,OFFSET ManNAV mov ah,9
int 21h mov ah,1 jz Exit WomWroOK:
mov dx,OFFSET WomWro mov ah,9
int 21h mov ah,1 jz Exit ManYesOK:
mov dx,OFFSET ManYes mov ah,9
int 21h mov ah,1 jz Exit ManPenOK:
mov dx,OFFSET ManPen mov ah,9
int 21h mov ah,1 jz Exit WomPorOK:
mov dx,OFFSET WomPor mov ah,9
int 21h mov ah,1 jz Exit ManPorOK:
mov dx,OFFSET ManPor mov ah,9
int 21h mov ah,1 jz Exit
Exit:
Int 21h
mov ax,4c00h int 21h
end start
Програма з паролем, створена студентом групи 411-ОКС-2004 Яворським Володимиром Володимировичем.
Принцип роботи програми з паролем поданий на рисунку 6.1.
60