2011-08-01 22 views
5

muhtemelen bazı güzel örneklerle bazı referans ama iyi bir tane, gerekir. İhtiyacım var çünkü NASM assembler'ı kullanarak montajda kod yazmaya başladım. Bu başvuru vardır: oldukça güzel ve kullanışlıİyi referanslar

http://bluemaster.iu.hio.no/edu/dark/lin-asm/syscalls.html

ancak diğer kayıtlar alanları açıklamıyor çünkü kısıtlamalar bir çok var. Örneğin, yazma syscallını kullanıyorum, EAX kaydına 1 koymam gerektiğini biliyorum ve ECX muhtemelen dizgeye bir işaretçi, ancak EBX ve EDX hakkında ne? Bunu açıklamak isterim ki, EBX girişi belirler (stdin için 0, başka bir şey için 1, vs.) ve EDX girilecek dizenin uzunluğudur, vb. Umarım ne istediğimi anlarsın. Böyle bir materyal bulamadım bu yüzden burada yazıyorum. Şimdiden teşekkürler. Eğer (ikinci paragrafta da anlaşılacağı gibi) bu web sayfasını indirmek ve çekirdek kaynaklarını indirirseniz

cevap

0

, siz "Kaynak" sütununda bağlantıları tıklayın ve sistem çağrıları uygulayan kaynak dosyasının doğrudan gidebilirsiniz. Her bir parametrenin ne için kullanıldığını görmek için C imzalarını okuyabilirsiniz.

Sadece hızlı bir başvuru arıyorsanız, bu sistem çağrılarının her biri, sys_ eksi ile aynı ada sahip bir C kitaplığı arabirimine sahiptir. Yani, örneğin, sys_lseek için parametreleri hakkında bilgi almak için man 2 lseek kontrol edebilir:

%ebx   %ecx %edx 
unsigned int off_t unsigned int 
+0

Tabii ki, her birini Google'da veya uygulama için kaynak kodlu aramada arama yapsanız bile, nasıl kullanıldığına dair doğrudan örnekler bulabilirsiniz. Mesajımın amacı, arama ve analiz etmeyi güzel bir hile sayfasıyla atlamak. Teşekkürler. –

11
: Gördüğünüz gibi, parametreler HTML tablosundan olanlara uyuyor,

off_t lseek(int fd, off_t offset, int whence); 

Linux'taki standart programlama dili C'dir. Bu nedenle, sistem çağrılarının en iyi açıklamaları, bunları çağrılacak C işlevleri olarak gösterecektir. Bir C işlevi olarak açıklamaları ve montajda gerçek sistem çağrısına nasıl haritalanacağı bilgisi verildiğinde, kolayca istediğiniz herhangi bir sistem çağrısını kullanabilirsiniz. Onlar C programcısı görünecektir gibi tüm sistem çağrıları için

Öncelikle, bir başvuru gerekiyor. En iyi bildiğim, Linux man-pages project, özellikle system calls bölümüdür.

sizin söz konusu biridir, çünkü o, bir örnek olarak write sistem çağrısını ele alalım. Gördüğünüz gibi, ilk parametre, genellikle open sistem çağrısı tarafından döndürülen bir dosya tanıtıcısı olan bir işaretli tamsayıdır. Bu dosya tanıtıcıları, genellikle ilk üç dosya tanıtıcısı için olduğu gibi (0 = stdin, 1 = stdout, 2 = stderr), ana işleminizden miras alınmış olabilir. İkinci parametre, bir arabelleğin işaretçisidir ve üçüncü parametre, arabellek boyutudur (işaretsiz bir tam sayı olarak). Son olarak, işlev yazılan bayt sayısı veya bir hata için negatif bir sayı olan bir işaretli tamsayı döndürür.

