Dəyişənlər
Əvvəlki Dəyişənlər proqramın .data hissəsində elan olunur. Dəyişənlərdən hər hansı məlumat saxlamaq üçün istifadə olunur. Assembler dilində dəyişən elan etmək üçün aşağıdakı sintaksisdən istifadə olunur.
nişan:
.tip ilkin_qiymət
Nişan dəyişənin adını bildirir. tip isə dəyişənin yaddaşda neçə bayt yer tutduğunu göstərir. Qeyd edim ki, assembler dilində yüksək səviyyəli dillərdə olduğu kimi, tam tipi, həqiqi tipi, və s. tiplər xarakteristik deyil. Tip deyərkən, əsasən yaddaşda tutulan yerin ölçüsü başa düşülür. Ən geniş istifadə olunan tiplər aşağıdakılardır: byte, int, long və ascii. byte və ascii tiplər bir bayt, int və long isə, uyğun olaraq 2 və 4 bayt qədər yer tutur. ascii tipindən Simvol tipli məlumatları yerləşdirmək üçün istifadə olunur.
Misal üçün, dey1 və dey2 adlı iki dəyişən elan etmək istəsək, aşağıdakı kimi yazmalıyıq:
dey1:
.long
dey2:
.long
Bu zaman yaddaşda dey1 və dey2 adlı, hər biri 4 bayt yer tutan iki dəyişən elan etmiş oluruq.
Əgər elan zamanı dəyişənlərə ilkin qiymət mənimsətmək istəsək, onda bu qiyməti tipdən sonra qeyd etməliyik. Aşağıdakı kimi:
dey1:
.long 34
Bu zaman artıq dey1 dəyişəninin ilkin qiyməti 34 olar.
Cərgələrin elan olunması
Yüksək səviyyəli dillərdə olduğu kimi, assembler dilində də cərgələrdən (massivlər) istifadə etmək mümkündür. Bunun üçün adi dəyişənlər elan etdiyimiz qaydadan istifadə olunur, sadəcə olaraq, bu zaman cərgənin elementləri qeyd edilərək, vergüllə ayrılır. Misal üçün, byte tipindən olan 5 elementli f cərgəsi elan etmək istəsək, onda aşağıdakı kimi yazmaq lazımdır.
f:
.byte 1,3,45,6,7
Bu zaman biz cərgənin elementlərinə ilkin qiymətlər mənimsətmiş olduq.
Sətirlərin elan olunması
Assembler dilində sətir elan etmək istəsək, onda yenə də, adi dəyişən elan etmə yolundan istifadə edəcəyik və tip olaraq ascii seçəcəyik. İlkin qiymət olaraq isə, cütdırnaq arasında elan etmək istədiyimiz sətri yerləşdirəcəyik, misal üçün, aşağıdakı kimi:
set:
.ascii "Salam dünya"
Bu qayda ilə biz "Salam dünya" sətrini elan etmiş oluruq.
Dəyişənlərin qiymətlərinə müraciət
Gəlin, assembler dilində dəyişənlərə aid bir neçə proqram nümunəsinə baxaq.
proq3.s-də biz iki ədədin cəmini hesabladıq. Ədədlərin qiymətlərini registrlərdə yerləşdirdik. İndi artıq biz fiziki yaddaşa müraciət edə bilərik. Gəlin, eyni proqramı dəyişənlərdən istifadə etməklə tərtib edək.
İki ədədin cəmi proqramı (proq4.s):
#pro14.s
.data
eded1:
.long 45
eded2:
.long 34
.text
.globl _start
.type _start,@function
_start:
movl eded1, %eax
movl eded2, %ebx
addl %eax, %ebx
movl $1, %eax
int $0x80
Proqramı kompilyasiya və icra edək:
[user@unix progs_as]$
[user@unix progs_as]$ as proq4.s -o proq4.o
[user@unix progs_as]$ ld proq4.o -o proq4
[user@unix progs_as]$ ./proq4
[user@unix progs_as]$ echo $?
79
[user@unix progs_as]$
[user@unix progs_as]$
jmp instruksiyası
jmp instruksiyası (hoppanmaq) proqramın icra istiqamətini bir yerdən başqa yerə yönləndirmək üçün istifadə olunur. Əsasən cmp instruksiyası ilə birlikdə istifadə olunur. Yəni müqayisənin nəticəsindən asılı olaraq proqramın icrasını bu və ya digər yerdən davam etdirmək.
jmp instruksiyasının sintaksisi aşağıdakı kimidir:
jmp mövqe
Bu zaman icraolunma artıq "mövqe" adlı yerə sıçrayır.
Sadə proqrama baxaq.
# proq6.s
.text
.globl _start
.type _start,@function
_start:
movl $1, %ecx
movl $5, %edx
addl %ecx, %edx
movl $6, %ebx
addl %edx, %ebx
son:
movl $1, %eax
int $0x80
Bu proqramda biz _start-dan əlavə son nişanını tərtib etmişik. Nişanları yuxarıda qeyd elədiyimiz kimi, proqramın məlumat və kod hissəsinin istənilən yerində elan edə bilərik. Proqram _start-dan başlayaraq, aşağı doğru yerləşmiş instruksiyaları ardıcıl icra edir. Proqramı icra eləsək, nəticə olaraq 12 alarıq. İndi isə, proqramda jmp instruksiyasından istifadə edək.
# proq6.s
.text
.globl _start
.type _start,@function
_start:
movl $1, %ecx
movl $5, %edx
addl %ecx, %edx
movl $6, %ebx
jmp son
addl %edx, %ebx
son:
movl $1, %eax
int $0x80
Əgər bu proqramı icra eləsək, onda cavab olaraq 6 qiymətini alarıq. Səbəb isə odur ki, movl $6, %ebx instruksiyasından sonra jmp son instruksiyası icra olunur. Nəticədə addl %edx, %ebx instruksiyası icra olunmadan son nişanına keçid baş verir.
cmp instruksiyası
Məlumatların qiymətlərini müqayisə etmək üçün CPU cmp instruksiyasından istifadə edir. cmp instruksiyasının sintaksisi aşağıdakı kimidir:
cmp arq1, arq2
arq1 ilə arq2-in qiyməti yoxlanılır və nəticə flags registrində qeydə alınır. Müqayisənin nəticəsindən asılı olaraq, bu və ya digər əməliyyatı icra etmək üçün
cmp instruksiyasından sonra şərti keçid instruksiyalarından istifadə etməliyik.
Şərti keçid instruksiyaları aşağıdakılardır:
jg, jge, jl, jle, je, jne.
(jump great, jump great equal, jump less, jump less equal, jump equal, jump not equal)
Bu keçid instruksiyaları iki kəmiyyətin müqayisəsinin bütün mümkün nəticələrini uyğun olaraq, aşağıdakı kimi nəzərə alır: keç əgər ikinci arqument birincidən böyükdürsə, böyük bərabərdirsə, kiçikdirsə, kiçik bərabərdirsə, bərabərdirsə, fərqlidirsə.
Proqram nümunəsi: İki ədədin böyüyünü tapan proqram tərtib edək.
#prog7.s
.data
eded1:
.long 110
eded2:
.long 15
.text
.globl _start
.type _start, @function
_start:
#eded1-i eax-ə yaz
movl eded1, %eax
#eded2-ni ebx-ə yaz
movl eded2, %ebx
#ədədləri müqayisə et, əgər ikinci birincidən böyükdürsə
#son-a keç, çünki artıq böyük ədəd ebx-dədir
cmpl %eax, %ebx
jg son
#birinci böyükdür, onu ebx-ə köçür
movl %eax, %ebx
son:
movl $1, %eax
int $0x80
Proqramın izahı:
Biz əvvəlcə eded1 və eded2-nin qiymətlərini uyğun olaraq %eax və %ebx registrlərinə köçürdük. Daha sonra, cmp vasitəsilə bu qiymətləri müqayisə etdik. Əgər %ebx %eax-dən böyük olarsa, bu zamanjg instruksiyası son-a keçəcək, əks halda - (%eax > %ebx) olarsa, proqramın icrası növbəti instruksiyadan davam edir. movl %eax, %ebx. Böyük qiymət %ebx-ə yazılır. Proqram sona çatır.
Tapşırıq:
1. eded1 və eded2-yə (0-255 arası) müxtəlif qiymətlər verməklə proqramı test edib necə işlədiyin yoxlayın.