11.9. Komut satırıArgümanları

Yukarıda yazmışolduğumuz hex isimli program eğer girişçıkış dosyalarının isimlerini içeren komut satırıargümanlarıile çağırılabiliyor olsaydıçok daha kullanışlıolacaktı. Fakat bu komutlara nasıl ulaşabiliriz ?

Bir UNIX programıbaşlamadan önce bazıverileri yığınına kaydeder.Bundan sonra _start isimli etiketin bulunduğu yere zıplar.Evet fonksiyon çağrısıdeğil sadece zıplama.Bu da demek oluyor ki bu verilere [esp+offset] ile yada basitçe (pop) işlemi ile rahatlıkla ulaşılabilir.

Yığının en üstünde bulunan sayıgenellikle 'argc' olarak adlandırılan argüman sayısıdır.

Bundan sonra gelenler ise argümanların değerleridir.Genel olarak 'argv' olarak adlandırılır ve argv[0] dan argv[argc -1] e kadar gider.Bunlar gerçek argüman değillerdir. Fakat argümanların nerede olduğunu gösteren işaretçilerdir. Argümanların kendisi NULL ile bitirilmişstringlerdir.

argv listesinin sonunda NULL işaretçisi yani 0 bulunur.Dahasıda var ama bizim için şimdilik bu kadar yeter.

Not: Eğer MS-DOS programlama ortamından geçişyaptıiseniz ana farklılık her bir argümana ayrıbir string atanmasıdır. İkinci olarak pratik olarak argüman sayısında herhangi bir sınırlama söz konusu değildir.

Bu bilgi ile donandıktan sonra hex.asm'nin yeni versiyonunu yapmaya neredeyse hazırız.Ama öncelikle system.inc dosyasına bir iki satır kod ekleyeceğiz.

İlk olarak iki yeni sistem çağrınumarasınıdosyamıza eklemeliyiz.

%define SYS_open 5 %define SYS_close 6

Bundan sonra iki yeni makroyu da dosyanın sonuna yazıyoruz.

sys.open:
sys.close:
[etc...]
	int	80h
	ret

İşte şimdi kaynak kodumuzun değiştirilmişhali :

sys.exit:
sys.close:
[etc... one-parameter functions]
	push	ebx
	mov	ebx, [esp+12]
	int	80h
	pop	ebx
	jmp	sys.return
...
sys.return:
	or	eax, eax
	js	sys.err
	clc
	ret
sys.err:
	neg	eax
	stc
	ret

Programımızın .data bölümünde fd.in ve fd.out isimli iki değişken kullanarak girdi çıktıdosyalarımızın numalarınıtuttuk.

.text bölümünde standart girişve çıkış olan stdin ve stdout yerine [fd.in] ve [fd.out] ile kendi girişçıkışdosyalarımızıkullandık.Hata durumunda işlenecek kodu _start etiketinden önce tanımladık böylece hatanın oluşabileceği yere daha yakın olacaktır.

Doğal olarak programımız yine _start etiketinden başlıyor.İlk olarak yığından argc ve argv[0] değişkenlerini siliyoruz : Şu anda bizi ilgilendirmiyorlar.

Argv[1]' i ECX yazmacına çıkarıyoruz. Çünkü bu yazmaç işaretçiler için daha uygun ve en son NULL işaretçisi kontrol ederken

      jecxz
komutunu kullanacağız.Argümanıaldıktan sonra eğer NULL değilse dosyayıaçmayıdeniyor eğer açamaz ise önceki programımızda olduğu gibi
 stdin
ile girdi işlemine devam ediyor ve çıktıyı
 stdout
'a yapıyor.Eğer girdi dosyasının açılması sırasında bir hata oluşur ise hata karşılama(error handler) kodunu çalıştırır.

Programımızın geri kalan kısmıesikisi gibi sadece bir farkla : Programdan çıkmadan önce [fd.in] ve [fd.out] dosyalarınıkapatıyoruz.

Çalıştırılabilir dosyamız 768 byte gibi devasa (!) bir yer kaplıyor.

Hala programıgeliştiremez miyiz ? Elbette geliştirebiliriz , bütün programlar geliştirilebilir. Burada örnek olacak bir kaç fikir yazalım :