Şimdi, nasıl gerçek sistem çağrısına bu haritaya? 32-bit x86'da bir sistem çağrısı yapmanın birçok yolu vardır (büyük olasılıkla kullandığınız, kayıt isimlerine bağlı olarak); 64-bit x86'da tamamen farklı olmasına dikkat edin (32-bit modda bir araya getirdiğinizden ve 32-bit bir yürütülebilir dosyayı bağladığınızdan emin olun; aksi halde, hataların nasıl ters gidebileceğine dair bir örnek için bkz. this question). 32-bit x86'daki en eski, en basit ve en yavaşı, int $0x80 yöntemidir.

int $0x80 yöntemi için, sen %eax sistem çağrı numarasını koymak ve parametreler %ebx, %ecx, %edx, %esi, %edi ve %ebp, bu sırayla. Ardından, int $0x80 numaralı telefonu arayın ve sistem çağrısından dönüş değeri %eax üzerindeyken. Bu dönüş değerinin, referansın söylediklerinden farklı olduğunu unutmayın; referans C kütüphanesinin nasıl geri getireceğini gösterir, ancak sistem çağrısı -errno hata ile döner (örneğin -EINVAL). C kitaplığı bu durumu errno'a taşır ve bu durumda -1 döndürür. Daha fazla ayrıntı için bkz. syscalls(2) ve intro(2).

Yani, write örnekte, (%eax yılında write sistem çağrı numarası, %ebx ilk parametre (dosya tanıtıcı numarası), %ecx ikinci parametre (dize işaretçisi) ve üçüncü parametre koyardı dizgenin uzunluğu) %edx. Sistem çağrısı %eax'da yazılan bayt sayısı veya reddedilen hata numarası olarak geri dönecektir (dönüş değeri -1 ve -4095 arasındaysa, bu bir negatif hata numarasıdır).

Son olarak, sistem çağrı numaralarını nasıl buluyorsunuz? Bunlar /usr/include/linux/unistd.h adresinde bulunabilir. Benim sistemimde, bu sadece /usr/include/asm/unistd_32.h içerir /usr/include/asm/unistd.h içerir, bu yüzden sayılar vardır (write için, __NR_write4 olduğunu görebilirsiniz). Aynı durum, /usr/include/linux/errno.h (sistemimde, ilk harfleri /usr/include/asm-generic/errno-base.h'da ve geri kalanını /usr/include/asm-generic/errno.h numaralı telefonda bulduktan sonra dahil olmak üzere) gelen hata sayıları için de geçerlidir. Diğer sabitleri veya yapıları kullanan sistem çağrıları için, belgeleri, ilgili tanımları bulmak için hangi başlıklara bakmanız gerektiğini söyler. Dediğim gibi


Şimdi, int $0x80 en eski ve en yavaş yöntemdir. Daha yeni işlemciler, daha hızlı olan özel sistem çağrı yönergelerine sahiptir. Bunları kullanmak için, çekirdek, sanal bir dinamik paylaşımlı nesneyi (vDSO; paylaşılan bir kitaplığa benzer, ancak yalnızca bellekte), donanımınız için mevcut en iyi yöntemi kullanarak sistem çağrısı yapmak üzere çağıran bir işlevle kullanılabilir hale getirir. Ayrıca, sistem çağrısı yapmak zorunda kalmadan, şimdiki zamanı elde etmek için özel işlevler ve birkaç şey daha sunar. Elbette, dinamik bir bağlayıcı kullanmıyorsanız kullanmak biraz daha zordur.

Başka bir eski yöntem de vsyscall, vDSO'a benzer, ancak sabit bir adreste tek bir sayfa kullanır. Bu yöntem kullanımdan kaldırılır, en son çekirdeği kullanıyorsanız, daha yeni çekirdekler üzerinde önyükleme sırasında devre dışı bırakılabilir ve gelecekte kaldırılabiliyorsa, sistem günlüğüne uyarılarla sonuçlanır. Bunu kullanma.

+0

Bu, gördüğüm en iyi cevaplardan biri. –

İlgili konular