Menu

Daxil olun Qeydiyyat

Assembler x86 Linux (64 bit)

Say sistemləri

Say sistemləri

Biz indiyə kimi proqramlarımızda yalnız onluq ədədlər və ascii simvollardan istifadə etdik. Proqramlaşdırmada, xüsusilə, sistem proqramlaşdırmada yaddaş ünvanları ilə işləyərkən, 16-lıq (hexal) say sistemləri ilə işləmək daha məsləhətdir. Bəzən isə, bit əməliyyatları (irəlidə) yerinə yetirərkən, ədədlərin ikili say sistemindəki halı ilə işləmək lazım gəlir. Bir proqramçı kimi, say sistemlərinin mahiyyətini bilmək, bir say sistemindən digərinə keçməyi bacarmaq mühümdür.

Gəlin, bu məsələlər ilə məşğul olaq.

Məlumat ölçüsü vahidi olaraq, bayt qəbul olunur. Bayt özü də bit adlandırılan daha kiçik yaddaş elementlərindən ibarətdir. Bir bayt 8 bit-dən ibarətdir.

 


 

Bir bit özündə 2 müxtəlif qiymət: 0 və ya 1 qiymətlərini saxlaya bilər (eyni vaxtda yalnız birini). Bu isə imkan verir ki, bir baytda 256 bitlərin müxtəlif düzülüşünü saxlaya bilək. Misal üçün:


 

Kompüter yaddaşında bütün məlumatlar bu şəkildə olur, baytlar ardıcıllığı, onlar da öz növbəsində bitlər ardıcıllığı şəklində. Məlumatın bitlərdə yerləşdirlimiş forması onun ikili forması adlandırılır. Burada məlumat dedikdə, söhbət yalnız ədədlərdən gedir. Bütün məlumatlar onluq və ya 16-lıq ədədlərlə ifadə olunur, bu ədədlər isə, yaddaşda ikili say sistemində yerləşdirilir.

 

İkili say sistemi

Adından da göründüyü kimi, ikili say sistemində bütün ədədlər cəmi 2 rəqəm: 0 və 1 vasitəsilə ifadə olunur. İkili ədədlərə misal olaraq, 0001010010, 1111, 011001111, 0, 11 və s. misal göstərmək olar.

Aşağıdakı qaydadan istifadə etməklə, verilmiş ikili ədədi onluq ədədə çevirə bilərik. Tutaq ki, hər hansı [x(n)][x(n-1)][x(n-2)]...[x2][x1] ikili ədədi verilmişdir. Burada hər bir x(k), 1<=k<=n 0 və ya 1 qiyməti ala bilər. İkili ədədi onluq ədədə çevirmək üçün aşağıdakı düsturdan istifadə edirik.

onluq_eded = x(n)*2^(n - 1) + x(n-1)*2^(n-2)+ ... x(2)*2^1 + x(1)*2^0;

Burada 2^k ifadəsi 2 üstü k mənasını verir, yəni 2*2*2 ... *2 k dəfə.

Misal üçün, 1000101001 ikili ədədini onluq ədədə çevirək. Burada rəqəmlərin sayı = 10. Ona görə yazırıq:

1000101001 = 1*2^9 + 0*2^8 + 0*2^7 + 0*2^6 + 1*2^5 + 0*2^4 + 1*2^3 + 0*2^2 + 0*2^1 + 1*2^0

1000101001 = 1*2^9 + 1*2^5 + 1*2^3 + 1*2^0 = 512 + 32 + 8 + 1 = 553

Başqa bir ikili ədədi onluq ədədə çevirək, 00000100111101. Bu halda rəqəmlərin sayı 15-dir.

İlk rəqəmlər 0 olduğundan, onların 2-nin üstünə hasili 0 edəcək. Ona görə onları buraxa və birbaşa 1 ilə başlayan rəqəmlərdən hesablamanı apara bilərik.

00000100111101 = 1*2^8 + 0*2^7 + 0*2^6 + 1*2^5 + 1*2^4 + 1*2^3 + 1*2^2 + 0*2^1 + 1*2^0 =

