Assembly ile PGM Dosyasında Kontrast Ayarı

Açık Kaynak, Kategorilenmemiş, Programlama, Uzun Kod İçerikli, ytulinux

Evet arkadaşlar birkaç hafta önce Gnu Assembler ile yapmış olduğum görüntü işleme ödevimi buraya atıyorum. Öncelikle Gnu Assembler için tanımlama/açıklama tarzı birşey yazmam sanırım konuyu açıklığa kavuşturmak açısından iyi olacaktır.

Gnu Assembler, gcc nin de kullandığı, daha çok unix türevi işletim sistemlerinde kullanılan assemblerdır. Terminalden as komutu ile erişilebilir. Yazmış olduğunuz Gnu Assembler imlasına uygun programı derlemek için, önce
as program.s -o program.o
veya gdb ile debug etmek istiyorsanız
as -gstabs program.s -o program.o
diyerek object dosyasına çevirip, sonra da
ld program.o -o program.out
Komutuyla çalıştırılabilir hale çevirebilirsiniz.
Gnu Assembler imlasına gelince, öncelikle default olarak 32 bit mantığına göre yazmamız gerekiyor. Yani 8086 assemblerlarda alıştığımız ax, bx yerine eax, ebx kullanıyoruz ki bunlar dört baytlık hafıza büyüklüğüne sahip. Tabi bu ax, bx ya da bl, ah gibi küçük kısımları kullanamayacağımız anlamına gelmiyor. Örneğin
movl %eax,8(%esp)

evet yazmaçlardan önce yüzde işareti, adres göstermek için parantez kullanılır. esp nin başındaki 8 ise esp+8 anlamına gelir(bu arada esp bizim stack pointerımız, yani sp). l ise long tipi işlem olduğunu belirtir. Sağdaki sola değil,soldaki sağa atanır. (hızlı bir özet oldu, hiç assembler bilmeyene gnu assembler anlatmak değil zaten niyetim, daha önce 8086 masm veya nasm kullananlara yönelik, yoksa bu açıklama uzar gider)

Değişkenlerimizi tanımlarken ise, normal etiket verir tarzda örneğin
hede_sayisi:
.int 10
şeklinde veriyoruz.
Bu şekilde uzayıp gider diyerek bitirmek istiyorum :)

Şimdi de kontrast ayarı ile ilgili açıklamaya gelelim.
Elimizde 0-255 arası gri tonda renkler tutan bir resim var. bu resmin rengini açmak istiyoruz. diyelim ki 50 açacağız. İki yöntem var. Birinde direk 50 arttırıp, 255 den fazla çıkarsa 255 yazıp geçiyoruz. Bu durumda 205-255 arasındaki renklerin birbirinden farkı kalmadığı için bu aralıktaki bölgeleri göremez hale geliyoruz ki bu bizim için bir kayıp. Diğerinde ise, 50 arttıracaksak, normalizasyon yöntemi ile renkleri 50-255 arasına çekiyoruz. Şimdi normalizasyon deyince bazılarımızdan o ne ya dur anlamadım sesini duyabiliyorum. O kelimenin pek bir numarası yok arkadaşlar kısaca 0-255 arası renklerimizi, 50-255 arasına yayıyoruz. Bunu nasıl yaparım diye düşündüğünüzde aklınıza gelecek ilk oranlama yöntemi ile. Nasıl bu sefer anladınız değil mi 😀
Sıkça Sorulan Soru: Niye assemblerda yazdın bu ödevi?
Çıkıntılık yapmak için. Bir arkadaş assemby ile yazalım mı hocam dedi, hoca yok artık der gibi bir ifadeye büründü. Ben de dedim ki yapılır ya niye yapılmasın. Sonra pişman olmadım değil tabi ortalara doğru :) 4 günümü aldı bu ödev. Ortalarına geldikten sonra bu kadar yazdım boşa gitmesin diye devam ettim. Proje yapar gibi oldu. C ile yarım saatte yazılabiliyor bu arada (tabi hazır yazılmış readpgm ve writepgm fonksiyonları ile).

