képzés

Ebben a részben a bemutató, akkor a legfontosabb alapokat létrehozásának eljárásokat. Az eljárás egy kódot, amely elvégezhető többször, és hogy lehet elérni a különböző részein a program. eljárások általában tervezték, hogy végre minden egyes elkészült az akcióprogram, és ezért néha szubrutinok. A másik eljárás, programozási nyelvek hívhatják a funkciók és módszerek, de valójában mindegy

CALL és RET utasítások

Visszatérés a végrehajtott eljárás RET utasítást. Ez a parancs visszaállítja az értéket a verem regiszterbe IP. Így a program végrehajtása folytatódik az utasítást követő után azonnal CALL paranccsal. Jellemzően az eljárást kódot a parancssor végét. CALL és RET utasítások ne módosítsa az értékeket a zászlók (kivéve néhány speciális esetet védett módban). Egy kis minta különböző módon hívja eljárások:

Közel-és Távol eljárás hívások

Vannak 2 típusú eljárás hívások. A szomszédok hívják eljárás hívás, ami a jelenlegi kódot szegmensben. Far kihívás - a kihívás, hogy az eljárás egy másik szegmensben. Ennek megfelelően, 2 típusú parancsok RET - a közeli és távoli visszatérés. FASM fordítóprogram automatikusan meghatározza a megfelelő típusú gépi utasítás, így a legtöbb esetben nem kell aggódni miatta.

A bemutató, csak akkor tudunk használni közelharci eljárás hívások.

Emellett az átviteli paramétereket gyakran kell, hogy néhány érték az eljárásból. Például, ha az eljárás valamit kiszámítja, szeretnénk, ha az egy számítás eredményét Ha az eljárás nem valami hasznos, ha tudni, hogy a kereset sikeres vagy hiba történt. Vannak különböző módon vissza értéket az eljárás, de a leggyakrabban használt - az, hogy az érték az egyik a nyilvántartásokban. Általában erre a célra használt AL és AX regisztereket. Bár lehet csinálni, ahogy tetszik.

Jó vétel az, hogy a nyilvántartások eljárás változásai során annak végrehajtását. Ez az eljárás lehetővé teszi, hogy hívja bármely részén a kódot, és nem kell aggódni, hogy az értékek a nyilvántartásokban lesz kényeztetve. Jellemzően regiszterek mentése a verem a push paranccsal. és mielőtt visszatért az eljárás felújított POP csapat. Természetesen meg kell visszaállítani azokat fordított sorrendben. Mint ez:

Ahhoz, hogy rajzoljon egy vízszintes vonalat a karakterek draw_line eljárást. A DL átvitt karakter kódját, és a CX - karakterek számát szeretné megjeleníteni a képernyőn. Ez az eljárás nem ad vissza semmilyen értéket. Az O 2 végén karaktersorokat írásbeli eljárás print_endline. Ez az úgynevezett paraméterek nélkül, és szintén nincs visszatérési értéke. Kódok karakterek felhívni a keret megtalálható a szimbólum táblát 866, vagy a kódolás, akkor a standard program a Windows «táblázat karakterek” Terminal betűtípust.

Az eredmény a program így néz ki:

képzés

Debugger Turbo Debugger

Itt úgy tűnik, működik. Csak itt, mi szemetet: elosztjuk az egészében ah, és a maradékot - teljes dx, és Sze számtani - egész + frakciót. Hogyan juthat el a nem tudom.
use16
org 100h
JMP Start
; --------
tömb1 dw 1,2,3,4,5,6,6
tömb2 dw 2,5,6,8,9
array3 dw 5,5,7,6,8,8
n1 dw 7
n2 dw 5
n3 dw 6
SR1 rw 1
SR2 rw 1
SR3 rw 1
; ----------
kezdet:
mov cx, [N1]
mov bx, tomb1
hívás sr_arifm
mov [SR1], ax

mov cx, [n2]
mov bx, tömb2
hívás sr_arifm
mov [SR2], ax

mov cx, [N3]
mov bx, array3
hívás sr_arifm
mov [SR3], ax
JMP kilép

sr_arifm:
xor di, di
xor si, si
xor ax, ax
xor dx, dx
mov si, cx

lp:
add ax, [bx + di]
add di, 2
jcxz visszatérés
loop lp
visszatéréshez:
div si
áztat

kilép:
mov ax, 4c00h
int 21h

Igazad van azt feltételezni, törtrész dobni elosztjuk egészek úgy, hogy a többit lehet figyelmen kívül hagyni.
A program meg van írva rendesen. Az egyetlen dolog, amit nem lehet visszaállítani az SI regisztrálja az eljárás (de tudom, hogy így jobban tetszik). És a csapat JCXZ akart itt, az átmenet soha nem lesz, mert belülről a CX sorozat nem nulla.

Igen, jcxz túl okos))) végén a ciklus még egy részlege.
Köszönöm, várjon a következő leckét.

Ott kell lennie a nyilvántartásban BX.