= 256 + 32 + 16 + 8 + 4 + 1 = 317

İndi isə, onluq ədədin ikili ədədə çevrilməsi ilə məşğul olaq.

Onluq ədədi ikili ədədə çevirmək üçün aşağıdakı qaydadan istifadə edirik:

Onluq ədədi ikiyə bölürük, qalığı yadda saxlayırıq (qalıq 0 və ya 1 ola bilər), qisməti isə yenidən ikiyə bölürük. Yenidən qalığı yadda saxlayırıq və qisməti 2-yə bölürük. Bu prosesi qismətdə 0 qiyməti alınana kimi davam etdiririk. Sonda bütün aldığımız qalıqları əks sıra ilə düzsək, verilmiş onluq ədədə müvafiq ikili ədədi almış olarıq. Misal üçün, 35 onluq ədədini ikili ədədə çevirək.

 


 

Qalıqları sondan əvvələ düzsək, alarıq: 100011

Başqa bir misal, 1378 onluq ədədini ikili ədədə çevirək:

 


 

Qalıqları sondan əvvələ düzsək, alarıq: 10101100010

 

16-lıq say sistemi.

Yaddaş ünvanları ilə işləyərkən ədədlərin 16-lıq say sistemindəki ifadəsindən istifadə etmək çox rahatdır. 16-lıq say sistemindəki rəqəmlər 16 simvol vasitəsilə ifadə olunur. Bu simvollar aşağıdakılardır:

0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f

Burada 0,1,2 ... 9 rəqəmləri onluq say sistemindəki müvafiq ədədlərə, a, b, c, d, e, f 16-lıq rəqəmləri isə, onluq sistemdəki 10, 11, 12, 13, 14 və 15 ədədlərinə uyğun gəlir.

16-lıq ədədin 10-luq ədədə çevrilməsi.

16-lıq ədədi 10-luq ədədə çevirmək üçün aşağıdakı qaydadan istiadə edirik. Tutaq ki,

[x(n)][x(n-1)]...[x(2)][x(1)] 16-lıq ədədi verilmişdir. Bu ədədi aşağıdakı düsturla 10-luq ədədə çevirə bilərik:

[x(n)][x(n-1)]...[x(2)][x(1)] = x(n)*16^(n - 1) + x(n-1)*16^(n-2)+ ... x(2)*16^1 + x(1)*16^0;

Misal üçün, 1256f 16-lıq ədədi 10-luq ədədə aşağıdakı kimi çevirə bilərik.

1256f = 1*16^4 + 2*16^3 + 5*16^2 + 6*16^1 + 15*16^0 = 65536 + 8292 + 1280 + 96 + 15 = 75219

Başqa bir 16-lıq ədədi 10-luq ədədə çevirək:

f3a034b1 = 15*16^7 + 3*16^6 + 10*16^5 + 0*16^4 + 3*16^3 + 4*16^2 + 11*16^1 + 1*16^0 =

= 4087362737

 

Onluq ədədlərin 16-lıq say sisteminə çevrilməsi.

Onluq ədədləri 16-lıq say sisteminə çevirərkən, ikilik sistemə çevirdiyimiz qaydanı tətbiq edəcəyik, lakin bölünən olaraq 2 yox, 16-dan istifadə edəcəyik. Misal üçün, 20560414 onluq ədədini 16-lıq ədədə çevirək:

 


 

16-lıq sistemdə verilmiş ədədləri 10-luq ədədlərlə qarışdırmamaq üçün onların əvvəlinə "0x" işarələməsi artırılır. Misal üçün, 0xff450012 şəklində. İkilik ədədlərin qarşısına isə, "0b"işarələməsi artırılır. Misal üçün, 0b11010011101001 şəklində.

Elə proqram tərtib edək ki, verilmiş ikili ədədi onluq ədədə çevirsin:


#prog17.s
#ikili ədədi 10-luq ədədə çevirən program

.data

setir1:
.ascii "İkili ədədi daxil edin\n"

say1:
.long 23

yeni_str:
.ascii "\n"

str:
.ascii "     "

eded1:
.long 0

onluq_simvollar:
.ascii "0123456789"