Ha peki PGM ne derseniz, PGM resim dosyaları arasında en kolay anlaşılabilir olanı. Şu an inceleyeceğimiz dosya tipi P5 PGM, dosyanın başlangıçında dosyanın tipi (P5) dosyanın genişlik ve yüksekliği, kaç renge sahip olduğu (255) ascii olarak yazıyor. sonraki satırda ise unsigned char olarak düşünebileceğiniz bir dizi var, bu dizinin içinde de sırasıyla hangi karenin hangi renkte olduğu yazıyor. Assembly ile yazdığım için ascii-sayı sayı-ascii dönüşümleri epey ızdıraba neden oldu :) Bir de p2 tipi dosya ile uğraşacağımızı sanıyordum (hepsi ascii oluyor bu durumda ki kodlarda zaten bu kısım ile ilgili gereksiz hale gelen kodlar hala duruyor)

Neyse sizi kodlarla başbaşa bırakıyorum.
.section .data
tampon: .fill 40000,1,0
tampon2: .fill 40000,1,0
tampon3: .fill 40000,1,0

#tampondan sayiya fonksiyonuna ait
aski: .fill 10,1,0

veribaslangic:
.int 0
header_uzunluk:
.int 0
asciiboyut:
.long 0
acilis:
.ascii “Resim Ceviriliyor…\n”
acilis_len:
.long acilis_len – acilis
dosya1:
.string “lighthouse.512.pgm”
dosya1len:
.long dosya1len – dosya1
boyut1:
.int 0
dosya2:
.string “lighthouse.512_50.pgm”
dosya2len:
.long dosya2len – dosya1
dosya3:
.string “lighthouse.512_100.pgm”
dosya3len:
.long dosya3len – dosya1
dosya4:
.string “lighthouse.512_150.pgm”
dosya4len:
.long dosya4len – dosya1
dosya5:
.string “lighthouse.512_50n.pgm”
dosya5len:
.long dosya5len – dosya1
dosya6:
.string “lighthouse.512_100n.pgm”
dosya6len:
.long dosya6len – dosya1
dosya7:
.string “lighthouse.512_150n.pgm”
dosya7len:
.long dosya7len – dosya1
knum1:
.int 0
knum2:
.int 0
knum3:
.int 0
knum4:
.int 0
knum5:
.int 0
knum6:
.int 0
knum7:
.int 0
boyut:
.int 0
buffer:
.section .text
.globl _start
_start:
movl %esp, %ebp

#dosya1 i ac
leal dosya1, %eax
pushl %eax
pushl $0
call _dosya_ac
movl %eax,knum1
addl $8,%esp
cmp $0, %eax
jle cikis

#dosya2 yi ac
# leal dosya2, %eax
# pushl %eax
# pushl $1
# call _dosya_ac
# movl %eax,knum2
# addl $8,%esp
cmp $0, %eax
jle cikis

leal  acilis, %eax
pushl %eax
leal  acilis_len, %ebx
pushl (%ebx)
call _yaz
addl $8, %esp

#dosya1 i oku tampona yerlestir
oku:
pushl knum1
leal tampon, %eax
pushl %eax
pushl $40000
call _dosya_oku
addl $12,%esp
movl %eax,boyut1

# cevirilecek resim p5 sanildigi icin yazilmis gereksiz kod parcasi
#leal tampon,%eax
#addl $2,%eax
#pushl %eax
#leal tampon2,%eax
#pushl %eax
#call _tampondan_sayiya
#addl $8,%esp

#xorl %eax,%eax
#xorl %ecx,%ecx
#leal tampon2,%esi
#movb (%esi),%al
#inc %esi
#movb (%esi),%cl
#mul %ecx
#addl $3,%eax
#movl %eax,boyut

#dosya boyutu ogrenilecek (gerek kalmadi, sayilar atlansa yeter)
leal tampon,%eax
#p5\n i atladik
addl $3,%eax
push %eax
call _sayi_al
movl %eax,%ebx
#operand aynı, push yapilmayacak
call _sayi_al
call _sayi_al
pop %ebx
addl $1,%ebx
mov %ebx,veribaslangic
push %ebx
leal tampon,%eax
subl %eax,%ebx
movl %ebx,header_uzunluk
leal header_uzunluk,%ebx
movl (%ebx),%ecx
leal boyut1,%ebx
movl (%ebx),%eax
subl %ecx,%eax
movl %eax,boyut1