Ezután a funkción belül meg kell állítani a nyilvántartásban AX. Ellenkező esetben az összeg tekinthető rossz. És a második hívás a tömb elemeinek hozzáadódik a számtani átlaga az első tömb.

A fenti példák nem a probléma dimenziójának összege a tömb elemeinek a szavak, amely csak 65 535 * 65 535 - azaz dupla szó.
És ez még mindig érdekes, hogy tolóerő a köteget.
use16
org 100h
JMP Start

kezdet:
mov bx, tomb1
mov cx, [arl1]
hívás sr_ar
mov bx, tömb2
mov cx, [arl2]
hívás sr_ar
mov bx, array3
mov cx, [arl3]
hívás sr_ar

mov ax, 4C00h
int 21h

Mint minden rendesen
Megvan kiderül, hogy az eljárás visszaadja az eredményt a verem. Ehelyett könnyebb volt, csak hogy hagyja AX?

Gyönyörű darab kód:

Egy jó program, de van egy hátránya.

Ha az eredmény vissza AL, majd mentse el a teljes AX - rossz. A AH a maradék szétválás.
meg kell adni

előtt minden megőrzése eredményeket. Mivel aláírva. Vagy add, hogy a végén az eljárás, akkor az eredmény lesz AX.

Mégis el lehet távolítani az egyedi utasítás MOV az eljárás alól, ha a szám átviteli elemek CX és DX.

use16
org 100h
JMP Start

tömb1 dw 12, 8456, 0
length1 dw 3
tomb2 dw 56.875, 1546, 154, 84, 6
length2 dw 5
array3 dw 156, 8974, 1548, 7895
length3 dw 4

kezdet:
mov bx, tomb1
mov cx, [length1]
hívás sr_arifm
mov bx, tömb2
mov cx, [length2]
hívás sr_arifm
mov bx, array3
mov cx, [length3]
hívás sr_arifm

mov ax, 4C00h
int 21h

sr_arifm:
tolja cx
xor si, si
xor ax, ax
lp:
add ax, [bx + si]
add si, 2
loop lp
pop cx
div cx
áztat
Úgy véli, csak a jobb az első alkalommal.
Nem fogja kérni, hogy mi volt a baj?

DX kell állítani, mielőtt a DIV utasítás.
Mivel az osztó - egy 16 bites regiszter, akkor az osztalék DX: AX.
Az első osztály a DX nulla, és a második és a harmadik - ott van a maradék az előző osztály.
Ami a többit illeti, minden rendben

[Kód]
use16
org 100h
JMP indítása

; ======================== [adatok] ==
Arra dw 0xa0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5
arrAlen db 6

arrB DW 0xB0, 0xB1, 0xB2, 0xB3, 0xB4
5 db arrBlen

ARRC dw 0xC0, 0xC1, 0xC2, 0xC3
arrClen dB 4

átlagos rw 3; Arra = 0xA2, arrB = 0xB2, ARRC = 0xC1
; ================================
Kezdés:
xor si, si

mov bx, ARRA
MOVZX cx, [arrAlen]
hívás get_average
mov [átlagos + si], ax

inc si
mov bx, arrB
MOVZX cx, [arrBlen]
hívás get_average
mov [átlagos + si], ax

inc si
mov bx, ARRC
MOVZX cx, [arrClen]
hívás get_average
mov [átlagos + si], ax

mov ax, 4c00h
int 21h

; ----------
get_average :; bx == arrN, cx == száma, ax == visszatérés következtében az átlagos
xor ax, ax
tolja cx
számított:
add ax, [bx]
add bx, 2
hurok számított
pop cx
hívás szakadék
áztat

ossza :; ax == osztva, cx == osztó, ax == eredmény
cwd
div cx
áztat
[/ Code]

Nincsenek hibák, de a szakadék hiába, hogy egy külön eljárás.

Akkor egyszerűen eltávolítani a csapat hívás megosztottság és a ret után - jól működik

JMP fő
; =====================================;
arr1 dw 834,536,1744,6890,241
5 db arr1_length
arr2 dw 486,6574,19,684
arr2_length dB 4
arr3 dw 8577,985,911,648,6578,9894,245
arr3_length db 7
; =====================================;
fő:
xor cx, cx
CLD
mov si, arr1
mov cl, [arr1_length]
hívja getAvrg; ax - számtani átlaga arr1
mov si, arr2
mov cl, [arr2_length]
hívja getAvrg; ax - számtani átlaga arr2
mov si, arr3
mov cl, [arr3_length]
hívja getAvrg; ax - számtani átlaga arr3

Jó eljárás lodsw csapat, lodsb használt megfelelő.
Ott csak kötelező a tény, hogy a méret a tömb a byte után magát a tömböt. Ha elfelejti, akkor kap egy kemény hiba findability.
Azt már jobban megőrizte a korai POP cx parancsot, akkor a parancs helyreállítja PUSH szétosztása előtt.

Egyetértek. És CLD adunk elején eljárás

Kapcsolódó cikkek