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.gzbulunduğu Linux kaynak arşivini indirin X.XX.

  • Arşivi, bir alt dizin oluşturan bir dizine açın nasm-X. XX.

  • cd nasm-X.XXve 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!