#leal tampon2,%eax
#pushl %eax
#leal tampon3,%eax
#pushl %eax
#leal boyut,%ebx
#pushl (%ebx)
#call _asciiye_donustur
#addl $12,%esp
#leal asciiboyut,%esi
#movl %eax,(%esi)

#dosya2 yi oluştur
leal dosya2, %eax
pushl %eax
call _dosya_yarat
addl $8,%esp
movl %eax,knum2
#dosya3 yi oluştur
leal dosya3, %eax
pushl %eax
call _dosya_yarat
addl $8,%esp
movl %eax,knum3
#dosya4 yi oluştur
leal dosya4, %eax
pushl %eax
call _dosya_yarat
addl $8,%esp
movl %eax,knum4
#dosya5 yi oluştur
leal dosya5, %eax
pushl %eax
call _dosya_yarat
addl $8,%esp
movl %eax,knum5
#dosya6 yi oluştur
leal dosya6, %eax
pushl %eax
call _dosya_yarat
addl $8,%esp
movl %eax,knum6
#dosya7 yi oluştur
leal dosya7, %eax
pushl %eax
call _dosya_yarat
addl $8,%esp
movl %eax,knum7

#dosya2 ye tampondan yaz (header)
pushl knum2
leal tampon, %eax
pushl %eax
leal header_uzunluk,%ebx
pushl (%ebx)
call _dosya_yaz
addl $12,%esp
#dosya3 e tampondan yaz (header)
pushl knum3
leal tampon, %eax
pushl %eax
leal header_uzunluk,%ebx
pushl (%ebx)
call _dosya_yaz
addl $12,%esp
#dosya4 e tampondan yaz (header)
pushl knum4
leal tampon, %eax
pushl %eax
leal header_uzunluk,%ebx
pushl (%ebx)
call _dosya_yaz
addl $12,%esp
#dosya5 ye tampondan yaz (header)
pushl knum5
leal tampon, %eax
pushl %eax
leal header_uzunluk,%ebx
pushl (%ebx)
call _dosya_yaz
addl $12,%esp
#dosya6 ye tampondan yaz (header)
pushl knum6
leal tampon, %eax
pushl %eax
leal header_uzunluk,%ebx
pushl (%ebx)
call _dosya_yaz
addl $12,%esp
#dosya7 ye tampondan yaz (header)
pushl knum7
leal tampon, %eax
pushl %eax
leal header_uzunluk,%ebx
pushl (%ebx)
call _dosya_yaz
addl $12,%esp

#veri kismini kopyaliyoruz, header ile işimiz bitti (duz arttirma dosyalari icin)
leal tampon,%ebx
movl %ebx,%esi
leal header_uzunluk,%ebx
addl (%ebx),%esi
leal tampon2,%ebx
movl %ebx,%edi
leal boyut1,%ebx
movl (%ebx),%ecx
kopyala:
movb (%esi),%dl
movb %dl,(%edi)
inc %esi
inc %edi
loop kopyala
#veri kismini kopyaliyoruz, header ile işimiz bitti (norm.lu arttirma dosyalari icin)
leal tampon2,%ebx
movl %ebx,%esi
leal tampon,%ebx
movl %ebx,%edi
leal boyut1,%ebx
movl (%ebx),%ecx
kopyala2:
movb (%esi),%dl
movb %dl,(%edi)
inc %esi
inc %edi
loop kopyala2
veriyaz:
leal tampon2,%eax
pushl %eax
leal tampon2,%eax
pushl %eax
leal boyut1,%ebx
pushl (%ebx)
pushl $50
call _direk_arttir
addl $16,%esp

#dosya2 ye tampondan yaz
pushl knum2
leal tampon2, %eax
pushl %eax
leal boyut1,%ebx
pushl (%ebx)
call _dosya_yaz
addl $12,%esp
#dosya3 arttir
leal tampon2,%eax
pushl %eax
leal tampon2,%eax
pushl %eax
leal boyut1,%ebx
pushl (%ebx)
pushl $50
call _direk_arttir
addl $16,%esp

#dosya3 ye tampondan yaz
pushl knum3
leal tampon2, %eax
pushl %eax
leal boyut1,%ebx
pushl (%ebx)
call _dosya_yaz
addl $12,%esp
#dosya4 arttir
leal tampon2,%eax
pushl %eax
leal tampon2,%eax
pushl %eax
leal boyut1,%ebx
pushl (%ebx)
pushl $50
call _direk_arttir
addl $16,%esp