bufer:
.rept 100
.ascii "\0"
.endr

.text

.globl _start
.type _start, @function
_start:
#birinci ədədin daxil edilməsini istə
pushq say1
pushq $setir1
call cap_et

#ikili ədədi sətir şəklində qəbul et
pushq $100
pushq $bufer
call daxil_et

#sətri ədədə çevir
pushq $bufer
pushq $eded1
call ikili_setri_edede_cevir

#nəticəni çap etmək üçün yenidən sətrə çevir
pushq eded1
pushq $str
call ededi_setre_cevir

#sətir formasında olan ədədi çap et
pushq $10
pushq $str
call cap_et

#yeni sətir simvolunu çap et
pushq $1
pushq $yeni_str
call cap_et

son:
movl $1, %eax
int $0x80

#==========================================#
#        FUNKSİYALAR        #
#==========================================#

#cap_et funksiyası
.type cap_et, @function
cap_et:
pushq %rbp
movq %rsp, %rbp

movl $4, %eax
movl $1, %ebx
movq 16(%rbp),%rcx
movq 24(%rbp),%rdx
int $0x80

popq %rbp
ret


#daxil_et funksiyası
.type cap_et, @function
daxil_et:
pushq %rbp
movq %rsp, %rbp

movl $3, %eax
movl $0, %ebx
movq 16(%rbp),%rcx
movq 24(%rbp),%rdx
int $0x80

popq %rbp
ret


#sətri ədədə çevir
.type setri_edede_cevir, @function


ikili_setri_edede_cevir:

pushq %rbp
movq %rsp, %rbp

#buferdəki sətri ədədə çevir

subq $8, %rsp

#simvolların sayını hesablayaq
#sonuncu simvol '\n' simvoludur

movl $0, %ecx
movl 24(%rbp), %esi
isec_dovr:
movb (%esi, %ecx, 1), %ah
cmpb $'\n', %ah
je  isec_dovr_son
incl %ecx
jmp isec_dovr

isec_dovr_son:


movl $1, %ebx
movl $0, -8(%rbp)

movl $0, %eax
decl %ecx

yeni_isec_dovr:

movb (%esi, %ecx, 1), %al
subb $'0', %al
movl %ebx, %edx
imull %eax, %edx
addl %edx, -8(%rbp)
shll $1, %ebx
decl %ecx
cmpl $0, %ecx
jl yeni_isec_dovr_son
jmp yeni_isec_dovr


yeni_isec_dovr_son:

movl 16(%rbp), %ebx
movl -8(%rbp), %eax
movl %eax, (%ebx)
    
addq $8, %rsp
popq %rbp
ret

#ədədi sətrə çevir
.type ededi_setre_cevir, @function

ededi_setre_cevir:

pushq %rbp
movq %rsp, %rbp

subq $8, %rsp
movl $0, -8(%rbp)
e_s_c_dovr:
movl $10, %edi
movl $0, %edx
movl 24(%rbp), %eax
div %edi

movl %eax, 24(%rbp)

xorq %rbx, %rbx
movb onluq_simvollar(%edx), %bh
pushq %rbx

incl -8(%rbp)

movl $0, %ebx
movl 24(%rbp), %eax
cmpl %eax, %ebx
je  e_s_c_dovr_son

jmp e_s_c_dovr

e_s_c_dovr_son:

movl -8(%rbp), %ecx
movl 16(%rbp), %eax
xorl %ebx, %ebx
stekden_setre:
cmpl %ebx, %ecx
je e_s_c_son

popq %rdx
movb %dh, (%eax)
incl %eax
incl %ebx
jmp stekden_setre

e_s_c_son:
addq $8, %rsp
popq %rbp
ret

İcra edək:


[user@unix progs_as]$ 
[user@unix progs_as]$ as prog17.s -o prog17.o
[user@unix progs_as]$ ld prog17.o -o prog17
[user@unix progs_as]$ ./prog17
İkili ədədi daxil edin
110101010100111
27303   
[user@unix progs_as]$ 
[user@unix progs_as]$


Bizi dəstəkləyənlər