Montaj - Hızlı Kılavuz
Assembly Dili nedir?
Her kişisel bilgisayar, bilgisayarın aritmetik, mantıksal ve kontrol faaliyetlerini yöneten bir mikroişlemciye sahiptir.
Her işlemci ailesinin klavyeden girdi alma, ekranda bilgi görüntüleme ve çeşitli diğer işleri gerçekleştirme gibi çeşitli işlemlerin gerçekleştirilmesi için kendi yönergeleri vardır. Bu talimat setine 'makine dili talimatları' adı verilir.
Bir işlemci, yalnızca 1'ler ve 0'ların dizeleri olan makine dili talimatlarını anlar. Bununla birlikte, makine dili, yazılım geliştirmede kullanmak için çok belirsiz ve karmaşıktır. Bu nedenle, düşük seviyeli montaj dili, sembolik kodda ve daha anlaşılır bir biçimde çeşitli talimatları temsil eden belirli bir işlemci ailesi için tasarlanmıştır.
Assembly Dilinin Avantajları
Birleştirme dili anlayışına sahip olmak, bir kişinin farkına varmasını sağlar:
- Programlar işletim sistemi, işlemci ve BIOS ile nasıl arayüz oluşturur;
- Verilerin bellekte ve diğer harici cihazlarda nasıl temsil edildiği;
- İşlemci talimata nasıl erişir ve onu yürütür;
- Talimatların verilere nasıl eriştiği ve işlediği;
- Bir programın harici cihazlara nasıl eriştiği.
Assembly dilini kullanmanın diğer avantajları şunlardır:
Daha az bellek ve yürütme süresi gerektirir;
Donanıma özgü karmaşık işlere daha kolay bir şekilde izin verir;
Zaman açısından kritik işler için uygundur;
Kesme hizmeti rutinlerini ve diğer bellekte yerleşik programları yazmak için en uygun olanıdır.
PC Donanımının Temel Özellikleri
Bir bilgisayarın ana dahili donanımı işlemci, bellek ve kayıtlardan oluşur. Kayıtlar, veri ve adres tutan işlemci bileşenleridir. Bir programı yürütmek için, sistem onu harici cihazdan dahili belleğe kopyalar. İşlemci, program talimatlarını yürütür.
Bilgisayar depolamasının temel birimi birazdır; AÇIK (1) veya KAPALI (0) olabilir ve 8 ilgili bitlik bir grup modern bilgisayarların çoğunda bir bayt oluşturur.
Dolayısıyla, eşlik biti bir bayttaki bit sayısını tek yapmak için kullanılır. Eşitlik eşitse, sistem, donanım hatası veya elektriksel bozukluktan kaynaklanmış olabilecek bir eşlik hatası (nadir de olsa) olduğunu varsayar.
İşlemci aşağıdaki veri boyutlarını destekler -
- Word: 2 baytlık bir veri öğesi
- Doubleword: 4 baytlık (32 bit) veri öğesi
- Quadword: 8 baytlık (64 bit) veri öğesi
- Paragraf: 16 baytlık (128 bit) alan
- Kilobayt: 1024 bayt
- Megabayt: 1.048.576 bayt
İkili Sayı Sistemi
Her sayı sistemi konumsal notasyonu kullanır, yani bir rakamın yazıldığı her konum farklı bir konumsal değere sahiptir. Her pozisyon, ikili sayı sistemi için 2 olan tabanın gücüdür ve bu güçler 0'dan başlayıp 1 artar.
Aşağıdaki tablo, tüm bitlerin AÇIK olarak ayarlandığı 8 bitlik bir ikili sayı için konumsal değerleri gösterir.
Bit değeri | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
---|---|---|---|---|---|---|---|---|
Baz 2'nin gücü olarak konum değeri | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
Bit numarası | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
İkili bir sayının değeri, 1 bitin varlığına ve bunların konumsal değerine bağlıdır. Yani, belirli bir ikili sayının değeri -
1 + 2 + 4 + 8 +16 + 32 + 64 + 128 = 255
2 8 - 1 ile aynıdır .
Onaltılık Sayı Sistemi
Onaltılık sayı sistemi 16 tabanını kullanır. Bu sistemdeki rakamlar 0 ile 15 arasındadır. Geleneksel olarak, 10 ile 15 arasındaki ondalık değerlere karşılık gelen onaltılık basamakları temsil etmek için A'dan F'ye kadar olan harfler kullanılır.
Hesaplamada onaltılık sayılar, uzun ikili gösterimleri kısaltmak için kullanılır. Temel olarak, onaltılık sayı sistemi, her baytı ikiye bölerek ve her yarım baytın değerini ifade ederek ikili bir veriyi temsil eder. Aşağıdaki tablo ondalık, ikili ve onaltılık eşdeğerleri sağlar -
Ondalık sayı | İkili gösterim | Onaltılık gösterim |
---|---|---|
0 | 0 | 0 |
1 | 1 | 1 |
2 | 10 | 2 |
3 | 11 | 3 |
4 | 100 | 4 |
5 | 101 | 5 |
6 | 110 | 6 |
7 | 111 | 7 |
8 | 1000 | 8 |
9 | 1001 | 9 |
10 | 1010 | Bir |
11 | 1011 | B |
12 | 1100 | C |
13 | 1101 | D |
14 | 1110 | E |
15 | 1111 | F |
İkili bir sayıyı onaltılık eşdeğerine dönüştürmek için, onu sağdan başlayarak her biri 4 ardışık gruptan oluşan gruplara ayırın ve bu grupları onaltılık sayının karşılık gelen rakamları üzerine yazın.
Example - Binary sayı 1000 1100 1101 0001 onaltılık - 8CD1'e eşdeğerdir
Onaltılık bir sayıyı ikiliye dönüştürmek için, her onaltılık basamağı 4 basamaklı ikili eşdeğerine yazın.
Example - Onaltılık sayı FAD8 ikiliye eşdeğerdir - 1111 1010 1101 1000
İkili Aritmetik
Aşağıdaki tablo, ikili toplama için dört basit kuralı göstermektedir -
(ben) | (ii) | (iii) | (iv) |
---|---|---|---|
1 | |||
0 | 1 | 1 | 1 |
+0 | +0 | +1 | +1 |
= 0 | = 1 | = 10 | = 11 |
Kurallar (iii) ve (iv), bir sonraki sol pozisyona 1-bit taşınmasını gösterir.
Example
Ondalık | İkili |
---|---|
60 | 00111100 |
+42 | 00101010 |
102 | 01100110 |
Negatif bir ikili değer şu şekilde ifade edilir: two's complement notation. Bu kurala göre ikili bir sayıyı negatif değerine çevirmek, bit değerlerini ters çevirip 1 eklemektir .
Example
53 numara | 00110101 |
Bitleri ters çevirin | 11001010 |
1 ekle | 0000000 1 |
-53 numara | 11001011 |
Bir değeri diğerinden çıkarmak için, çıkarılan sayıyı ikinin tümleyen biçimine dönüştürün ve sayıları ekleyin .
Example
53'ten 42 çıkar
53 numara | 00110101 |
42 numara | 00101010 |
42 bitlerini ters çevir | 11010101 |
1 ekle | 0000000 1 |
Sayı -42 | 11010110 |
53 - 42 = 11 | 00001011 |
Son 1 bitin taşması kaybolur.
Bellekteki Verileri Adresleme
İşlemcinin talimatların uygulanmasını kontrol ettiği süreç, fetch-decode-execute cycle ya da execution cycle. Üç sürekli adımdan oluşur -
- Talimatın bellekten alınması
- Talimatı çözme veya tanımlama
- Talimatı yerine getirmek
İşlemci aynı anda bir veya daha fazla bayt belleğe erişebilir. 0725H onaltılık bir sayıyı düşünelim. Bu numara, iki bayt bellek gerektirecektir. Yüksek sıralı bayt veya en önemli bayt 07 ve düşük sıralı bayt 25'tir.
İşlemci verileri ters bayt dizisinde depolar, yani düşük sıralı bir bayt düşük bellek adresinde ve yüksek sıralı bayt yüksek bellek adresinde depolanır. Dolayısıyla, işlemci 0725H değerini kayıttan belleğe getirirse, önce 25'i alt bellek adresine ve 07'yi bir sonraki bellek adresine aktaracaktır.
x: hafıza adresi
İşlemci, hafızadan kayıt için sayısal verileri aldığında, baytları yeniden tersine çevirir. İki tür hafıza adresi vardır -
Mutlak adres - belirli bir konumun doğrudan referansı.
Segment adresi (veya ofset) - ofset değeri ile bir bellek segmentinin başlangıç adresi.
Yerel Ortam Kurulumu
Assembly dili, komut setine ve işlemcinin mimarisine bağlıdır. Bu eğitimde, Pentium gibi Intel-32 işlemcilere odaklanıyoruz. Bu öğreticiyi takip etmek için ihtiyacınız olacak -
- Bir IBM PC veya herhangi bir eşdeğer uyumlu bilgisayar
- Linux işletim sisteminin bir kopyası
- NASM assembler programının bir kopyası
Pek çok iyi derleyici programı vardır, örneğin:
- Microsoft Assembler (MASM)
- Borland Turbo Birleştirici (TASM)
- GNU birleştirici (GAS)
NASM derleyicisini olduğu gibi kullanacağız -
- Bedava. Çeşitli web kaynaklarından indirebilirsiniz.
- İyi belgelenmiş ve internette çok fazla bilgi alacaksınız.
- Hem Linux hem de Windows'ta kullanılabilir.
NASM Kurulumu
Linux'u kurarken "Geliştirme Araçları" nı seçerseniz, Linux işletim sistemiyle birlikte NASM'yi kurabilir ve ayrı olarak indirip kurmanıza gerek kalmaz. Halihazırda NASM'nin kurulu olup olmadığını kontrol etmek için aşağıdaki adımları izleyin -
Bir Linux terminali açın.
Tür whereis nasm ve ENTER tuşuna basın.
Zaten yüklenmişse, nasm: / usr / bin / nasm gibi bir satır görünür. Aksi takdirde, sadece nasm göreceksiniz :, o zaman NASM'yi kurmanız gerekir.
NASM'yi kurmak için aşağıdaki adımları izleyin -
En son sürüm için netwide assembler (NASM) web sitesini kontrol edin .
Arşivdeki NASM sürüm numarasının
nasm-X.XX.ta.gz
bulunduğu Linux kaynak arşivini indirinX.XX
.Arşivi, bir alt dizin oluşturan bir dizine açın
nasm-X. XX
.cd
nasm-X.XX
ve yazın./configure. Bu kabuk betiği, Makefiles'ı buna göre kullanmak ve kurmak için en iyi C derleyicisini bulacaktır.Tür make nasm ve ndisasm ikili dosyalarını oluşturmak için.
Tür make install nasm ve ndisasm'ı / usr / local / bin içine kurmak ve man sayfalarını kurmak için.
Bu, sisteminize NASM'yi kurmalıdır. Alternatif olarak, Fedora Linux için bir RPM dağıtımı kullanabilirsiniz. Bu sürümün kurulumu daha basittir, sadece RPM dosyasına çift tıklayın.
Bir montaj programı üç bölüme ayrılabilir -
data Bölüm,
bss bölümü ve
text Bölüm.
veri bölümü
databölümü, başlatılmış verileri veya sabitleri bildirmek için kullanılır. Bu veriler çalışma zamanında değişmez. Bu bölümde çeşitli sabit değerler, dosya adları veya arabellek boyutu vb. Bildirebilirsiniz.
Veri bölümünü bildirmek için sözdizimi -
section.data
bss Bölüm
bssbölümü değişkenleri bildirmek için kullanılır. Bss bölümünü bildirmek için sözdizimi -
section.bss
metin bölüm
textbölümü asıl kodu saklamak için kullanılır. Bu bölüm beyanname ile başlamalıdırglobal _start, çekirdeğe programın nerede başladığını söyler.
Metin bölümünü bildirmek için sözdizimi -
section.text
global _start
_start:
Yorumlar
Assembly dili yorumu bir noktalı virgülle (;) başlar. Boş dahil herhangi bir yazdırılabilir karakter içerebilir. Kendi başına bir satırda görünebilir, örneğin -
; This program displays a message on screen
veya aynı satırda bir talimatla birlikte, örneğin -
add eax, ebx ; adds ebx to eax
Assembly Dili Beyanları
Assembly dili programları üç tür ifadeden oluşur -
- Yürütülebilir talimatlar veya talimatlar,
- Assembler yönergeleri veya sahte operasyonlar ve
- Macros.
executable instructions ya da sadece instructionsişlemciye ne yapması gerektiğini söyleyin. Her talimat biroperation code(opcode). Her yürütülebilir talimat, bir makine dili talimatı üretir.
assembler directives veya pseudo-opsmontajcıya montaj sürecinin çeşitli yönlerini anlatın. Bunlar yürütülemez ve makine dili talimatları oluşturmaz.
Macros temelde bir metin ikame mekanizmasıdır.
Assembly Dili İfadelerinin Sözdizimi
Assembly dili ifadeleri her satıra bir ifade girilir. Her ifade aşağıdaki biçimi izler -
[label] mnemonic [operands] [;comment]
Köşeli parantez içindeki alanlar isteğe bağlıdır. Temel bir komutun iki bölümü vardır, birincisi yürütülecek komutun (veya anımsatıcı) adı ve ikincisi komutun işlenenleri veya parametreleridir.
Aşağıda, tipik birleştirme dili ifadelerinin bazı örnekleri verilmiştir -
INC COUNT ; Increment the memory variable COUNT
MOV TOTAL, 48 ; Transfer the value 48 in the
; memory variable TOTAL
ADD AH, BH ; Add the content of the
; BH register into the AH register
AND MASK1, 128 ; Perform AND operation on the
; variable MASK1 and 128
ADD MARKS, 10 ; Add 10 to the variable MARKS
MOV AL, 10 ; Transfer the value 10 to the AL register
Assembly'de Merhaba Dünya Programı
Aşağıdaki montaj dili kodu, ekranda 'Merhaba Dünya' dizesini görüntüler -
section .text
global _start ;must be declared for linker (ld)
_start: ;tells linker entry point
mov edx,len ;message length
mov ecx,msg ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
msg db 'Hello, world!', 0xa ;string to be printed
len equ $ - msg ;length of the string
Yukarıdaki kod derlendiğinde ve yürütüldüğünde, aşağıdaki sonucu verir -
Hello, world!
NASM'de Bir Montaj Programını Derleme ve Bağlama
Yolunu ayarladığınızdan emin olun. nasm ve ldPATH ortam değişkeninizdeki ikili dosyalar. Şimdi, yukarıdaki programı derlemek ve bağlamak için aşağıdaki adımları izleyin -
Bir metin düzenleyici kullanarak yukarıdaki kodu yazın ve hello.asm olarak kaydedin.
Kaydettiğiniz yerle aynı dizinde olduğunuzdan emin olun hello.asm.
Programı oluşturmak için yazın nasm -f elf hello.asm
Herhangi bir hata varsa, bu aşamada size sorulacaktır. Aksi takdirde, programınızın bir nesne dosyasıhello.o yaratılacak.
Nesne dosyasını bağlamak ve merhaba adlı bir yürütülebilir dosya oluşturmak için şunu yazın: ld -m elf_i386 -s -o hello hello.o
Programı yazarak yürütün ./hello
Her şeyi doğru yaptıysanız, 'Merhaba dünya!' ekranda.
Bir montaj programının üç bölümünü daha önce tartışmıştık. Bu bölümler aynı zamanda çeşitli bellek bölümlerini de temsil eder.
İlginç bir şekilde, bölüm anahtar kelimesini segment ile değiştirirseniz, aynı sonucu alırsınız. Aşağıdaki kodu deneyin -
segment .text ;code segment
global _start ;must be declared for linker
_start: ;tell linker entry point
mov edx,len ;message length
mov ecx,msg ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
segment .data ;data segment
msg db 'Hello, world!',0xa ;our dear string
len equ $ - msg ;length of our dear string
Yukarıdaki kod derlendiğinde ve yürütüldüğünde, aşağıdaki sonucu verir -
Hello, world!
Bellek Bölümleri
Bölümlere ayrılmış bellek modeli, sistem belleğini, bölüm kayıtlarında bulunan işaretçiler tarafından referans verilen bağımsız bölüm gruplarına böler. Her bölüm, belirli bir veri türünü içermek için kullanılır. Bir bölüm komut kodlarını içermek için kullanılır, başka bir bölüm veri elemanlarını depolar ve üçüncü bölüm program yığınını tutar.
Yukarıdaki tartışmanın ışığında, çeşitli bellek bölümlerini şu şekilde belirleyebiliriz:
Data segment - tarafından temsil edilir .data bölüm ve .bss. .Data bölümü, program için veri öğelerinin depolandığı bellek bölgesini bildirmek için kullanılır. Bu bölüm, veri öğeleri bildirildikten sonra genişletilemez ve program boyunca sabit kalır.
.Bss bölümü ayrıca programda daha sonra bildirilecek veriler için arabellekleri içeren statik bir bellek bölümüdür. Bu tampon bellek sıfır doludur.
Code segment - tarafından temsil edilir .textBölüm. Bu, talimat kodlarını saklayan bellekte bir alanı tanımlar. Bu aynı zamanda sabit bir alandır.
Stack - Bu segment, program içindeki işlevlere ve prosedürlere aktarılan veri değerlerini içerir.
İşlemci işlemleri çoğunlukla verilerin işlenmesini içerir. Bu veriler hafızada saklanabilir ve buradan erişilebilir. Bununla birlikte, verilerin bellekten okunması ve belleğe depolanması, veri talebinin kontrol veriyolu üzerinden ve bellek depolama birimine gönderilmesi ve verilerin aynı kanaldan alınması gibi karmaşık süreçleri içerdiğinden işlemciyi yavaşlatır.
İşlemci işlemlerini hızlandırmak için işlemci, adı verilen bazı dahili bellek depolama konumları içerir. registers.
Kayıtlar, belleğe erişmek zorunda kalmadan işlenmek üzere veri öğelerini depolar. İşlemci yongasında sınırlı sayıda yazmaç bulunur.
İşlemci Kayıtları
IA-32 mimarisinde on adet 32-bit ve altı adet 16-bit işlemci kaydı vardır. Kayıtlar üç kategoriye ayrılmıştır -
- Genel kayıtlar,
- Kontrol kayıtları ve
- Segment kayıtları.
Genel kayıtlar ayrıca aşağıdaki gruplara ayrılmıştır -
- Veri kayıtları,
- İşaretçi kayıtları ve
- Dizin kayıtları.
Veri Kayıtları
Aritmetik, mantıksal ve diğer işlemler için dört adet 32 bit veri kaydı kullanılır. Bu 32 bitlik yazmaçlar üç şekilde kullanılabilir -
Tam 32 bit veri kayıtları olarak: EAX, EBX, ECX, EDX.
32 bitlik kayıtların alt yarısı, dört 16 bitlik veri kaydı olarak kullanılabilir: AX, BX, CX ve DX.
Yukarıda bahsedilen dört 16-bitlik yazmaçların alt ve üst yarıları sekiz 8-bit veri yazmaçları olarak kullanılabilir: AH, AL, BH, BL, CH, CL, DH ve DL.
Bu veri kayıtlarından bazıları aritmetik işlemlerde özel kullanıma sahiptir.
AX is the primary accumulator; giriş / çıkışta ve çoğu aritmetik komutta kullanılır. Örneğin, çarpma işleminde, bir işlenen, işlenenin boyutuna göre EAX veya AX veya AL yazmacında saklanır.
BX is known as the base register, endeksli adreslemede kullanılabileceği için.
CX is known as the count registerECX olarak, CX kayıtları döngü sayısını yinelemeli işlemlerde depolar.
DX is known as the data register. Ayrıca giriş / çıkış işlemlerinde de kullanılır. Ayrıca, büyük değerler içeren çarpma ve bölme işlemleri için DX ile birlikte AX yazmacıyla birlikte kullanılır.
İşaretçi Kayıtları
İşaretçi kayıtları, 32 bitlik EIP, ESP ve EBP kayıtları ve bunlara karşılık gelen 16 bitlik sağ kısımlar IP, SP ve BP'dir. İşaretçi kayıtlarının üç kategorisi vardır -
Instruction Pointer (IP)- 16 bitlik IP kaydı, yürütülecek bir sonraki komutun ofset adresini saklar. CS yazmacıyla ilişkili IP (CS: IP olarak), kod segmentindeki mevcut talimatın tam adresini verir.
Stack Pointer (SP)- 16 bitlik SP kaydı, program yığını içinde ofset değerini sağlar. SS yazmacı (SS: SP) ile ilişkili SP, program yığını içindeki verilerin veya adresin mevcut konumunu ifade eder.
Base Pointer (BP)- 16 bitlik BP kaydı, esas olarak bir alt yordama geçirilen parametre değişkenlerinin referans alınmasına yardımcı olur. SS yazmacındaki adres, parametrenin konumunu elde etmek için BP'deki ofset ile birleştirilir. BP ayrıca özel adresleme için temel kayıt olarak DI ve SI ile birleştirilebilir.
Dizin Kayıtları
32 bitlik dizin kayıtları, ESI ve EDI ve bunların 16 bitlik en sağdaki kısımları. SI ve DI, indeksli adresleme için kullanılır ve bazen toplama ve çıkarma işlemlerinde kullanılır. İki dizi dizin işaretçisi vardır -
Source Index (SI) - String işlemleri için kaynak indeks olarak kullanılır.
Destination Index (DI) - String işlemleri için hedef indeks olarak kullanılır.
Kontrol Kayıtları
32-bitlik talimat işaretçisi yazmacı ve 32-bit bayrak yazmacı birleştirilen kontrol kayıtları olarak kabul edilir.
Çoğu talimat karşılaştırmaları ve matematiksel hesaplamaları içerir ve bayrakların durumunu değiştirir ve diğer bazı koşullu talimatlar, kontrol akışını başka bir konuma götürmek için bu durum bayraklarının değerini test eder.
Ortak bayrak bitleri şunlardır:
Overflow Flag (OF) - İmzalı bir aritmetik işlemden sonra yüksek dereceli bir veri bitinin (en soldaki bit) taşmasını gösterir.
Direction Flag (DF)- Dizi verilerini taşımak veya karşılaştırmak için sol veya sağ yönü belirler. DF değeri 0 olduğunda, dizi işlemi soldan sağa ve değer 1 olarak ayarlandığında, dizi işlemi sağdan sola doğru olur.
Interrupt Flag (IF)- Klavye girişi vb. Gibi harici kesintilerin yok sayılacağını veya işleneceğini belirler. Değer 0 olduğunda harici kesmeyi devre dışı bırakır ve 1'e ayarlandığında kesmeleri etkinleştirir.
Trap Flag (TF)- İşlemcinin çalışmasını tek adım modunda ayarlamaya izin verir. Kullandığımız DEBUG programı tuzak bayrağını ayarlar, böylece her seferinde bir komut yürütme adımına geçebiliriz.
Sign Flag (SF)- Bir aritmetik işlemin sonucunun işaretini gösterir. Bu bayrak, aritmetik işlemin ardından bir veri öğesinin işaretine göre ayarlanır. İşaret, en soldaki bitin yüksek sırasıyla gösterilir. Pozitif bir sonuç, SF'nin değerini 0'a temizler ve negatif sonuç onu 1'e ayarlar.
Zero Flag (ZF)- Bir aritmetik veya karşılaştırma işleminin sonucunu gösterir. Sıfır olmayan bir sonuç, sıfır bayrağını 0 olarak temizler ve sıfır sonuç onu 1 olarak ayarlar.
Auxiliary Carry Flag (AF)- Bir aritmetik işlemin ardından bit 3'ten bit 4'e taşımayı içerir; özel aritmetik için kullanılır. AF, 1 baytlık bir aritmetik işlem, bit 3'ten bit 4'e taşınmaya neden olduğunda ayarlanır.
Parity Flag (PF)- Bir aritmetik işlemden elde edilen sonuçtaki toplam 1 bit sayısını gösterir. 1 bitlik çift sayı, eşlik bayrağını 0'a, tek sayıdaki 1 bitlik eşlik bayrağını 1'e ayarlar.
Carry Flag (CF)- Bir aritmetik işlemden sonra yüksek dereceli bir bitten (en soldaki) 0 veya 1'in taşınmasını içerir. Ayrıca, bir kaydırma veya döndürme işleminin son bitinin içeriğini de depolar .
Aşağıdaki tablo, 16 bitlik Flags kaydındaki bayrak bitlerinin konumunu gösterir:
Bayrak: | Ö | D | ben | T | S | Z | Bir | P | C | |||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Bit hayır: | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
Segment Kayıtları
Segmentler, veri, kod ve yığını içermek için bir programda tanımlanan belirli alanlardır. Üç ana bölüm vardır -
Code Segment- Yürütülecek tüm talimatları içerir. 16 bitlik bir Kod Segment kaydı veya CS kaydı, kod segmentinin başlangıç adresini depolar.
Data Segment- Veri, sabitler ve çalışma alanlarını içerir. 16 bitlik Veri Segment kaydı veya DS kaydı, veri segmentinin başlangıç adresini depolar.
Stack Segment- Prosedürlerin veya alt rutinlerin verilerini ve dönüş adreslerini içerir. Bir 'yığın' veri yapısı olarak uygulanır. Yığın Segment kaydı veya SS kaydı, yığının başlangıç adresini depolar.
DS, CS ve SS kayıtlarından ayrı olarak, verilerin depolanması için ek segmentler sağlayan ES (ekstra segment), FS ve GS gibi başka ekstra segment kayıtları da vardır.
Montaj programlamasında, bir programın bellek konumlarına erişmesi gerekir. Bir segment içindeki tüm hafıza konumları, segmentin başlangıç adresine göredir. Bir segment, 16 veya onaltılık 10 ile eşit olarak bölünebilen bir adreste başlar. Dolayısıyla, tüm bu tür hafıza adreslerindeki en sağdaki onaltılık rakam, genellikle segment kayıtlarında saklanmayan O'dır.
Segment kayıtları, bir segmentin başlangıç adreslerini saklar. Bir segment içindeki verilerin veya talimatın tam konumunu elde etmek için bir ofset değeri (veya yer değiştirme) gereklidir. Bir bölümdeki herhangi bir bellek konumuna referans vermek için, işlemci bölüm yazmacındaki bölüm adresini konumun ofset değeri ile birleştirir.
Misal
Montaj programlamasında yazmaçların kullanımını anlamak için aşağıdaki basit programa bakın. Bu program, basit bir mesajla birlikte ekranda 9 yıldız görüntüler -
section .text
global _start ;must be declared for linker (gcc)
_start: ;tell linker entry point
mov edx,len ;message length
mov ecx,msg ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov edx,9 ;message length
mov ecx,s2 ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
msg db 'Displaying 9 stars',0xa ;a message
len equ $ - msg ;length of message
s2 times 9 db '*'
Yukarıdaki kod derlendiğinde ve yürütüldüğünde, aşağıdaki sonucu verir -
Displaying 9 stars
*********
Sistem çağrıları, kullanıcı alanı ile çekirdek alanı arasındaki arayüz için API'lerdir. Sistem çağrılarını zaten kullandık. sırasıyla ekrana yazmak ve programdan çıkmak için sys_write ve sys_exit.
Linux Sistem Çağrıları
Assembly programlarınızda Linux sistem çağrılarından yararlanabilirsiniz. Programınızda Linux sistem çağrılarını kullanmak için aşağıdaki adımları atmanız gerekir -
- Sistem çağrı numarasını EAX kaydına girin.
- Sistem çağrısındaki argümanları EBX, ECX vb. Kayıtlarında saklayın.
- İlgili kesmeyi arayın (80h).
- Sonuç genellikle EAX kaydına döndürülür.
Kullanılan sistem çağrısının argümanlarını depolayan altı kayıt vardır. Bunlar EBX, ECX, EDX, ESI, EDI ve EBP'dir. Bu kayıtlar, EBX yazmacından başlayarak ardışık argümanları alır. Altıdan fazla argüman varsa, ilk argümanın hafıza konumu EBX kaydında saklanır.
Aşağıdaki kod parçacığı, sys_exit sistem çağrısının kullanımını gösterir -
mov eax,1 ; system call number (sys_exit)
int 0x80 ; call kernel
Aşağıdaki kod parçası, sys_write sistem çağrısının kullanımını gösterir -
mov edx,4 ; message length
mov ecx,msg ; message to write
mov ebx,1 ; file descriptor (stdout)
mov eax,4 ; system call number (sys_write)
int 0x80 ; call kernel
Tüm sistem çağrıları numaralarıyla birlikte /usr/include/asm/unistd.h'de listelenir (int 80h'yi çağırmadan önce EAX'e koymanız gereken değer).
Aşağıdaki tablo, bu eğitimde kullanılan bazı sistem çağrılarını göstermektedir -
% eax | İsim | % ebx | % ecx | % edx | % esx | % edi |
---|---|---|---|---|---|---|
1 | sys_exit | int | - | - | - | - |
2 | sys_fork | struct pt_regs | - | - | - | - |
3 | sys_read | imzasız int | karakter * | size_t | - | - |
4 | sys_write | imzasız int | const karakter * | size_t | - | - |
5 | sys_open | const karakter * | int | int | - | - |
6 | sys_close | imzasız int | - | - | - | - |
Misal
Aşağıdaki örnek klavyeden bir sayı okur ve ekranda görüntüler -
section .data ;Data segment
userMsg db 'Please enter a number: ' ;Ask the user to enter a number
lenUserMsg equ $-userMsg ;The length of the message
dispMsg db 'You have entered: '
lenDispMsg equ $-dispMsg
section .bss ;Uninitialized data
num resb 5
section .text ;Code Segment
global _start
_start: ;User prompt
mov eax, 4
mov ebx, 1
mov ecx, userMsg
mov edx, lenUserMsg
int 80h
;Read and store the user input
mov eax, 3
mov ebx, 2
mov ecx, num
mov edx, 5 ;5 bytes (numeric, 1 for sign) of that information
int 80h
;Output the message 'The entered number is: '
mov eax, 4
mov ebx, 1
mov ecx, dispMsg
mov edx, lenDispMsg
int 80h
;Output the number entered
mov eax, 4
mov ebx, 1
mov ecx, num
mov edx, 5
int 80h
; Exit code
mov eax, 1
mov ebx, 0
int 80h
Yukarıdaki kod derlendiğinde ve yürütüldüğünde, aşağıdaki sonucu verir -
Please enter a number:
1234
You have entered:1234
Çoğu montaj dili talimatı, işlenenlerin işlenmesini gerektirir. Bir işlenen adresi, işlenecek verilerin depolandığı konumu sağlar. Bazı komutlar bir işlenen gerektirmezken, diğer bazı komutlar bir, iki veya üç işlenen gerektirebilir.
Bir talimat iki işlenen gerektirdiğinde, ilk işlenen genellikle bir yazmaç veya bellek konumundaki verileri içeren hedeftir ve ikinci işlenen kaynaktır. Kaynak, ya teslim edilecek verileri (anında adresleme) ya da verilerin adresini (kayıt veya hafızada) içerir. Genellikle kaynak veriler işlemden sonra değişmeden kalır.
Üç temel adresleme modu şunlardır:
- Adreslemeyi kaydet
- Anında adresleme
- Bellek adresleme
Kayıt Adresleme
Bu adresleme modunda, bir kayıt işleneni içerir. Talimata bağlı olarak, kayıt ilk işlenen, ikinci işlenen veya her ikisi olabilir.
Örneğin,
MOV DX, TAX_RATE ; Register in first operand
MOV COUNT, CX ; Register in second operand
MOV EAX, EBX ; Both the operands are in registers
Kayıtlar arasında veri işlemek bellek içermediğinden, verilerin en hızlı şekilde işlenmesini sağlar.
Anında Adresleme
Bir anlık işlenenin sabit bir değeri veya bir ifadesi vardır. İki işlenenli bir talimat anında adresleme kullandığında, ilk işlenen bir kayıt veya bellek konumu olabilir ve ikinci işlenen bir anlık sabittir. İlk işlenen, verilerin uzunluğunu tanımlar.
Örneğin,
BYTE_VALUE DB 150 ; A byte value is defined
WORD_VALUE DW 300 ; A word value is defined
ADD BYTE_VALUE, 65 ; An immediate operand 65 is added
MOV AX, 45H ; Immediate constant 45H is transferred to AX
Doğrudan Bellek Adresleme
Hafıza adresleme modunda işlenenler belirtildiğinde, ana hafızaya, genellikle veri segmentine doğrudan erişim gereklidir. Bu şekilde ele alma, verilerin daha yavaş işlenmesine neden olur. Hafızadaki verilerin tam yerini bulmak için, tipik olarak DS kaydında bulunan segment başlangıç adresine ve bir ofset değerine ihtiyacımız var. Bu ofset değeri aynı zamandaeffective address.
Doğrudan adresleme modunda, ofset değeri doğrudan talimatın bir parçası olarak belirtilir ve genellikle değişken adı ile gösterilir. Assembler, ofset değerini hesaplar ve programda kullanılan tüm değişkenlerin ofset değerlerini saklayan bir sembol tablosu tutar.
Doğrudan bellek adreslemede, işlenenlerden biri bir bellek konumuna ve diğer işlenen bir yazmacıya başvurur.
Örneğin,
ADD BYTE_VALUE, DL ; Adds the register in the memory location
MOV BX, WORD_VALUE ; Operand from the memory is added to register
Doğrudan Ofset Adresleme
Bu adresleme modu, bir adresi değiştirmek için aritmetik operatörleri kullanır. Örneğin, veri tablolarını tanımlayan aşağıdaki tanımlara bakın -
BYTE_TABLE DB 14, 15, 22, 45 ; Tables of bytes
WORD_TABLE DW 134, 345, 564, 123 ; Tables of words
Aşağıdaki işlemler hafızadaki tablolardan verilere kayıtlara erişir -
MOV CL, BYTE_TABLE[2] ; Gets the 3rd element of the BYTE_TABLE
MOV CL, BYTE_TABLE + 2 ; Gets the 3rd element of the BYTE_TABLE
MOV CX, WORD_TABLE[3] ; Gets the 4th element of the WORD_TABLE
MOV CX, WORD_TABLE + 3 ; Gets the 4th element of the WORD_TABLE
Dolaylı Bellek Adresleme
Bu adresleme modu, bilgisayarın Segment: Ofset adresleme yeteneğini kullanır . Genel olarak, bu amaç için bellek referansları için köşeli parantez içinde kodlanan EBX, EBP (veya BX, BP) temel kayıtları ve indeks kayıtları (DI, SI) kullanılır.
Dolaylı adresleme genellikle diziler gibi birkaç öğe içeren değişkenler için kullanılır. Dizinin başlangıç adresi, örneğin EBX yazmacında saklanır.
Aşağıdaki kod parçacığı, değişkenin farklı öğelerine nasıl erişileceğini gösterir.
MY_TABLE TIMES 10 DW 0 ; Allocates 10 words (2 bytes) each initialized to 0
MOV EBX, [MY_TABLE] ; Effective Address of MY_TABLE in EBX
MOV [EBX], 110 ; MY_TABLE[0] = 110
ADD EBX, 2 ; EBX = EBX +2
MOV [EBX], 123 ; MY_TABLE[1] = 123
MOV Talimatı
Verileri bir depolama alanından diğerine taşımak için kullanılan MOV komutunu zaten kullandık. MOV komutu iki işlenen alır.
Sözdizimi
MOV komutunun sözdizimi -
MOV destination, source
MOV talimatı aşağıdaki beş formdan birine sahip olabilir -
MOV register, register
MOV register, immediate
MOV memory, immediate
MOV register, memory
MOV memory, register
Lütfen unutmayın -
- MOV işlemindeki her iki işlenen de aynı boyutta olmalıdır
- Kaynak işlenenin değeri değişmeden kalır
MOV talimatı bazen belirsizliğe neden olur. Örneğin, ifadelere bakın -
MOV EBX, [MY_TABLE] ; Effective Address of MY_TABLE in EBX
MOV [EBX], 110 ; MY_TABLE[0] = 110
110 sayısının bir bayt eşdeğerini mi yoksa kelime eşdeğerini mi hareket ettirmek istediğiniz açık değildir. Bu gibi durumlarda, kullanmak akıllıca olacaktır. type specifier.
Aşağıdaki tablo, yaygın tür belirticilerinden bazılarını göstermektedir -
Tür Belirteci | Baytlar adreslendi |
---|---|
BAYT | 1 |
WORD | 2 |
DWORD | 4 |
QWORD | 8 |
TBYTE | 10 |
Misal
Aşağıdaki program, yukarıda tartışılan kavramlardan bazılarını göstermektedir. Belleğin veri bölümünde bir 'Zara Ali' adı depolar, sonra değerini programlı olarak başka bir 'Nuha Ali' ismine değiştirir ve her iki adı da görüntüler.
section .text
global _start ;must be declared for linker (ld)
_start: ;tell linker entry point
;writing the name 'Zara Ali'
mov edx,9 ;message length
mov ecx, name ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov [name], dword 'Nuha' ; Changed the name to Nuha Ali
;writing the name 'Nuha Ali'
mov edx,8 ;message length
mov ecx,name ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
name db 'Zara Ali '
Yukarıdaki kod derlendiğinde ve yürütüldüğünde, aşağıdaki sonucu verir -
Zara Ali Nuha Ali
NASM, çeşitli define directivesdeğişkenler için depolama alanı ayırmak için. Define assembler direktifi, depolama alanı tahsisi için kullanılır. Bir veya daha fazla baytı ayırmak ve başlatmak için kullanılabilir.
İlklendirilmiş Veriler için Depolama Alanı Tahsis Etme
Başlatılan veriler için depolama ayırma ifadesi sözdizimi şöyledir:
[variable-name] define-directive initial-value [,initial-value]...
Burada, değişken adı , her depolama alanı için tanımlayıcıdır. Birleştirici, veri segmentinde tanımlanan her değişken adı için bir ofset değerini ilişkilendirir.
Tanımlama yönergesinin beş temel biçimi vardır -
Direktif | Amaç | Depolama alanı |
---|---|---|
DB | Bayt Tanımla | 1 bayt ayırır |
DW | Kelime Tanımla | 2 bayt ayırır |
DD | Doubleword tanımlayın | 4 bayt ayırır |
DQ | Quadword tanımlayın | 8 bayt ayırır |
DT | On Bayt Tanımla | 10 bayt ayırır |
Aşağıda, define yönergelerinin kullanımına ilişkin bazı örnekler verilmiştir -
choice DB 'y'
number DW 12345
neg_number DW -12345
big_number DQ 123456789
real_number1 DD 1.234
real_number2 DQ 123.456
Lütfen unutmayın -
Her karakter baytı, onaltılık sistemde ASCII değeri olarak saklanır.
Her ondalık değer otomatik olarak 16 bitlik ikili eşdeğerine dönüştürülür ve onaltılık bir sayı olarak saklanır.
İşlemci, küçük endian bayt sıralaması kullanır.
Negatif sayılar, 2'nin tümleyen gösterimine dönüştürülür.
Kısa ve uzun kayan noktalı sayılar sırasıyla 32 veya 64 bit kullanılarak temsil edilir.
Aşağıdaki program, define yönergesinin kullanımını göstermektedir -
section .text
global _start ;must be declared for linker (gcc)
_start: ;tell linker entry point
mov edx,1 ;message length
mov ecx,choice ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
choice DB 'y'
Yukarıdaki kod derlendiğinde ve yürütüldüğünde, aşağıdaki sonucu verir -
y
İlklendirilmemiş Veriler için Depolama Alanı Tahsis Etme
Rezerv direktifleri, başlatılmamış veriler için yer ayırmak için kullanılır. Rezerv direktifleri, rezerve edilecek alan birimlerinin sayısını belirten tek bir işlenen alır. Her bir tanımlama yönergesinin ilgili bir yedek yönergesi vardır.
Rezerv direktifinin beş temel biçimi vardır -
Direktif | Amaç |
---|---|
RESB | Bayt ayır |
RESW | Bir Kelime Rezerve Et |
RESD | Doubleword ayırtın |
RESQ | Bir Quadword ayırtın |
DİNLENME | On Bayt Ayırtın |
Çoklu Tanımlar
Bir programda birden çok veri tanımlama ifadesine sahip olabilirsiniz. Örneğin -
choice DB 'Y' ;ASCII of y = 79H
number1 DW 12345 ;12345D = 3039H
number2 DD 12345679 ;123456789D = 75BCD15H
Birleştirici, birden çok değişken tanımı için bitişik bellek ayırır.
Çoklu İlklendirmeler
TIMES yönergesi, aynı değerde birden çok başlatmaya izin verir. Örneğin, 9 boyutunda işaretler adlı bir dizi aşağıdaki ifade kullanılarak tanımlanabilir ve sıfır olarak başlatılabilir -
marks TIMES 9 DW 0
TIMES yönergesi, dizileri ve tabloları tanımlamada kullanışlıdır. Aşağıdaki program ekranda 9 yıldız işareti gösterir -
section .text
global _start ;must be declared for linker (ld)
_start: ;tell linker entry point
mov edx,9 ;message length
mov ecx, stars ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
stars times 9 db '*'
Yukarıdaki kod derlendiğinde ve yürütüldüğünde, aşağıdaki sonucu verir -
*********
Sabitleri tanımlayan NASM tarafından sağlanan birkaç yönerge vardır. EQU direktifini önceki bölümlerde zaten kullandık. Özellikle üç yönergeyi tartışacağız -
- EQU
- %assign
- %define
EQU Direktifi
EQUyönergesi sabitleri tanımlamak için kullanılır. EQU direktifinin sözdizimi aşağıdaki gibidir -
CONSTANT_NAME EQU expression
Örneğin,
TOTAL_STUDENTS equ 50
Daha sonra bu sabit değeri kodunuzda kullanabilirsiniz, örneğin -
mov ecx, TOTAL_STUDENTS
cmp eax, TOTAL_STUDENTS
Bir EQU ifadesinin işleneni bir ifade olabilir -
LENGTH equ 20
WIDTH equ 10
AREA equ length * width
Yukarıdaki kod segmenti AREA'yı 200 olarak tanımlar.
Misal
Aşağıdaki örnek, EQU direktifinin kullanımını göstermektedir -
SYS_EXIT equ 1
SYS_WRITE equ 4
STDIN equ 0
STDOUT equ 1
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, msg1
mov edx, len1
int 0x80
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, msg2
mov edx, len2
int 0x80
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, msg3
mov edx, len3
int 0x80
mov eax,SYS_EXIT ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
msg1 db 'Hello, programmers!',0xA,0xD
len1 equ $ - msg1
msg2 db 'Welcome to the world of,', 0xA,0xD
len2 equ $ - msg2 msg3 db 'Linux assembly programming! ' len3 equ $- msg3
Yukarıdaki kod derlendiğinde ve yürütüldüğünde, aşağıdaki sonucu verir -
Hello, programmers!
Welcome to the world of,
Linux assembly programming!
% Atama Yönergesi
%assignyönergesi, EQU yönergesi gibi sayısal sabitleri tanımlamak için kullanılabilir. Bu yönerge yeniden tanımlamaya izin verir. Örneğin, TOTAL sabitini şu şekilde tanımlayabilirsiniz:
%assign TOTAL 10
Kodun ilerleyen kısımlarında, bunu şu şekilde yeniden tanımlayabilirsiniz:
%assign TOTAL 20
Bu yönerge büyük / küçük harfe duyarlıdır.
% Direktifi tanımlar
%defineyönerge hem sayısal hem de dizge sabitlerinin tanımlanmasına izin verir. Bu yönerge C'deki #define yönergesine benzer. Örneğin, sabit PTR'yi şu şekilde tanımlayabilirsiniz:
%define PTR [EBP+4]
Yukarıdaki kod, PTR'yi [EBP + 4] ile değiştirir.
Bu yönerge aynı zamanda yeniden tanımlamaya izin verir ve büyük / küçük harfe duyarlıdır.
INC Talimatı
INC komutu, bir işleneni birer birer artırmak için kullanılır. Bir yazmaçta veya bellekte olabilen tek bir işlenen üzerinde çalışır.
Sözdizimi
INC talimatı aşağıdaki sözdizimine sahiptir -
INC destination
İşlenen hedefi 8 bitlik, 16 bitlik veya 32 bitlik bir işlenen olabilir.
Misal
INC EBX ; Increments 32-bit register
INC DL ; Increments 8-bit register
INC [count] ; Increments the count variable
DEC Talimatı
DEC komutu, bir işleneni birer birer azaltmak için kullanılır. Bir yazmaçta veya bellekte olabilen tek bir işlenen üzerinde çalışır.
Sözdizimi
DEC talimatı aşağıdaki sözdizimine sahiptir -
DEC destination
İşlenen hedefi 8 bitlik, 16 bitlik veya 32 bitlik bir işlenen olabilir.
Misal
segment .data
count dw 0
value db 15
segment .text
inc [count]
dec [value]
mov ebx, count
inc word [ebx]
mov esi, value
dec byte [esi]
ADD ve SUB Talimatları
ADD ve SUB komutları, ikili verilerin bayt, kelime ve çift kelime boyutunda basit bir şekilde toplanması / çıkarılması için, yani sırasıyla 8-bit, 16-bit veya 32-bit işlenenleri eklemek veya çıkarmak için kullanılır.
Sözdizimi
ADD ve SUB komutları aşağıdaki sözdizimine sahiptir -
ADD/SUB destination, source
ADD / SUB komutu aşağıdakiler arasında gerçekleşebilir:
- Kaydolmak için kaydolun
- Kaydedilecek hafıza
- Hafızaya kaydol
- Sabit verilere kaydolun
- Sabit verilere bellek
Ancak, diğer talimatlar gibi, ADD / SUB komutları kullanılarak bellekten belleğe işlemler mümkün değildir. Bir ADD veya SUB işlemi taşma ve taşıma bayraklarını ayarlar veya siler.
Misal
Aşağıdaki örnek, kullanıcıdan iki basamak isteyecek, basamakları sırasıyla EAX ve EBX kaydına kaydedecek, değerleri ekleyecek, sonucu bir bellek konumuna ' res ' depolayacak ve son olarak sonucu görüntüleyecektir.
SYS_EXIT equ 1
SYS_READ equ 3
SYS_WRITE equ 4
STDIN equ 0
STDOUT equ 1
segment .data
msg1 db "Enter a digit ", 0xA,0xD
len1 equ $- msg1 msg2 db "Please enter a second digit", 0xA,0xD len2 equ $- msg2
msg3 db "The sum is: "
len3 equ $- msg3
segment .bss
num1 resb 2
num2 resb 2
res resb 1
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, msg1
mov edx, len1
int 0x80
mov eax, SYS_READ
mov ebx, STDIN
mov ecx, num1
mov edx, 2
int 0x80
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, msg2
mov edx, len2
int 0x80
mov eax, SYS_READ
mov ebx, STDIN
mov ecx, num2
mov edx, 2
int 0x80
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, msg3
mov edx, len3
int 0x80
; moving the first number to eax register and second number to ebx
; and subtracting ascii '0' to convert it into a decimal number
mov eax, [num1]
sub eax, '0'
mov ebx, [num2]
sub ebx, '0'
; add eax and ebx
add eax, ebx
; add '0' to to convert the sum from decimal to ASCII
add eax, '0'
; storing the sum in memory location res
mov [res], eax
; print the sum
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, res
mov edx, 1
int 0x80
exit:
mov eax, SYS_EXIT
xor ebx, ebx
int 0x80
Yukarıdaki kod derlendiğinde ve yürütüldüğünde, aşağıdaki sonucu verir -
Enter a digit:
3
Please enter a second digit:
4
The sum is:
7
The program with hardcoded variables −
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov eax,'3'
sub eax, '0'
mov ebx, '4'
sub ebx, '0'
add eax, ebx
add eax, '0'
mov [sum], eax
mov ecx,msg
mov edx, len
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov ecx,sum
mov edx, 1
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
msg db "The sum is:", 0xA,0xD
len equ $ - msg
segment .bss
sum resb 1
Yukarıdaki kod derlendiğinde ve yürütüldüğünde, aşağıdaki sonucu verir -
The sum is:
7
MUL / IMUL Talimatı
İkili verileri çarpmak için iki talimat vardır. MUL (Çarpma) talimatı işaretsiz verileri işler ve IMUL (Tamsayı Çarpma) işaretli verileri işler. Her iki talimat da Taşıma ve Taşma bayrağını etkiler.
Sözdizimi
MUL / IMUL komutlarının sözdizimi aşağıdaki gibidir -
MUL/IMUL multiplier
Her iki durumda da çarpan, çarpanın boyutuna ve çarpana bağlı olarak bir toplayıcıda olacaktır ve üretilen ürün ayrıca işlenenlerin boyutuna bağlı olarak iki kayıtta saklanır. Aşağıdaki bölüm MUL talimatlarını üç farklı durumla açıklamaktadır -
Sr.No. | Senaryolar |
---|---|
1 | When two bytes are multiplied − Çarpan AL yazmacında ve çarpan bellekte veya başka bir yazmaçta bir bayttır. Ürün AX'te. Ürünün yüksek sıralı 8 biti AH'de depolanır ve düşük sıralı 8 biti AL'de depolanır.
|
2 | When two one-word values are multiplied − Çarpan AX kaydında olmalıdır ve çarpan bellekte veya başka bir kayıtta bir sözcüktür. Örneğin, MUL DX gibi bir komut için, çarpanı DX'te ve çarpanı AX'te saklamanız gerekir. Ortaya çıkan ürün, iki kayda ihtiyaç duyan bir çift sözcüktür. Yüksek dereceli (en soldaki) bölüm DX'te depolanır ve alt sıra (en sağdaki) bölüm AX'te depolanır.
|
3 | When two doubleword values are multiplied − İki doubleword değeri çarpıldığında, çarpan EAX'te olmalıdır ve çarpan, bellekte veya başka bir kayıtta saklanan bir doubleword değeridir. Üretilen ürün, EDX: EAX kayıtlarında depolanır, yani, yüksek sıralı 32 bit, EDX kaydında depolanır ve düşük sıralı 32 bit, EAX kaydında depolanır.
|
Misal
MOV AL, 10
MOV DL, 25
MUL DL
...
MOV DL, 0FFH ; DL= -1
MOV AL, 0BEH ; AL = -66
IMUL DL
Misal
Aşağıdaki örnek 3'ü 2 ile çarpıyor ve sonucu gösteriyor -
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov al,'3'
sub al, '0'
mov bl, '2'
sub bl, '0'
mul bl
add al, '0'
mov [res], al
mov ecx,msg
mov edx, len
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov ecx,res
mov edx, 1
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
msg db "The result is:", 0xA,0xD
len equ $- msg
segment .bss
res resb 1
Yukarıdaki kod derlendiğinde ve yürütüldüğünde, aşağıdaki sonucu verir -
The result is:
6
DIV / IDIV Talimatları
Bölme işlemi iki öğe oluşturur - a quotient ve bir remainder. Çarpma durumunda, ürünü tutmak için çift uzunluklu yazmaçlar kullanıldığından taşma meydana gelmez. Ancak bölünme durumunda taşma meydana gelebilir. İşlemci, taşma meydana gelirse bir kesinti oluşturur.
DIV (Böl) komutu, işaretsiz veriler için kullanılır ve IDIV (Integer Divide) imzalı veriler için kullanılır.
Sözdizimi
DIV / IDIV talimatı için format -
DIV/IDIV divisor
Temettü bir akümülatörde. Her iki komut da 8 bit, 16 bit veya 32 bit işlenenlerle çalışabilir. İşlem altı durum bayrağının tümünü etkiler. Aşağıdaki bölüm, farklı işlenen boyutuna sahip üç bölme durumunu açıklamaktadır -
Sr.No. | Senaryolar |
---|---|
1 | When the divisor is 1 byte − Temettü, AX kaydında (16 bit) olduğu varsayılır. Bölünmeden sonra, bölüm AL yazmacına gider ve geri kalanı AH yazmacına gider.
|
2 | When the divisor is 1 word − Temettü tutarının 32 bit uzunluğunda olduğu ve DX: AX kayıtlarında olduğu varsayılır. Yüksek sıralı 16 bit DX'te ve düşük sıralı 16 bit AX'te. Bölünmeden sonra, 16 bitlik bölüm AX yazmacına gider ve 16 bitlik kalan DX yazmacına gider.
|
3 | When the divisor is doubleword − Temettü tutarının 64 bit uzunluğunda olduğu ve EDX: EAX kayıtlarında olduğu varsayılır. Yüksek sıralı 32 bitler EDX'te ve düşük sıralı 32 bitler EAX'te. Bölünmeden sonra, 32 bitlik bölüm EAX kaydına gider ve 32 bitlik kalan EDX kaydına gider.
|
Misal
Aşağıdaki örnek 8'i 2'ye böler. dividend 8 içinde saklanır 16-bit AX register ve divisor 2 içinde saklanır 8-bit BL register.
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov ax,'8'
sub ax, '0'
mov bl, '2'
sub bl, '0'
div bl
add ax, '0'
mov [res], ax
mov ecx,msg
mov edx, len
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov ecx,res
mov edx, 1
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
msg db "The result is:", 0xA,0xD
len equ $- msg
segment .bss
res resb 1
Yukarıdaki kod derlendiğinde ve yürütüldüğünde, aşağıdaki sonucu verir -
The result is:
4
İşlemci komut seti, programın ihtiyacına göre bitleri test eden, ayarlayan ve temizleyen AND, OR, XOR, TEST ve NOT Boole mantığını sağlar.
Bu talimatların biçimi -
Sr.No. | Talimat | Biçim |
---|---|---|
1 | VE | AND işlenen1, işlenen2 |
2 | VEYA | OR işlenen1, işlenen2 |
3 | ÖZELVEYA | XOR işlenen1, işlenen2 |
4 | ÖLÇEK | TEST işlenen1, işlenen2 |
5 | DEĞİL | DEĞİL işlenen1 |
Tüm durumlarda ilk işlenen, kayıtta veya bellekte olabilir. İkinci işlenen, kayıt / bellekte veya anlık (sabit) bir değer olabilir. Ancak, bellekten belleğe işlemler mümkün değildir. Bu talimatlar, işlenenlerin bitlerini karşılaştırır veya eşleştirir ve CF, OF, PF, SF ve ZF bayraklarını ayarlar.
AND Talimatı
AND komutu, bitsel AND işlemi gerçekleştirerek mantıksal ifadeleri desteklemek için kullanılır. Her iki işlenenden eşleşen bitler 1 ise bitsel AND işlemi 1 döndürür, aksi takdirde 0 döndürür. Örneğin -
Operand1: 0101
Operand2: 0011
----------------------------
After AND -> Operand1: 0001
AND işlemi, bir veya daha fazla biti temizlemek için kullanılabilir. Örneğin, BL yazmacının 0011 1010 içerdiğini söyleyin. Yüksek sıralı bitleri sıfıra sıfırlamanız gerekiyorsa, siz VE 0FH ile.
AND BL, 0FH ; This sets BL to 0000 1010
Başka bir örnek ele alalım. Belirli bir sayının tek mi çift mi olduğunu kontrol etmek istiyorsanız, basit bir test sayının en az anlamlı bitini kontrol etmektir. Bu 1 ise sayı tek, yoksa çift sayıdır.
Numaranın AL sicilinde olduğunu varsayarsak, yazabiliriz -
AND AL, 01H ; ANDing with 0000 0001
JZ EVEN_NUMBER
Aşağıdaki program bunu göstermektedir -
Misal
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov ax, 8h ;getting 8 in the ax
and ax, 1 ;and ax with 1
jz evnn
mov eax, 4 ;system call number (sys_write)
mov ebx, 1 ;file descriptor (stdout)
mov ecx, odd_msg ;message to write
mov edx, len2 ;length of message
int 0x80 ;call kernel
jmp outprog
evnn:
mov ah, 09h
mov eax, 4 ;system call number (sys_write)
mov ebx, 1 ;file descriptor (stdout)
mov ecx, even_msg ;message to write
mov edx, len1 ;length of message
int 0x80 ;call kernel
outprog:
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
even_msg db 'Even Number!' ;message showing even number
len1 equ $ - even_msg odd_msg db 'Odd Number!' ;message showing odd number len2 equ $ - odd_msg
Yukarıdaki kod derlendiğinde ve yürütüldüğünde, aşağıdaki sonucu verir -
Even Number!
Balta kaydındaki değeri tek bir rakamla değiştirin, örneğin -
mov ax, 9h ; getting 9 in the ax
Program şunu görüntüler:
Odd Number!
Benzer şekilde tüm kütüğü temizlemek için VE bunu 00H ile yapabilirsiniz.
OR Talimatı
OR komutu, bitsel OR işlemi gerçekleştirerek mantıksal ifadeyi desteklemek için kullanılır. Bitsel OR operatörü, işlenenlerden birinin veya her ikisinin eşleşen bitleri bir ise, 1 döndürür. Her iki bit de sıfırsa 0 döndürür.
Örneğin,
Operand1: 0101
Operand2: 0011
----------------------------
After OR -> Operand1: 0111
OR işlemi, bir veya daha fazla biti ayarlamak için kullanılabilir. Örneğin, AL yazmacının 0011 1010 içerdiğini varsayalım, dört düşük sıralı biti ayarlamanız gerekir, bunu 0000 1111, yani FH değeriyle VEYA yapabilirsiniz.
OR BL, 0FH ; This sets BL to 0011 1111
Misal
Aşağıdaki örnek, OR talimatını gösterir. Sırasıyla AL ve BL yazmaçlarında 5 ve 3 değerini saklayalım, ardından komut,
OR AL, BL
AL kaydında 7'yi saklamalıdır -
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov al, 5 ;getting 5 in the al
mov bl, 3 ;getting 3 in the bl
or al, bl ;or al and bl registers, result should be 7
add al, byte '0' ;converting decimal to ascii
mov [result], al
mov eax, 4
mov ebx, 1
mov ecx, result
mov edx, 1
int 0x80
outprog:
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .bss
result resb 1
Yukarıdaki kod derlendiğinde ve yürütüldüğünde, aşağıdaki sonucu verir -
7
XOR Talimatı
XOR komutu bitsel XOR işlemini uygular. XOR işlemi sonuçtaki biti 1'e ayarlar, ancak ve ancak işlenenlerden gelen bitler farklıysa. İşlenenlerden gelen bitler aynıysa (her ikisi de 0 veya her ikisi 1), ortaya çıkan bit 0'a temizlenir.
Örneğin,
Operand1: 0101
Operand2: 0011
----------------------------
After XOR -> Operand1: 0110
XORing kendi başına bir işlenen, işleneni şu şekilde değiştirir: 0. Bu, bir kaydı temizlemek için kullanılır.
XOR EAX, EAX
TEST Talimatı
TEST komutu, AND işlemiyle aynı şekilde çalışır, ancak AND komutunun aksine, ilk işleneni değiştirmez. Yani, bir kayıttaki bir sayının çift mi yoksa tek mi olduğunu kontrol etmemiz gerekirse, bunu orijinal sayıyı değiştirmeden TEST komutunu kullanarak da yapabiliriz.
TEST AL, 01H
JZ EVEN_NUMBER
NOT Talimatı
NOT komutu bitsel NOT işlemini uygular. NOT işlemi bir işlenendeki bitleri ters çevirir. İşlenen, bir kayıtta veya bellekte olabilir.
Örneğin,
Operand1: 0101 0011
After NOT -> Operand1: 1010 1100
Assembly dilinde koşullu yürütme, birkaç döngü ve dallanma talimatıyla gerçekleştirilir. Bu talimatlar, bir programdaki kontrol akışını değiştirebilir. Koşullu yürütme iki senaryoda gözlemlenir -
Sr.No. | Koşullu Talimatlar |
---|---|
1 | Unconditional jump Bu, JMP talimatı ile gerçekleştirilir. Koşullu yürütme, genellikle o anda yürütülen talimatı takip etmeyen bir talimatın adresine bir kontrol aktarımını içerir. Kontrolün devri ileri, yeni bir talimatlar dizisini uygulamak için veya aynı adımları yeniden uygulamak için geri olabilir. |
2 | Conditional jump Bu, koşula bağlı olarak bir dizi atlama talimatı j <koşul> ile gerçekleştirilir. Koşullu komutlar, sıralı akışı keserek kontrolü aktarır ve bunu IP'deki ofset değerini değiştirerek yapar. |
Koşullu talimatları tartışmadan önce CMP talimatını tartışalım.
CMP Talimatı
CMP komutu iki işleneni karşılaştırır. Genelde şartlı icrada kullanılır. Bu komut temelde işlenenlerin eşit olup olmadığını karşılaştırmak için bir işleneni diğerinden çıkarır. Hedefi veya kaynak işlenenleri rahatsız etmez. Karar vermede şartlı atlama talimatıyla birlikte kullanılır.
Sözdizimi
CMP destination, source
CMP, iki sayısal veri alanını karşılaştırır. Hedef işlenen, kayıtlı veya bellekte olabilir. Kaynak işlenen sabit (anlık) bir veri, kayıt veya bellek olabilir.
Misal
CMP DX, 00 ; Compare the DX value with zero
JE L7 ; If yes, then jump to label L7
.
.
L7: ...
CMP genellikle bir sayaç değerinin bir döngünün çalıştırılması gereken sayıya ulaşıp ulaşmadığını karşılaştırmak için kullanılır. Aşağıdaki tipik durumu düşünün -
INC EDX
CMP EDX, 10 ; Compares whether the counter has reached 10
JLE LP1 ; If it is less than or equal to 10, then jump to LP1
Koşulsuz Atlama
Daha önce belirtildiği gibi, bu JMP talimatı ile gerçekleştirilir. Koşullu yürütme, genellikle o anda yürütülen talimatı takip etmeyen bir talimatın adresine bir kontrol aktarımını içerir. Kontrolün devri ileri, yeni bir talimatlar dizisini uygulamak için veya aynı adımları yeniden uygulamak için geri olabilir.
Sözdizimi
JMP talimatı, kontrol akışının hemen aktarıldığı bir etiket adı sağlar. JMP talimatının sözdizimi -
JMP label
Misal
Aşağıdaki kod parçası JMP talimatını göstermektedir -
MOV AX, 00 ; Initializing AX to 0
MOV BX, 00 ; Initializing BX to 0
MOV CX, 01 ; Initializing CX to 1
L20:
ADD AX, 01 ; Increment AX
ADD BX, AX ; Add AX to BX
SHL CX, 1 ; shift left CX, this in turn doubles the CX value
JMP L20 ; repeats the statements
Koşullu Atlama
Koşullu atlamada belirtilen bazı koşullar karşılanırsa, kontrol akışı bir hedef talimata aktarılır. Koşul ve verilere bağlı olarak çok sayıda koşullu atlama talimatı vardır.
Aşağıda, aritmetik işlemler için kullanılan imzalı verilerde kullanılan koşullu atlama talimatları verilmiştir -
Talimat | Açıklama | Test edilen bayraklar |
---|---|---|
JE / JZ | Eşit Atla veya Sıfırla Atla | ZF |
JNE / JNZ | Eşit Değil Atlama veya Sıfır Değil Atlama | ZF |
JG / JNLE | Daha Büyük Zıpla veya Daha Az Değil / Eşit Zıpla | OF, SF, ZF |
JGE / JNL | Daha Büyük / Eşittir veya Daha Az Değil Zıpla | OF, SF |
JL / JNGE | Daha Az Zıpla veya Büyük Değil / Eşit Zıpla | OF, SF |
JLE / JNG | Daha Az Atla / Eşit veya Daha Fazla Atla | OF, SF, ZF |
Mantıksal işlemler için kullanılan işaretsiz verilerde kullanılan koşullu atlama talimatları aşağıdadır -
Talimat | Açıklama | Test edilen bayraklar |
---|---|---|
JE / JZ | Eşit Atla veya Sıfırla Atla | ZF |
JNE / JNZ | Eşit Değil Atlama veya Sıfır Değil Atlama | ZF |
JA / JNBE | Yukarı Atla veya Aşağıya Atla / Eşit | CF, ZF |
JAE / JNB | Yukarı Atla / Eşittir veya Aşağıya Atla | CF |
JB / JNAE | Aşağı Atla veya Yukarıya Atla / Eşit | CF |
JBE / JNA | Aşağı Atla / Eşittir veya Yukarıya Atla | AF, CF |
Aşağıdaki koşullu atlama talimatlarının özel kullanımları vardır ve bayrakların değerini kontrol edin -
Talimat | Açıklama | Test edilen bayraklar |
---|---|---|
JXCZ | CX Sıfır ise atla | Yok |
JC | Taşınırsa Atla | CF |
JNC | Taşıma Yoksa Atla | CF |
JO | Taşarsa Atla | NIN-NİN |
JNO | Taşma Olmazsa Atla | NIN-NİN |
JP / JPE | Eşitliği Atla veya Eşitliği Atla | PF |
JNP / JPO | Eşlik Yok Atlama veya Eşlik Oranı Atlama | PF |
JS | Atlama İşareti (negatif değer) | SF |
JNS | İşaret Yok (pozitif değer) | SF |
J <koşul> yönerge kümesinin sözdizimi -
Misal,
CMP AL, BL
JE EQUAL
CMP AL, BH
JE EQUAL
CMP AL, CL
JE EQUAL
NON_EQUAL: ...
EQUAL: ...
Misal
Aşağıdaki program üç değişkenden en büyüğünü gösterir. Değişkenler çift basamaklı değişkenlerdir. Üç değişken num1, num2 ve num3 sırasıyla 47, 22 ve 31 değerlerine sahiptir -
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov ecx, [num1]
cmp ecx, [num2]
jg check_third_num
mov ecx, [num2]
check_third_num:
cmp ecx, [num3]
jg _exit
mov ecx, [num3]
_exit:
mov [largest], ecx
mov ecx,msg
mov edx, len
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov ecx,largest
mov edx, 2
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax, 1
int 80h
section .data
msg db "The largest digit is: ", 0xA,0xD
len equ $- msg
num1 dd '47'
num2 dd '22'
num3 dd '31'
segment .bss
largest resb 2
Yukarıdaki kod derlendiğinde ve yürütüldüğünde, aşağıdaki sonucu verir -
The largest digit is:
47
JMP talimatı döngüleri uygulamak için kullanılabilir. Örneğin, aşağıdaki kod parçacığı döngü gövdesini 10 kez çalıştırmak için kullanılabilir.
MOV CL, 10
L1:
<LOOP-BODY>
DEC CL
JNZ L1
Bununla birlikte, işlemci talimat seti yinelemenin uygulanması için bir grup döngü talimatı içerir. Temel LOOP komutu aşağıdaki sözdizimine sahiptir -
LOOP label
Nerede, etiket atlama talimatlarında olduğu gibi hedef talimatı tanımlayan hedef etikettir. LOOP talimatı,ECX register contains the loop count. Döngü talimatı yürütüldüğünde, ECX kaydı azaltılır ve kontrol, ECX kayıt değeri, yani sayaç sıfır değerine ulaşıncaya kadar hedef etikete atlar.
Yukarıdaki kod parçacığı şu şekilde yazılabilir:
mov ECX,10
l1:
<loop body>
loop l1
Misal
Aşağıdaki program ekrana 1'den 9'a kadar olan sayıları yazdırır -
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov ecx,10
mov eax, '1'
l1:
mov [num], eax
mov eax, 4
mov ebx, 1
push ecx
mov ecx, num
mov edx, 1
int 0x80
mov eax, [num]
sub eax, '0'
inc eax
add eax, '0'
pop ecx
loop l1
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .bss
num resb 1
Yukarıdaki kod derlendiğinde ve yürütüldüğünde, aşağıdaki sonucu verir -
123456789:
Sayısal veriler genellikle ikili sistemde temsil edilir. Aritmetik komutlar ikili veriler üzerinde çalışır. Numaralar ekranda görüntülendiğinde veya klavyeden girildiğinde ASCII formundadır.
Şimdiye kadar, ASCII formundaki bu girdi verilerini aritmetik hesaplamalar için ikiliye dönüştürdük ve sonucu tekrar ikiliye çevirdik. Aşağıdaki kod bunu göstermektedir -
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov eax,'3'
sub eax, '0'
mov ebx, '4'
sub ebx, '0'
add eax, ebx
add eax, '0'
mov [sum], eax
mov ecx,msg
mov edx, len
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov ecx,sum
mov edx, 1
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
msg db "The sum is:", 0xA,0xD
len equ $ - msg
segment .bss
sum resb 1
Yukarıdaki kod derlendiğinde ve yürütüldüğünde, aşağıdaki sonucu verir -
The sum is:
7
Bununla birlikte, bu tür dönüşümlerin bir yükü vardır ve montaj dili programlaması, sayıların ikili biçimde daha verimli bir şekilde işlenmesine izin verir. Ondalık sayılar iki biçimde gösterilebilir -
- ASCII formu
- BCD veya İkili Kodlu Ondalık form
ASCII Gösterimi
ASCII gösteriminde, ondalık sayılar ASCII karakter dizileri olarak saklanır. Örneğin, 1234 ondalık değeri -
31 32 33 34H
31H, 1 için ASCII değeridir, 32H, 2 için ASCII değeridir ve bu böyle devam eder. ASCII gösteriminde sayıları işlemek için dört talimat vardır -
AAA - Eklemeden Sonra ASCII Ayarı
AAS - Çıkarmadan Sonra ASCII Ayarı
AAM - Çarpma İşleminden Sonra ASCII Ayarı
AAD - ASCII Bölüm Öncesi Ayarla
Bu komutlar herhangi bir işlenen almaz ve gerekli işlenenin AL yazmacında olduğunu varsayar.
Aşağıdaki örnek, kavramı göstermek için AAS talimatını kullanır -
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
sub ah, ah
mov al, '9'
sub al, '3'
aas
or al, 30h
mov [res], ax
mov edx,len ;message length
mov ecx,msg ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov edx,1 ;message length
mov ecx,res ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
msg db 'The Result is:',0xa
len equ $ - msg
section .bss
res resb 1
Yukarıdaki kod derlendiğinde ve yürütüldüğünde, aşağıdaki sonucu verir -
The Result is:
6
BCD Temsilciliği
İki tür BCD gösterimi vardır -
- Ambalajsız BCD gösterimi
- Paketlenmiş BCD gösterimi
Paketlenmemiş BCD gösteriminde, her bayt bir ondalık basamağın ikili eşdeğerini depolar. Örneğin, 1234 sayısı -
01 02 03 04H
Bu numaraları işlemek için iki talimat vardır -
AAM - Çarpma İşleminden Sonra ASCII Ayarı
AAD - ASCII Bölüm Öncesi Ayarla
Dört ASCII ayarlama talimatı, AAA, AAS, AAM ve AAD, paketlenmemiş BCD gösterimi ile de kullanılabilir. Paketlenmiş BCD gösteriminde, her rakam dört bit kullanılarak saklanır. İki ondalık hane bir bayta paketlenmiştir. Örneğin, 1234 sayısı -
12 34H
Bu numaraları işlemek için iki talimat vardır -
DAA - Eklemeden Sonra Ondalık Ayar
DAS - Çıkarmadan Sonra Ondalık Ayar
Paketlenmiş BCD gösteriminde çarpma ve bölme desteği yoktur.
Misal
Aşağıdaki program iki adet 5 basamaklı ondalık sayı ekler ve toplamı görüntüler. Yukarıdaki kavramları kullanır -
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov esi, 4 ;pointing to the rightmost digit
mov ecx, 5 ;num of digits
clc
add_loop:
mov al, [num1 + esi]
adc al, [num2 + esi]
aaa
pushf
or al, 30h
popf
mov [sum + esi], al
dec esi
loop add_loop
mov edx,len ;message length
mov ecx,msg ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov edx,5 ;message length
mov ecx,sum ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
msg db 'The Sum is:',0xa
len equ $ - msg
num1 db '12345'
num2 db '23456'
sum db ' '
Yukarıdaki kod derlendiğinde ve yürütüldüğünde, aşağıdaki sonucu verir -
The Sum is:
35801
Önceki örneklerimizde zaten değişken uzunluklu dizeler kullandık. Değişken uzunluklu dizeler gerektiği kadar karakter içerebilir. Genel olarak, dizenin uzunluğunu iki yoldan biriyle belirtiriz -
- Dize uzunluğunu açıkça depolamak
- Nöbetçi bir karakter kullanmak
Dize uzunluğunu, konum sayacının mevcut değerini temsil eden $ konum sayaç sembolünü kullanarak açıkça saklayabiliriz. Aşağıdaki örnekte -
msg db 'Hello, world!',0xa ;our dear string
len equ $ - msg ;length of our dear string
$, msg dize değişkeninin son karakterinden sonraki baytı gösterir . Bu nedenle,$-msgdizenin uzunluğunu verir. Biz de yazabiliriz
msg db 'Hello, world!',0xa ;our dear string
len equ 13 ;length of our dear string
Alternatif olarak, dize uzunluğunu açıkça depolamak yerine bir dizeyi sınırlandırmak için sonda bir gözcü karakter içeren dizeleri depolayabilirsiniz. Sentinel karakter, bir dizede görünmeyen özel bir karakter olmalıdır.
Örneğin -
message DB 'I am loving it!', 0
Dize Talimatları
Her dizge talimatı bir kaynak işlenen, bir hedef işlenen veya her ikisini de gerektirebilir. 32 bitlik segmentler için, dize talimatları sırasıyla kaynak ve hedef işlenenleri işaret etmek için ESI ve EDI kayıtlarını kullanır.
16 bitlik segmentler için SI ve DI kayıtları sırasıyla kaynağı ve hedefi işaret etmek için kullanılır.
Dizeleri işlemek için beş temel talimat vardır. Onlar -
MOVS - Bu komut 1 Byte, Word veya Doubleword veriyi hafıza konumundan diğerine taşır.
LODS- Bu talimat bellekten yüklenir. İşlenen bir baytlık ise, AL yazmacına yüklenir, işlenen bir sözcükse, AX yazmacına yüklenir ve EAX yazmacına bir çift sözcük yüklenir.
STOS - Bu komut, kayıttan (AL, AX veya EAX) verileri belleğe kaydeder.
CMPS- Bu talimat hafızadaki iki veri öğesini karşılaştırır. Veriler bir bayt boyutunda, sözcükte veya çift sözcükte olabilir.
SCAS - Bu talimat, bir kaydın (AL, AX veya EAX) içeriğini bellekteki bir öğenin içeriği ile karşılaştırır.
Yukarıdaki talimatların her biri bir bayt, kelime ve çift kelime versiyonuna sahiptir ve dize talimatları bir tekrarlama öneki kullanılarak tekrarlanabilir.
Bu talimatlar ES: DI ve DS: SI kayıt çiftlerini kullanır; burada DI ve SI kayıtları, bellekte depolanan baytlara başvuran geçerli ofset adresleri içerir. SI normalde DS (veri segmenti) ile ilişkilidir ve DI her zaman ES (ekstra segment) ile ilişkilidir.
DS: SI (veya ESI) ve ES: DI (veya EDI) kayıtları sırasıyla kaynak ve hedef işlenenleri işaret eder. Kaynak işleneninin DS: SI (veya ESI) olduğu ve hedef işleneninin bellekteki ES: DI (veya EDI) olduğu varsayılır.
16 bit adresler için SI ve DI kayıtları kullanılır ve 32 bit adresler için ESI ve EDI kayıtları kullanılır.
Aşağıdaki tablo, dizi komutlarının çeşitli sürümlerini ve işlenenlerin varsayılan alanını sağlar.
Temel Talimat | Operandlar | Bayt İşlemi | Kelime İşlemi | Çift kelime İşlemi |
---|---|---|---|---|
MOVS | ES: DI, DS: SI | MOVSB | MOVSW | MOVSD |
LODLAR | AX, DS: SI | LODSB | LODSW | LODSD |
STOS | ES: DI, AX | STOSB | STOSW | STOSD |
CMPS | DS: SI, ES: DI | CMPSB | CMPSW | CMPSD |
SCAS | ES: DI, AX | SCASB | SCASW | SCASD |
Tekrarlama Önekleri
REP öneki, bir dizi talimatından önce ayarlandığında, örneğin - REP MOVSB, CX yazmacına yerleştirilen bir sayaca bağlı olarak komutun tekrarına neden olur. REP komutu yürütür, CX'i 1 azaltır ve CX'in sıfır olup olmadığını kontrol eder. Komut işlemeyi CX sıfır olana kadar tekrarlar.
Yön Bayrağı (DF) operasyonun yönünü belirler.
- İşlemi soldan sağa yapmak için CLD (Clear Direction Flag, DF = 0) kullanın.
- İşlemi sağdan sola yapmak için STD'yi (Yön Bayrağını Ayarla, DF = 1) kullanın.
REP ön eki aşağıdaki varyasyonlara da sahiptir:
REP: Koşulsuz tekrardır. CX sıfır olana kadar işlemi tekrarlar.
REPE veya REPZ: Koşullu tekrardır. Sıfır bayrağı eşit / sıfırı gösterirken işlemi tekrarlar. ZF eşit / sıfır olmadığını gösterdiğinde veya CX sıfır olduğunda durur.
REPNE veya REPNZ: Aynı zamanda koşullu tekrardır. Sıfır bayrağı eşit / sıfır olmadığını gösterirken işlemi tekrarlar. ZF eşit / sıfır gösterdiğinde veya CX sıfıra düşürüldüğünde durur.
Assembler için veri tanımlama direktiflerinin değişkenler için depolama ayırmak için kullanıldığını daha önce tartışmıştık. Değişken, belirli bir değerle de başlatılabilir. Başlatılan değer, onaltılık, onluk veya ikili biçimde belirtilebilir.
Örneğin, aşağıdaki yollardan biriyle 'aylar' kelimesini tanımlayabiliriz -
MONTHS DW 12
MONTHS DW 0CH
MONTHS DW 0110B
Veri tanımlama yönergeleri, tek boyutlu bir diziyi tanımlamak için de kullanılabilir. Tek boyutlu bir sayı dizisi tanımlayalım.
NUMBERS DW 34, 45, 56, 67, 75, 89
Yukarıdaki tanım, her biri 34, 45, 56, 67, 75, 89 sayılarıyla başlayan altı kelimeden oluşan bir dizi bildirir. Bu, 2x6 = 12 bayt ardışık bellek alanı tahsis eder. İlk sayının sembolik adresi NUMARALAR olacak ve ikinci numaranınki NUMBERS + 2 vb. Olacaktır.
Başka bir örnek alalım. 8 boyutunda envanter adlı bir dizi tanımlayabilir ve tüm değerleri sıfır ile başlatabilirsiniz.
INVENTORY DW 0
DW 0
DW 0
DW 0
DW 0
DW 0
DW 0
DW 0
Hangisi kısaltılabilir -
INVENTORY DW 0, 0 , 0 , 0 , 0 , 0 , 0 , 0
TIMES yönergesi, aynı değere birden çok ilklendirme için de kullanılabilir. TIMES kullanılarak INVENTORY dizisi şu şekilde tanımlanabilir:
INVENTORY TIMES 8 DW 0
Misal
Aşağıdaki örnek, üç değeri depolayan 3 öğeli bir x dizisi tanımlayarak yukarıdaki kavramları gösterir: 2, 3 ve 4. Diziye değerleri ekler ve toplamı 9 -
section .text
global _start ;must be declared for linker (ld)
_start:
mov eax,3 ;number bytes to be summed
mov ebx,0 ;EBX will store the sum
mov ecx, x ;ECX will point to the current element to be summed
top: add ebx, [ecx]
add ecx,1 ;move pointer to next element
dec eax ;decrement counter
jnz top ;if counter not 0, then loop again
done:
add ebx, '0'
mov [sum], ebx ;done, store result in "sum"
display:
mov edx,1 ;message length
mov ecx, sum ;message to write
mov ebx, 1 ;file descriptor (stdout)
mov eax, 4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax, 1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
global x
x:
db 2
db 4
db 3
sum:
db 0
Yukarıdaki kod derlendiğinde ve yürütüldüğünde, aşağıdaki sonucu verir -
9
Assembly dili programları boyut olarak büyük olma eğiliminde olduğundan, prosedürler veya alt yordamlar assembly dilinde çok önemlidir. Prosedürler bir adla tanımlanır. Bu ismin ardından, iyi tanımlanmış bir işi gerçekleştiren prosedürün gövdesi açıklanmaktadır. Prosedürün sonu bir dönüş ifadesiyle belirtilir.
Sözdizimi
Bir prosedürü tanımlamak için sözdizimi aşağıdadır -
proc_name:
procedure body
...
ret
Prosedür, CALL komutu kullanılarak başka bir işlevden çağrılır. CALL talimatı, çağrılan prosedürün adını aşağıda gösterildiği gibi bir argüman olarak içermelidir -
CALL proc_name
Çağrılan prosedür, RET komutunu kullanarak kontrolü çağırma prosedürüne döndürür.
Misal
Bize çok basit bir işlem adında yazalım toplamı ECX ve EDX saklanan değişkenler kayıt ve EAX kayıt döner toplamı ekler -
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov ecx,'4'
sub ecx, '0'
mov edx, '5'
sub edx, '0'
call sum ;call sum procedure
mov [res], eax
mov ecx, msg
mov edx, len
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov ecx, res
mov edx, 1
mov ebx, 1 ;file descriptor (stdout)
mov eax, 4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
sum:
mov eax, ecx
add eax, edx
add eax, '0'
ret
section .data
msg db "The sum is:", 0xA,0xD
len equ $- msg
segment .bss
res resb 1
Yukarıdaki kod derlendiğinde ve yürütüldüğünde, aşağıdaki sonucu verir -
The sum is:
9
Veri Yapısını Yığınlar
Yığın, bellekteki verilerin depolanabildiği ve yığının 'üstü' olarak adlandırılan bir konumdan kaldırılabildiği dizi benzeri bir veri yapısıdır. Depolanması gereken veriler yığına 'itilir' ve alınacak veriler yığından dışarı çıkarılır. Yığın bir LIFO veri yapısıdır, yani ilk depolanan veri en son alınır.
Assembly dili, yığın işlemleri için iki talimat sağlar: PUSH ve POP. Bu talimatların söz dizimi şu şekildedir:
PUSH operand
POP address/register
Yığın segmentinde ayrılan bellek alanı, yığını uygulamak için kullanılır. SS ve ESP (veya SP) kayıtları yığını uygulamak için kullanılır. Yığına eklenen son veri öğesini işaret eden yığının tepesine SS: ESP yazmacı işaret edilir, burada SS yazmacı yığın segmentinin başlangıcını gösterir ve SP (veya ESP) ofseti yığın segmenti.
Yığın uygulaması aşağıdaki özelliklere sahiptir -
Bir tek words veya doublewords bayt yerine yığına kaydedilebilir.
Yığın ters yönde, yani alt bellek adresine doğru büyür
Yığının tepesi, yığına eklenen son öğeyi gösterir; eklenen son kelimenin alt baytını gösterir.
Kayıtların değerlerini bir miktar kullanım için kullanmadan önce yığında depolamayı tartıştığımız gibi; şu şekilde yapılabilir -
; Save the AX and BX registers in the stack
PUSH AX
PUSH BX
; Use the registers for other purpose
MOV AX, VALUE1
MOV BX, VALUE2
...
MOV VALUE1, AX
MOV VALUE2, BX
; Restore the original values
POP BX
POP AX
Misal
Aşağıdaki program tüm ASCII karakter setini görüntüler. Ana program , ASCII karakter setini görüntüleyen display adlı bir prosedürü çağırır .
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
call display
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
display:
mov ecx, 256
next:
push ecx
mov eax, 4
mov ebx, 1
mov ecx, achar
mov edx, 1
int 80h
pop ecx
mov dx, [achar]
cmp byte [achar], 0dh
inc byte [achar]
loop next
ret
section .data
achar db '0'
Yukarıdaki kod derlendiğinde ve yürütüldüğünde, aşağıdaki sonucu verir -
0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}
...
...
Özyinelemeli prosedür, kendisini çağıran bir prosedürdür. İki tür özyineleme vardır: doğrudan ve dolaylı. Doğrudan özyinelemede, prosedür kendisini çağırır ve dolaylı özyinelemede, birinci prosedür ikinci bir prosedürü çağırır ve bu da ilk prosedürü çağırır.
Özyineleme, çok sayıda matematiksel algoritmada gözlemlenebilir. Örneğin, bir sayının faktöriyelini hesaplama durumunu düşünün. Bir sayının faktöriyeli denklemle verilir -
Fact (n) = n * fact (n-1) for n > 0
Örneğin: 5 faktöriyeli 1 x 2 x 3 x 4 x 5 = 5 x faktöriyeli 4'tür ve bu, özyinelemeli bir prosedürü göstermenin iyi bir örneği olabilir. Her özyinelemeli algoritmanın bir bitiş koşulu olmalıdır, yani programın özyinelemeli çağrısı, bir koşul yerine getirildiğinde durdurulmalıdır. Faktöriyel algoritma durumunda, son koşula n 0 olduğunda ulaşılır.
Aşağıdaki program, factorial n'nin assembly dilinde nasıl uygulandığını gösterir. Programı basit tutmak için faktöriyel 3'ü hesaplayacağız.
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov bx, 3 ;for calculating factorial 3
call proc_fact
add ax, 30h
mov [fact], ax
mov edx,len ;message length
mov ecx,msg ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov edx,1 ;message length
mov ecx,fact ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
proc_fact:
cmp bl, 1
jg do_calculation
mov ax, 1
ret
do_calculation:
dec bl
call proc_fact
inc bl
mul bl ;ax = al * bl
ret
section .data
msg db 'Factorial 3 is:',0xa
len equ $ - msg
section .bss
fact resb 1
Yukarıdaki kod derlendiğinde ve yürütüldüğünde, aşağıdaki sonucu verir -
Factorial 3 is:
6
Bir makro yazmak, assembly dilinde modüler programlamayı sağlamanın başka bir yoludur.
Makro, bir adla atanan ve programın herhangi bir yerinde kullanılabilen bir talimatlar dizisidir.
NASM'de makrolar şu şekilde tanımlanır: %macro ve %endmacro direktifler.
Makro,% makro yönergesi ile başlar ve% endmacro yönergesi ile biter.
Makro tanımı için Sözdizimi -
%macro macro_name number_of_params
<macro body>
%endmacro
Nerede, number_of_params belirtir sayı parametreleri, macro_name makro belirtir ismi.
Makro, makro adı ve gerekli parametreler kullanılarak çağrılır. Bir programda bazı komut dizilerini birçok kez kullanmanız gerektiğinde, bu talimatları bir makroya koyabilir ve her zaman talimatları yazmak yerine onu kullanabilirsiniz.
Örneğin, programlar için çok yaygın bir ihtiyaç, ekrana bir karakter dizisi yazmaktır. Bir karakter dizisini görüntülemek için aşağıdaki talimat sırasına ihtiyacınız vardır -
mov edx,len ;message length
mov ecx,msg ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
Yukarıdaki bir karakter dizisinin görüntülenmesi örneğinde, EAX, EBX, ECX ve EDX kayıtları INT 80H fonksiyon çağrısı tarafından kullanılmıştır. Bu nedenle, ekranda her görüntülemeniz gerektiğinde, bu yazmaçları yığına kaydetmeniz, INT 80H'yi çağırmanız ve ardından yazmaçların orijinal değerini yığından geri yüklemeniz gerekir. Bu nedenle, verileri kaydetmek ve geri yüklemek için iki makro yazmak faydalı olabilir.
IMUL, IDIV, INT vb. Gibi bazı komutların bazı bilgilerin belirli kayıtlarda saklanmasına ve hatta bazı belirli kayıt (lar) da değerlerin dönmesine ihtiyaç duyduğunu gözlemledik. Program önemli verileri saklamak için zaten bu kayıtları kullanıyorsa, bu kayıtlardan gelen mevcut veriler yığına kaydedilmeli ve komut yürütüldükten sonra geri yüklenmelidir.
Misal
Aşağıdaki örnek, makroların tanımlanmasını ve kullanılmasını gösterir -
; A macro with two parameters
; Implements the write system call
%macro write_string 2
mov eax, 4
mov ebx, 1
mov ecx, %1
mov edx, %2
int 80h
%endmacro
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
write_string msg1, len1
write_string msg2, len2
write_string msg3, len3
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
msg1 db 'Hello, programmers!',0xA,0xD
len1 equ $ - msg1 msg2 db 'Welcome to the world of,', 0xA,0xD len2 equ $- msg2
msg3 db 'Linux assembly programming! '
len3 equ $- msg3
Yukarıdaki kod derlendiğinde ve yürütüldüğünde, aşağıdaki sonucu verir -
Hello, programmers!
Welcome to the world of,
Linux assembly programming!
Sistem, herhangi bir girdi veya çıktı verisini bayt akışı olarak kabul eder. Üç standart dosya akışı vardır -
- Standart giriş (stdin),
- Standart çıktı (standart çıktı) ve
- Standart hata (stderr).
Dosya Tanımlayıcı
Bir file descriptorbir dosyaya dosya kimliği olarak atanan 16 bitlik bir tamsayıdır. Yeni bir dosya oluşturulduğunda veya mevcut bir dosya açıldığında, dosyaya erişim için dosya tanımlayıcı kullanılır.
Standart dosya akışlarının dosya tanımlayıcısı - stdin, stdout ve stderr sırasıyla 0, 1 ve 2'dir.
Dosya İşaretçisi
Bir file pointerbayt cinsinden dosyada sonraki bir okuma / yazma işleminin yerini belirtir. Her dosya bir bayt dizisi olarak kabul edilir. Her açık dosya, dosyanın başlangıcına göre bayt cinsinden bir uzaklık belirten bir dosya işaretçisi ile ilişkilendirilir. Bir dosya açıldığında, dosya işaretçisi sıfıra ayarlanır.
Dosya İşleme Sistemi Çağrıları
Aşağıdaki tablo dosya işlemeyle ilgili sistem çağrılarını kısaca açıklamaktadır -
% eax | İsim | % ebx | % ecx | % edx |
---|---|---|---|---|
2 | sys_fork | struct pt_regs | - | - |
3 | sys_read | imzasız int | karakter * | size_t |
4 | sys_write | imzasız int | const karakter * | size_t |
5 | sys_open | const karakter * | int | int |
6 | sys_close | imzasız int | - | - |
8 | sys_creat | const karakter * | int | - |
19 | sys_lseek | imzasız int | off_t | imzasız int |
Sistem çağrılarını kullanmak için gerekli adımlar, daha önce tartıştığımız gibi aynıdır -
- Sistem çağrı numarasını EAX kaydına girin.
- Sistem çağrısındaki argümanları EBX, ECX vb. Kayıtlarında saklayın.
- İlgili kesmeyi arayın (80h).
- Sonuç genellikle EAX kaydına döndürülür.
Dosya Oluşturma ve Açma
Bir dosya oluşturmak ve açmak için aşağıdaki görevleri gerçekleştirin -
- EAX kaydına 8 numaralı sys_creat () sistem çağrısını koyun.
- Dosya adını EBX yazmacına koyun.
- Dosya izinlerini ECX kaydına koyun.
Sistem çağrısı, EAX kaydında oluşturulan dosyanın dosya tanımlayıcısını döndürür; hata durumunda, hata kodu EAX kaydındadır.
Varolan bir Dosyayı Açmak
Mevcut bir dosyayı açmak için aşağıdaki görevleri gerçekleştirin -
- EAX kaydına 5 numaralı sys_open () sistem çağrısını koyun.
- Dosya adını EBX yazmacına koyun.
- Dosya erişim modunu ECX kaydına koyun.
- Dosya izinlerini EDX kaydına koyun.
Sistem çağrısı, EAX kaydında oluşturulan dosyanın dosya tanımlayıcısını döndürür; hata durumunda, hata kodu EAX kaydındadır.
Dosya erişim modları arasında en yaygın olarak kullanılanlar şunlardır: salt okunur (0), salt yazılır (1) ve okuma-yazma (2).
Dosyadan Okuma
Bir dosyadan okumak için aşağıdaki görevleri gerçekleştirin -
EAX kaydına 3 numaralı sys_read () sistem çağrısını koyun.
Dosya tanımlayıcısını EBX yazmacına koyun.
İşaretçiyi ECX yazmacındaki giriş arabelleğine koyun.
Tampon boyutunu, yani okunacak bayt sayısını EDX yazmacına koyun.
Sistem çağrısı, EAX kaydında okunan bayt sayısını döndürür, hata durumunda, hata kodu EAX kaydındadır.
Dosyaya Yazmak
Bir dosyaya yazmak için aşağıdaki görevleri gerçekleştirin -
EAX kaydına 4 numaralı sys_write () sistem çağrısını koyun.
Dosya tanımlayıcısını EBX yazmacına koyun.
İşaretçiyi ECX yazmacındaki çıktı tamponuna koyun.
Tampon boyutunu, yani yazılacak bayt sayısını EDX yazmacına koyun.
Sistem çağrısı, EAX kaydına yazılan gerçek bayt sayısını döndürür, hata durumunda, hata kodu EAX kaydındadır.
Bir Dosyayı Kapatmak
Bir dosyayı kapatmak için aşağıdaki görevleri gerçekleştirin -
- EAX kaydına sys_close () numarası 6 olan sistem çağrısını koyun.
- Dosya tanımlayıcısını EBX yazmacına koyun.
Sistem çağrısı, hata durumunda EAX kaydındaki hata kodunu döndürür.
Bir Dosyayı Güncelleme
Bir dosyayı güncellemek için aşağıdaki görevleri gerçekleştirin -
- EAX kaydına sistem çağrısı sys_lseek () numarası 19 koyun.
- Dosya tanımlayıcısını EBX yazmacına koyun.
- Ofset değerini ECX kaydına koyun.
- Ofset için referans konumunu EDX kaydına koyun.
Referans konumu şunlar olabilir:
- Dosyanın başlangıcı - değer 0
- Geçerli konum - değer 1
- Dosya sonu - değer 2
Sistem çağrısı, hata durumunda EAX kaydındaki hata kodunu döndürür.
Misal
Aşağıdaki program, myfile.txt adlı bir dosya oluşturup açar ve bu dosyaya bir 'Tutorials Point'e Hoş Geldiniz' metni yazar. Daha sonra, program dosyadan okur ve verileri info adlı bir arabelleğe kaydeder . Son olarak, bilgi içinde depolanan metni görüntüler .
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
;create the file
mov eax, 8
mov ebx, file_name
mov ecx, 0777 ;read, write and execute by all
int 0x80 ;call kernel
mov [fd_out], eax
; write into the file
mov edx,len ;number of bytes
mov ecx, msg ;message to write
mov ebx, [fd_out] ;file descriptor
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
; close the file
mov eax, 6
mov ebx, [fd_out]
; write the message indicating end of file write
mov eax, 4
mov ebx, 1
mov ecx, msg_done
mov edx, len_done
int 0x80
;open the file for reading
mov eax, 5
mov ebx, file_name
mov ecx, 0 ;for read only access
mov edx, 0777 ;read, write and execute by all
int 0x80
mov [fd_in], eax
;read from file
mov eax, 3
mov ebx, [fd_in]
mov ecx, info
mov edx, 26
int 0x80
; close the file
mov eax, 6
mov ebx, [fd_in]
int 0x80
; print the info
mov eax, 4
mov ebx, 1
mov ecx, info
mov edx, 26
int 0x80
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
file_name db 'myfile.txt'
msg db 'Welcome to Tutorials Point'
len equ $-msg
msg_done db 'Written to file', 0xa
len_done equ $-msg_done
section .bss
fd_out resb 1
fd_in resb 1
info resb 26
Yukarıdaki kod derlendiğinde ve yürütüldüğünde, aşağıdaki sonucu verir -
Written to file
Welcome to Tutorials Point
sys_brk()sistem çağrısı, belleği daha sonra taşımaya gerek kalmadan ayırmak için çekirdek tarafından sağlanır. Bu çağrı, bellekteki uygulama görüntüsünün hemen arkasında bellek ayırır. Bu sistem işlevi, veri bölümünde mevcut en yüksek adresi ayarlamanıza olanak tanır.
Bu sistem çağrısı, ayarlanması gereken en yüksek bellek adresi olan bir parametre alır. Bu değer EBX kaydında saklanır.
Herhangi bir hata durumunda sys_brk () -1 ile döner veya negatif hata kodunu kendisi döndürür. Aşağıdaki örnek, dinamik bellek tahsisini gösterir.
Misal
Aşağıdaki program sys_brk () sistem çağrısını kullanarak 16kb bellek ayırır -
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov eax, 45 ;sys_brk
xor ebx, ebx
int 80h
add eax, 16384 ;number of bytes to be reserved
mov ebx, eax
mov eax, 45 ;sys_brk
int 80h
cmp eax, 0
jl exit ;exit, if error
mov edi, eax ;EDI = highest available address
sub edi, 4 ;pointing to the last DWORD
mov ecx, 4096 ;number of DWORDs allocated
xor eax, eax ;clear eax
std ;backward
rep stosd ;repete for entire allocated area
cld ;put DF flag to normal state
mov eax, 4
mov ebx, 1
mov ecx, msg
mov edx, len
int 80h ;print a message
exit:
mov eax, 1
xor ebx, ebx
int 80h
section .data
msg db "Allocated 16 kb of memory!", 10
len equ $ - msg
Yukarıdaki kod derlendiğinde ve yürütüldüğünde, aşağıdaki sonucu verir -
Allocated 16 kb of memory!