#dosya4 ye tampondan yaz
pushl knum4
leal tampon2, %eax
pushl %eax
leal boyut1,%ebx
pushl (%ebx)
call _dosya_yaz
addl $12,%esp

#aslından kopyala
leal tampon,%ebx
movl %ebx,%esi
leal tampon3,%ebx
movl %ebx,%edi
leal boyut1,%ebx
movl (%ebx),%ecx
kopyala4:
movb (%esi),%dl
movb %dl,(%edi)
inc %esi
inc %edi
loop kopyala4

#dosya5 arttir
leal tampon3,%eax
pushl %eax
leal tampon3,%eax
pushl %eax
leal boyut1,%ebx
pushl (%ebx)
pushl $50
call _normlu_arttir
addl $16,%esp

#dosya5 ye tampondan yaz
pushl knum5
leal tampon3, %eax
pushl %eax
leal boyut1,%ebx
pushl (%ebx)
call _dosya_yaz
addl $12,%esp

#aslından kopyala
leal tampon,%ebx
movl %ebx,%esi
leal tampon3,%ebx
movl %ebx,%edi
leal boyut1,%ebx
movl (%ebx),%ecx
kopyala5:
movb (%esi),%dl
movb %dl,(%edi)
inc %esi
inc %edi
loop kopyala5

#dosya6 arttir
leal tampon3,%eax
pushl %eax
leal tampon3,%eax
pushl %eax
leal boyut1,%ebx
pushl (%ebx)
pushl $100
call _normlu_arttir
addl $16,%esp

#dosya6 ye tampondan yaz
pushl knum6
leal tampon3, %eax
pushl %eax
leal boyut1,%ebx
pushl (%ebx)
call _dosya_yaz
addl $12,%esp

#aslından kopyala
leal tampon,%ebx
movl %ebx,%esi
leal tampon3,%ebx
movl %ebx,%edi
leal boyut1,%ebx
movl (%ebx),%ecx
kopyala6:
movb (%esi),%dl
movb %dl,(%edi)
inc %esi
inc %edi
loop kopyala6

#dosya7 arttir
leal tampon3,%eax
pushl %eax
leal tampon3,%eax
pushl %eax
leal boyut1,%ebx
pushl (%ebx)
pushl $150
call _normlu_arttir
addl $16,%esp

#dosya7 ye tampondan yaz
pushl knum7
leal tampon3, %eax
pushl %eax
leal boyut1,%ebx
pushl (%ebx)
call _dosya_yaz
addl $12,%esp

#dosya1 i oku tampona yerlestir
oku2:
pushl knum1
leal tampon2, %eax
pushl %eax
pushl $40000
call _dosya_oku
addl $12,%esp
movl %eax,boyut1
cmp $0,%eax
je dosyalarikapat
leal tampon2,%ebx
movl %ebx,%esi
leal tampon,%ebx
movl %ebx,%edi
leal boyut1,%ebx
movl (%ebx),%ecx
kopyala3:
movb (%esi),%dl
movb %dl,(%edi)
inc %esi
inc %edi
loop kopyala3

cmp $0,%eax
jne veriyaz
dosyalarikapat:
#dosya1 i kapat
movl knum1,%ebx
call _dosya_kapat
#dosya2 yi kapat
movl knum2,%ebx
call _dosya_kapat
#dosya3 yi kapat
movl knum3,%ebx
call _dosya_kapat
#dosya4 yi kapat
movl knum4,%ebx
call _dosya_kapat
#dosya5 yi kapat
movl knum5,%ebx
call _dosya_kapat
#dosya6 yi kapat
movl knum6,%ebx
call _dosya_kapat
#dosya7 yi kapat
movl knum7,%ebx
call _dosya_kapat

cikis:
xorl %eax, %eax        # %eax = 0
incl %eax        # %eax = 1 system call _exit ()
xorl %ebx, %ebx    # %ebx = 0 normal program return code
int $0x80        # execute system call _exit ()

_yaz:   .type @function # ilk operand karakter dizisi, ikincisi uzunluk
push %ebp
movl %esp, %ebp
movl $4, %eax        # write () system call
movl $1, %ebx        # %ebx = 1, fd = stdout
movl 12(%ebp), %ecx    # string
movl 8(%ebp), %edx    # miktar
int $0x80
pop %ebp
ret

_dosya_ac: .type @function #operand dosya adı, ikinci oku/yaz; donus eax dosya knumarasi
pushl %ebp
movl %esp, %ebp
movl $5, %eax          # sys_open
movl 12(%ebp), %ebx    # dosyaadi
movl 8(%ebp), %ecx    # oku/yaz
int $0x80
popl %ebp
ret

_dosya_oku: .type @function # ilk operand knum, ikincisi tampon adresi, ucuncusu miktar; eax bitince 0
pushl %ebp
movl %esp, %ebp
movl $3,%eax
movl 16(%ebp), %ebx   #dosya knum
movl 12(%ebp), %ecx   #tampon
movl 8(%ebp), %edx    #miktar
int $0x80
popl %ebp
ret

_dosya_yaz: .type @function #ilk operand knum, ikincisi tampon adresi, ucuncusu miktar
pushl %ebp
movl %esp, %ebp
movl $4,%eax
movl 16(%ebp),%ebx    #dosya knum
movl 12(%ebp), %ecx   #tampon
movl 8(%ebp), %edx    #miktar
int $0x80
popl %ebp
ret

_dosya_kapat: .type @function #ilk operand knum
pushl %ebp
movl %esp, %ebp
movl $6, %eax         #kapat
movl 8(%ebp),%ebx     #knum
popl %ebp
ret

_dosya_yarat: .type @function #ilk operand isim
pushl %ebp
movl %esp, %ebp
movl $8, %eax         #yarat
movl 8(%ebp),%ebx     #isim
movl $0644,%ecx
popl %ebp
int $0x80
ret

_asciiye_donustur: .type @function #ilk operand adres, ikincisi hedef,ucuncu boyut: donus boyutu
pushl %ebp
movl %esp, %ebp
movl 16(%ebp),%esi
movl 12(%ebp),%edi
movl 8(%ebp),%ecx
movb $0x50,%al
movb %al,(%edi)
incl %edi
movb $0x32,%al
movb %al,(%edi)
incl %edi
movb $0x0a,%al
movb %al,(%edi)
incl %edi
don:
xorl %eax,%eax
movb (%esi),%al
movl $100,%ebx
div %bl
cmp $0,%al
jne ikinciv

xorl %eax,%eax
movb (%esi),%al
mov $10,%ebx
divb %bl
cmp $0,%al
je ucuncu
add $0x30,%al
movb %al,(%edi)
inc %edi
jmp ucuncu

ikinciv:
addb $0x30,%al
movb %al,(%edi)
incl %edi

xorl %eax,%eax
movb (%esi),%al
mov $10,%ebx
divb %bl
mulb %bl
mov $100,%ebx
divb %bl
xchg %al,%ah
mov $0,%ah
mov $10,%ebx
divb %bl
addb $0x30,%al
movb %al,(%edi)
incl %edi

ucuncu:
xorl %eax,%eax
movb (%esi),%al
movl $10,%ebx
div %bl
addb $0x30,%ah
movb %ah,(%edi)
incl %edi
incl %esi
movb $0x20,%ah
movb %ah,(%edi)
incl %edi

decl %ecx
jnz don

movl 12(%ebp),%ebx
movl %edi,%eax
subl %ebx,%eax
popl %ebp

ret

_direk_arttir: .type @function #ilk operand adres, ikincisi hedef, ucuncu kac tane oldugu, sonuncusu artirma
pushl %ebp
movl %esp, %ebp
movl 20(%ebp),%esi
movl 16(%ebp),%edi
movl 12(%ebp),%ecx
movl 8(%ebp),%edx

movl (%esi),%eax
movl %eax,(%edi)
ekle1:
xorl %eax,%eax
movb (%esi),%al
addl %edx,%eax
cmpl $255,%eax
jb devam1
movl $255,%eax
devam1:
movb %al,(%edi)
incl %edi
incl %esi
loop ekle1
popl %ebp
ret

_normlu_arttir: .type @function #ilk operand adres, ikincisi hedef, ucuncu kac tane oldugu, sonuncusu artirma
pushl %ebp
movl %esp, %ebp
movl 20(%ebp),%esi
movl 16(%ebp),%edi
movl 12(%ebp),%ecx
movl 8(%ebp),%ebx

movl (%esi),%ebx
movl %ebx,(%edi)
ekle2:
push %ecx
movl $255,%eax
movl 8(%ebp),%ebx
subl %ebx,%eax
xorl %ebx,%ebx
movb (%esi),%bl
mul %bl
movl $255,%ecx
div %cl
movl 8(%ebp),%ebx
add %bl,%al
movb %al,(%edi)
incl %edi
incl %esi
pop %ecx
loop ekle2
popl %ebp
ret

_tampondan_sayiya: .type @function # ilk operand tampon adresi ikinci yazilacak tampon adresi geri donus kac tane yazildigi
pushl %ebp
movl %esp,%ebp
movl 8(%ebp),%eax
movl %eax,%edi
xorl %ebx,%ebx
donustur:
pushl %ebx
pushl %edi
pushl 12(%ebp)
call _sayi_al
popl %ecx
movl %ecx,12(%ebp)
popl %edi
popl %ebx
cmp $256,%eax
je bitir_ts
movl %eax,(%edi)
incl %edi
incl %ebx
jmp donustur

movl %ebx,%eax
bitir_ts:
popl %ebp
ret

_sayi_al: .type @function # ilk operand kalinan adres (degisiyor)

pushl %ebp
movl %esp, %ebp
leal aski,%edi
movb $0x30,(%edi)
inc %edi
movb $0x30,(%edi)
inc %edi
movb $0x30,(%edi)
inc %edi
movb $0x30,(%edi)
movb $0x30,(%edi)
inc %edi
movb $0x30,(%edi)
inc %edi
movb $0x30,(%edi)
inc %edi
movb $0x30,(%edi)
leal aski,%edi
addl $4,%edi

#sayiyla karsilasana kadar devam

#ilk sayiyi aliyoruz
mov 8(%ebp),%esi
enter:
movb (%esi),%dl
#bosluk mu?
cmpb $0x0a,%dl
jne bosluk
#unutma!kaldigimiz yer donmeli
incl %esi
jmp enter

bosluk:
cmpb $0x020,%dl
jne endof
incl %esi
jmp enter
endof:
cmpb $0,%dl
jne sayi
movl $256,%eax
jmp bitir
#sayiyi almaya baslayabiliriz
sayi:
movb %dl,(%edi)
incl %edi
incl %esi
movb (%esi),%dl
incl 8(%ebp)

enter2:
cmpb $0x0a,%dl
jne bosluk2
jmp hesapla
bosluk2:
cmpb $0x20,%dl
jne endof2
jmp hesapla
endof2:
cmpb $0,%dl
jne sayi
movl $256,%eax
jmp bitir
jmp sayi
#yigina attigimiz stringi int e donusturuyoruz
hesapla:
xorl %edx,%edx
movl $0,(%edi)
decl %edi

movb (%edi),%al
subb $0x30,%al
movb %al,%dl
decl %edi

movb (%edi),%al
subb $0x30,%al
movb $10,%cl
mulb %cl
addb %al,%dl
decl %edi

movb (%edi),%al
subb $0x30,%al
movb $100,%cl
mulb %cl
addb %al,%dl
#geri donus
mov %edx,%eax

bitir:
#kalinan adres
mov %esi,8(%ebp)
popl %ebp

ret

Bu yazı toplamda 2418, bugün ise 0 kez görüntülenmiş

6 Comments
  • http://yildirim.isadamlari.org M. Salih YILDIRIM

    İyi misin koçum?
    insanoğlu kullanasın diye orta ve yüksek seviyeli diller icat etmiş :S

  • huseyinalb

    ne demişler bir musibet bin nasihatten daha iyidir 😀 evet artık orta ve yüksek seviyeli dillerin neden yapıldığını daha iyi biliyorum 😀

  • http://asd.com hönk

    İyi güzel de neden assembly ile yazdın? Sen manyak mısın?
    Bence en yakın zamanda bir psikoloğa görün :) Allam ne insanlar var yaa!

  • mnemonick

    hüseyin be, harbiden yazdın mı o kadar kodu?

  • huseyinalb

    Evet 😀 Baya uğraştırdı

  • hort

    Delikli kağıtlarla yazılmış versiyonunu da bekliyoruz ….