Asembler x86

S Vikipedije, slobodne enciklopedije

x86 asemblerski jezik je familija unazad-kompatibilnih asemblerskih jezika, koji daju određeni nivo kompatibilnosti sve do Intel 8008. x86 asemblerski jezici se koriste za pravljenje objektnog koda za procesore iz klase x86. Kao i svi asemblerski jezici, koristi kratku mnemotehniku za reprezentovanje osnovnih instrukcija koje CPJ može da može da razume i prati. Kompajleri ponekad prave asemblerski kod pri prevodu asemblerskih jezika u mašinski jezik. Asemblerski jezik se smatra programskim jezikom, i on je mašinski specifičan i jezik niskog nivoa. Ovaj jezik se koristi za male ugrađene sisteme u realnom vremenu, ili jezgra operativnih sistema.

Istorija[uredi | uredi izvor]

Intel 8088 i 8086 su bili prvi procesori koji su imali x86 skup instrukcija. Ovi 16-bitni procesori su bili evolucija prethodne generacije 8-bitnih procesora od kojih su nasledili mnoge karakteristike i instrukcije, koji su prošireni za 16-bitnu eru. 8088 i 8086 su koristili 20-bitnu adresnu magistralu i 16-bitne unutrašnje registre, ali 8086 je imao 16-bitnu magistralu za podatke, a 8088 8-bitni. x86 asemblerski jezik podržava razne verzije koje su pratile ove, od Intelovih 80188, 80186, 80286, 80386,80486, Pentium, Pentium Pro, i tako dalje, kao i AMD i Sajriksove 5x86 i K6 procesore i NEC V20. Termin x86 odnosi se na CPD koji može da radi na originalnom asemblerskom jeziku.

Moderni x86 instruckijski skup je nadskup 8086 skupa instrukcija i serija ekstenzija ovom skupu instrukcija koje je počelo sa Intel 8080 procesorom. Skoro potpuna binarna kompatibilnost unazad postoji između Intel 8086 čipa i svih čipova do trenutne generacije x86 procesora. U praksi je normalno da se koriste instrukcije koje će raditi na bilo čemu posle Intel 80386 ili Pentijuma, mada su u zadnjim godinama razni operativni sistemi počeli da zahtevaju modernije procesore ili bar da podržavaju novije ekstenzije za instrukcijski skup.

Mnemotehnika i operacioni kodovi[uredi | uredi izvor]

Svaka x86 montažna instrukcija je predstavljena mnemotehnikom koja kombinovana sa jednim ili više operanada, može da se pretvori u jedan ili više operacionih kodova (opkoda). NOP komanda se prevodi u 0x90, a HLT instrukcija se prevodi u 0xF4.

Sinstaksa[uredi | uredi izvor]

x86 asemblerski jezik ima dve glavne branše sintaksi: Intel sintaksa i ATiT sintaksa. Intel sintaksa je domnantna u DOS-u i Microsoft Windows svetu, a ATiT je dominantna u Juniks svetu, pošto je stvorena u ATiT Belovim laboratoriji. Ovde je pregled glavnih razlika između Intel i ATiT sintaksi:

ATiT Intel
redosled parametara Izvor pre odredišta

eax := 5 je mov $5, %eax

Odredište pre izvora

eax := 5 je mov eax, 5

Parameter Size Na mnemotehniku se stavlja sufiks sa pismom koje indijuje veličinu operanada ("q" za qword, "l" za long (dword), "w" za word, i "b" za bajt)

addl $4, %esp

Izvedeno iz imena registra koji se koristi (rax, eax, ax, al impliciraju q,l,w,b tim redom)
add   esp, 4
Sigili trenutne vrednosti Sa prefiksom "$", i registri moraju imati prefiks "%" Asembler automatski detektuje tip simbola, da li su registri, konstante, ili nešto drugo.
Efektivne adrese Generalna sintaksa DISP(BASE,INDEX,SCALE)

Primer:

movl mem_location(%ebx,%ecx,4), %eax
Koriste promenjive, i moraju da budu u uglastim zagradama; dodatno, veličinske reči kao byte, word, ili dword moraju biti korišćeni.

Primer:

mov eax, dword [ebx + ecx*4 + mem_location]

Mnogi x86 asembelri koriste Intel sintaksu, uključujući MASM, TASM, NASM, FASM, i JASM. GAS je podržavao obe sintakse pod .intel_sintaks direktivom.

Registri[uredi | uredi izvor]

x86 procesori imaju kolekciju registara koja je dozvoljena za skladištenje binarnih podataka. Zajedno se podaci i adresni registri zovu generalni registri. Svaki registar ima specijalnu primenu.

  • AX množenje-deljenje, vađenje i čuvanje stringa
  • CX brojač za operacije nad stringom
  • DX port adresa za IN i OUT
  • BX registar indeksa za MOVE
  • SP pokazju na vrh steka
  • BP pokazuje na bazu steka
  • SI pokzuje na izvor u strim operacijama
  • DI pokazuje na destinaciju u strim operacijama

Zajedno sa generalnim registrima, tu su obično i:

  • IP instrukcioni pokazivač
  • Zastave
  • Segmentni registri (CS, DS, ES, FS, GS, SS) koji određuju gde 64k segment počinje (nema FS i GS u 80286 i ranijim)
  • Dodatni ekstenzioni registri (MMX, 3DNow!, SSE, itd.) (samo Pentijum i kasniji).

IP registar pokazuje na memorijski ofset sledeće instrukcije u kodnom segmentu (pokazuje na prvi bajt instrukcije). Programer ne može pristupiti IP registru direktno. x86 registri se mogu koristiti primenom MOV instrukcija. Na primer:

mov ax, 1234h
mov bx, ax

kopira vrednost 1234h (4660d) u registar AX i onda kopira vrednost AX registra u BX registar (Intelova sintaksa).

Segmnetntno adresiranje[uredi | uredi izvor]

x86 arhitektura u realnom i virtuelnom 8086 režimu koristi proces koji se zove segmentacija za adresiranje memorije, a ne ravni memorijski model koji se koristi u raznim drugim okruženjima. Segmentacija se sastoji iz komponovanja memorijske adrese iz dva dela, segmenta i ofseta. Segment pokazuje na početak grupe od 64 kB adresa i ofset određuje koliko je otakle udaljena željena adresa. U segmentnom adresiranju, dva regustra su potrebna za kompletiranje memorijske adrese: jedan da drži segment, a drugi da drži ofset. Da bi se ovo prevelo na ravni memorijski model, segmentna vrednost je pomerena za 4 bita ulevo (ekvavilentno množenju sa 16) i onda dodato na ofset da se napravi cela adresa, što dozvoljava lomljenje 64k barijere kroz pametan izbor adresa, iako to čini programiranje kompleksnijim.

U realnom (zaštićenom) režimu, ako DS sadrži heksadecimalnu vrednost 0xDEAD i DX sadrži broj 0xCAFE oni bi zajedno pokazivali na adresu 0xDEAD * 0x10 + 0xCAFE = 0xEB5CE. Stoga, CPJ može adresirati do 1.048.576 bajtova (1 MB) u realnom režimu. Mešajući segmentnu i ofset vrednost nalazimo 20-bitnu adresu.

Originalni IBM PC je zabranjivao programe veće od 640 kB ali proširena memorijska specifikacija je korišćena za sprovođenje banke prekidačke šeme koja se nije koristila kada su kasniji operativni sistemi kao što je Windows, koristili veće adresne opsege novijih procesora i sproveli svoje šeme virtuelne memorije.

Zaštićeni režim je započeo sa Intelom 80386. Nekoliko nedostataka, kao što je nemogućnost pristupu BIOS-u i nemogućnost za vraćanjem na realni režim bez resetovanja procesora su onemogućili široko korišćenje. 80286 je takođe bio ograničen na adresnu memoriju u 16-bitnim segmentima, što znači da se može adresirati samo 64 kB memorije odjednom. Za pristup proširenoj funkcionalnosti 80286 procesor bi postavio procesor u zaštićeni režim, što bi omogućilo 24-bitno adresiranje i 16 MB memorije.

U zaštićenom režimu, segmentni selektor se može rastaviti na tri dela: 13-bitni indeks, indikator table koji određuje da li je ulaz u GDT ili LDT i dvobitni Requested Privilege Level.

Kada se govori o adresi sa segmentom, i ofsetiranju notacije segmenta, ofset se koristi, pa se u gornjem primeru ravna adresa 0xEB5CE može napisati kao 0xDEAD:0xCAFE ili kao segment i ofset registrovanog para; DS:DX.

Postoje specijalne kombinacije segmentnih registara i generalnih registara koje pokazuju na bitne adrese:

  • CS:IP (CS je Code Segment, IP je Instruction Pointer) pokazuje na adresu sa koje će procesor uzeti sledeći kodni bajt.
  • SS:SP (SS je Stack Segment, SP je Stack Pointer) pokazuje na adresu vrha steka, odnosno na poslednji stavljen bajt.
  • DS:SI (DS je Data Segment, SI je Source Index) je često korišćen za pokazivanje na string podatke koji se trebaju kopirati na ES:DI.
  • ES:DI (ES je Extra Segment, DI je Destination Index) je često korišćen za pokazivanje na odredište za kopiranje stringa, kao što je navedeno gore.

Intel 80386 ima tri operativna režima: realni, zaštićeni i virtuelni režim. Zaštićeni režim, koji je prvi put bio u 80286 je proširen za dopuštanje da 80386 adresira do 4 GB memorije, potpuno novi 8086 režim (VM86) je omogućio pokretanje jednog ili više realno-režimnih programa u zaštićenom okruženju koje je emuliralo realni režim, iako neku programi nisu bili kompatibilni (tipično zbog trikova u vezi sa adresiranjem memorije ili korišćenjem nespecifiranih opkodova).

Proširenje zaštićenog režima 32-bitnog ravnog memorijskog modela 80386-ice je možda najbitnija promena u familiji x86 procesora sve dok AMD nije izbacio x86-64 u 2003, pošto je pomoglo veliko primanje Windows-a 3.1 (koji se oslanjao na zaštićeni režim) pošto je Windows sada mogao da pokreće više aplikacija odjednom, uključujući DOS alpikcaije, korišćenjem virtuelne memorije i prostog multitaskinga.

Režimi izvršavanja[uredi | uredi izvor]

x86 procesori podržavaju pet režima operacija za x86 kod, Realni režim, Zaštićeni režim, Dugi režim, Virtuelni 86 režim, i Režim za sistemski menadžment, u kom su neke instrukcije dostupne a neke nisu. 16-bitni podskup instrukcija je dostupan u realnom režimu (svi x86 procesori), 16-bitni zaštićeni režim (80286 pa nadalje), V86 režim (80386 pa nadalje) i SMM (Intel i386SL, i486 i kasniji). U 32-bitnom zaštićenom režimu (Intel 80386 pa nadalje), 32-bitne instrukcije (uključukući kasnija proširenja) su takođe dostupni; u dugom režimu (AMD Opteron pa nadalje), 64-bitne instrukcije, i više registara su takođe dostupni. Instrukcioni skup je u svakom režima ali mmorijsko adresiranje i veličina reči variraju, što zahteva drugačije programerske strategije.

Režimi u kojima se x86 kod može izvršiti su:

  • Realni režim (16-bitni)
  • Zaštićeni režim (16-bitni i 32-bitni)
  • Dugi režim (64-bitni)
  • Virtuelni 8086 režim (16-bitni)
  • Režim za menadžment sistema (16-bitni)

Prekidački režimi[uredi | uredi izvor]

Procesor ulazi u realni režim odmah nakon paljenja, tako da operativni sistem ili neki drugi program moraju eksplicitno da ga promene na drugi režim ako želi da radi u bilo čemu osim u realnom režimu. Prekidački režimi su omogućeni modifikacijom određenih bitova procesorskih kontrolnih registra iako je neka priprema neophodna u najvećem broju slučajeva, i neko čišćenje posle menjanja.

Tipovi instrukcija[uredi | uredi izvor]

Generalno, funkcije modernog x86 skupa instrukcija su:

  • Kompaktno kodiranje
    • Promenjiva dužina i svrstavanje su nezavisni (kodirani kao mali endian, kao i svi podaci u x86 arhitekturi)
    • Uglanom jednoadresne ili dvoadresne instrukcije, odnosno prvi oprerand je i destinacija.
    • Memorijski operandi i kao izvor i kao destinacija su podržani (često korišćeni za čitanje i pisanje stek elemenata adresiranih pomoću malih trenutnih ofseta).
    • I generalno i implicitno korišćenje registara. Iako su svih sedam generalnih registara u 32-bitnom režimu, i svih 15 generalnih registara u 64-bitnom režim se mogu koristiti kao alumulatori ili za adresiranje, većina njih je implicitno korišćena za specijalne instrukcije. Pogođeni registri onda moraju da budu sačuvani.
  • Pravi kondicione flegove implicitno kroz većinu ALU instrukcija.
  • Podržava razne adresione režime uključujući trenutne, ofset, i skalirani indeks ale ne PC-relativni, osim za džampove (uvedenim kao poboljšanje u x86-64 arhitekturi).
  • Sadrži pokretni zarez za stek registara.
  • Sadrži specijalnu podršku za atomski čitaj-modifikuj-piši instukcije xchg, cmpxchg/cmpxchg8b, xadd, i instrukcije celog broja koje kombinuju sa lock prefiksom).
  • SIMD instrukcije (instrukcije koje izvršavaju paralelne istovremene pojedinačne instrukcije na mnogo operanada kodirani u susednim ćelijama širih registara).

Instrukcije za stek[uredi | uredi izvor]

x86 arhitektura ima hadrversku podršku za izvršavanje stek mehanizma. Instrukcije poput push, pop, call i ret se koriste sa stekom da alociraju prostor za lokalne podatke i da čuvaju i vraćaju call-return tačke. ret instrukcijaje veoma korisna za implementiranje prostorno efikasnih i brzih konvencija pozivanja gde je pozivani odgovoran za vraćanje stek prostora.

Kada se postavlja stek frejm da čuva lokalne podatke ili rekurzivnu proceduru postoji nekoliko izbora. Instrukcija na visokom nivou enter uzima procedure-nesting-depth argument kao i local size argument, i može da bude brža od eksplicitnijih manipulacija registrima. Da li je brža ili ne zavisi od x86 implementacije, kao i od konvencije pozivanja i koda potrebnom da radi na više procesora.

Puni opseg adresnih režima (uključujući trenutne i baza + ofset) čak i za instrukcije poput push i pop čini direktno korišćenje steka za celi broj, pokretni zarez i adresne podatke jednostavnim, kao što i ABI specifikacije i mehanizme istaju jednostavni u poređenju sa nekim RISC arhitekturama (zahtevaju eksplicitnije detalje poziva steka).

ALU instrukcije nad celim brojem[uredi | uredi izvor]

x86 ima standardne matematičke opcije add, sub, mul, sa idiv, logički operatori and, or, xor, neg aritmetiku za pomeranje bitova sal/sar, shl/shr, rotiranje sa i bez nošenja, rcl/rcr, rol/ror, komplement BCD aritmetičkih instrukcija, aaa, aad, daa i drugo.

Instrukcije nad pokretnim zarezom[uredi | uredi izvor]

x86 asemblerski jezik sadrži instrukcije za jedinicu za pokretni zarez baziran na steku. Ona sadrži sabiranje, oduzimanje, negaciju, množenje, deljenje, ostatak, kvadratni kornen i kvadriranje. Operacije takođe sadrže instrukcije za konvertovanje koji mogu da uzimaju ili čuvaju vrednost iz memorije u svim sledećim formatima: binarno kodirane decimale, 32-bitni celi brojevi, 64-bitni celi brojevi, 64-bitni brojevei sa pokretnim zarezom ili 80-bitni brojevi (koji se nakon uzimanja konvertuju u trenutno korišćen režim). x86 takođe sadrži funkcije poput sinusa, kosinusa, tangensa, arkus tangensa, računanje sa eksponentima sa bazom 2 i logaritmovanje sa bazama 2, 10 ili e.

Stek registar do stek registar instrukcije su obično fop st, st(*) ili fop st(*), st, gde je st ekvevilentno st(0), i st(*) je jedan od 8 stek registara (st(0), st(1), ..., st(7)). Kao i celi brojevi, prvi operand je i izvorni operand i destinacioni operand. Dodavanje, oduzimanje, množenje, deljenje, čuvanje i kompenzacione instrukcije sadrže instrukcione režime koji će se popeti na vrh steka kada su njihove instrukcije izvršene. Dakle na primer faddp st(1), st izvršava računanje st(1) = st(1) + st(0), onda uklanja st(0) od vrha steka, i tako menja ono što je bio rezultat u st(1)na vrh steka u st(0).

SIMD instrukcije[uredi | uredi izvor]

Moderni x86 procesori sadrže SIMD instukcije, koje uglavnom odrađuju iste operacije paralelno na mnogo vrednostu kodiranih u širokom SIMD regustru. Razne instrukcione tehnologije podržavaju različite operacije na različitim registarskim skupovoma, ali gledano kao celina (od MMX do SSE4.2) sadrže generalna računanja na celobrojnu ili decimalnu aritmetiku (sabiranje, oduzimanje, množenje, shift, minimalizacija, maksimizacija, poređenje, deljenje ili kvadratni koren). Dakle na primer, paddw mm0, mm1 odrađuje 4 paralelnih 16-bitnih (indikovano w) celobrojnih dodavanja (indikovano padd) mm0 vrednosti na mm1 i čuva rezultate u mm0. Streaming SIMD Extensions ili SSE takođe sadrže decimalni režim u kome je samo prva vrednost registra zapravo modifikovana (toje prošireno u SSE2). Neke druge neobične instrukcije su dodate uključujući sumu apsolutnih razlika (korišćenih za predvišanje pomeranja u kompresiji videa, kao što se radi u MPEG) i 16-bitnu akumulacionu instrukciju (korisno za softversko alfa blendovanje i digitalno filterovanje). SSE (od SSE3) i 3DNow! ekstenzije sadrže instrukcije za sabiranje i oduzimanjeza tretiranje uparenih decimalnih vrednosti kao što su kompleksni brojevi.

Ovi instukcijski skupovi takođe sadrže mnoštvo fiskiranih pod-instrukcija za mešanje, ubacivanje i vađenje vrednosti iz tih registara. Dodatno tu su instrukcije za pomeranje podataka između celobrojnih registara i XMM (korišćeni u SSE)/FPU (korišćeni u MMX) registara.

Instrukcije za manipulisanje podacima[uredi | uredi izvor]

x86 procesor takođe sadrži kompleksne adresne režime za adresiranje memorije sa trenutnim ofsetom, registar, registar sa ofsetom, skaliranu verziju sa ofsetom, ili bez njega, i registar sa obcionim ofsetom i još jedan skalirani registar. Tako na primer, jedan može da kodira mov eax, [Table + ebx + esi*4] kao jednu instrukciju koja čita 32 bita podataka sa adrese izračunate kao (Table + ebx + esi * 4) ofset od ds selektora, i čuva ga u eax registru. Generalno x86 mogu da čitaju i korsite memoriju pogođenu sa veličinom bilo kog registra na kojem radi. (SIMD instrukcije takođe sadrže instrukcije za polu-uvođenje.) x86 instrukcijski skup sadrži čitanje stringa, čuvanje, pomeranje, skeniranje i instrukcije za poređenje (lods, stos, movs, scas i cmps) koje odrađuju svaku operaciju na specifiranu veličinu (b za 8-bitnu, w za 16-bitnu i d za 32-bitnu duplu reč) onda uvećanje i umanjenje (zavisno od DF, direction flag) implicitni adresni registar (si za lods, di za stos za scas, i oba za movs i cmps). Za čitanje, čuvanje i operacije skeniranja, implicitni registar za cilj/izvor/poređenje je u al, ax ili eax registar (zavisno od veličine). Implicitni segmenti registri koji se koriste su ds za si i es za di. cx ili ecx registar se koristi kao brojač smanjivanja, i operacija staje kad brojač dođe do nule ili (za skeniranje ili poređenje) kada je nejednakost detektovana.

Stek je implementiran sa implicitnim dekrementiranjem (push) i inkrementiranjem (pop) pokazivača na stek. U 16-bitnom režimu, ovaj implicitni pokazivač steka je adresiran kao SS:[SP], u 32-bitnom je SS:[ESP], a u 64-bitnom režimu je [RSP]. Pokazivač steka zapravo pokazuje na poslednju vrednost koja je sačuvana, pod pretpostavkom da će njegova veličina odgovarati operativnom režimu procesora (16, 32, ili 64 bita) da bi odgovarao normalnoj širini push/pop/call/ret instrukcija. Takođe su uključene enter i leave koje čuvaju i brišu podatke od vrha steka dok postavljaju stek frejm pokazivač bp/ebp/rbp. Međutim, direktno podešavanje, ili dodavanje ili oduzimanje na sp/esp/rsp registar je takođe podržano, pa su enter/leave instrukcije generalno nepotrebne.

Ovaj kod je početak funkcije:

push    ebp       ; save calling function's stack frame (ebp)
mov     ebp, esp  ; make a new stack frame on top of our caller's stack
sub     esp, 4    ; allocate 4 bytes of stack space for this function's local variables

i funkcionalno je jednak:

enter   4, 0

Druge instrukcije za manipulisanje stekom uključuju pushf/popf za čuvanje i vraćanje (E)FLAGS registra. pusha/popa instrukcije će čuvati i vraćati stanje celog broja u i iz steka.

Pretpostavlja se da su vrednosti za SIMD čuvanje ili vraćanje pakovane na susedne pozicije za SIMD registar i da će ih poređati u sekvencijalni niz. Neke SSE instrukcije za čuvanje i vraćanje zahtevaju 16-bajtno ređanje da bi funkcionisali. SIMD instukcioni skupovi sadrže i "prefetch" instrukcije koje odrađuju uzimanje ali ne ciljaju nijedan registar koji se koristi za uzimanje keša.. SSE instrukcijski skup takođe sadrži ne-vremenske instukcije za čuvanje koje će izvršiti čuvanje pravo u memoriju bez alociranja keša ako odredište nije već keširano (inače će se ponašati kao regularno čuvanje).

Većina generičkih instrukcija za cele i decimalne brojeve (ali ne i SIMD) mogu da koriste jedan parametar kao kompleksnu adresu kao parametar drugog izvora. Celobrojne instrukcije takođe mogu prihvatiti jedan memorijski parametar kao operand odredišta.

Primeri[uredi | uredi izvor]

"Hello world!" program za DOS u MASM stilu montaže[uredi | uredi izvor]

Koristeći interrupt 21h za izlaz - drugi primeri koriste libc printf za pisanje na stdout.

.model small
.stack 100h

.data
msg	db	'Hello world!$'

.code
start:
	mov	ah, 09h ; Прикажи поруку
	lea	dx, msg
	int	21h
	mov	ax, 4C00h ; Прекини извршавање
	int	21h

end start

"Hello World!" program za Windows u MASM stilu montaže[uredi | uredi izvor]

; захтева /coff прекидач на верзији 6.15 и каснијим
.386
.model small,c
.stack 100h
 
.data
msg db "Hello World!",0
 
.code
includelib MSVCRT
extrn printf:near
extrn exit:near
 
public main
main proc
        push    offset msg
        call    printf
        push    0
        call    exit
main endp
 
end main

"Hello world!" program za Linuks u NASM stilu montaže[uredi | uredi izvor]

;
; Овај програм ради у 32-битном заштићеном режиму.
; build: nasm -f elf -F stabs name.asm
; link: ld -o name name.o
;
; У 64-битном режиму се могу користити 64-битни регистри (rax уместо eax, rbx уместо ebx, итд.)
; Такође се мења "-f elf " за "-f elf64" у команди грађења.
;
section .data ; секција за иницијализоване податке
str: db 'Hello world!', 0Ah ; стринг поруке са карактером нове линије на крају (10 decimal)
str_len: equ $ - str ; израчунава дужину стринга у бајтовима одузимајући адресу ($ symbol)
                                            ; од str почетне адресе

section .text ; ово је кодна секција
global _start ; _start је улазна тачка и потребан му је глобалан обим да би био видљив
                                            ; linker -    еквавилентан main() у C/C++
_start: ; процедура start
	mov	eax, 4 ; спецификовати sys_write код функције (од векторске табеле ОС-а)
	mov	ebx, 1 ; спецификовати опис фајла stdout -in Линукс, све се третира као фајл,
                                             ; чак и хардверски уређаји
	mov	ecx, str ; померити почетну _адресу_ стринг поруке до ecx регистра
	mov	edx, str_len ; померити дужину поруке (у бајтовима)
	int	80h ; рећи језгру да изврши системски позив који је управо постављен
                                             ; у Линуксу се сервиси траже преко језгра
	mov	eax, 1 ; спецификовати sys_exit код функције (од векторске табеле ОС-а)
	mov	ebx, 0 ; спецификовати код враћања за ОС (0 = све је у реду)
	int	80h ; рећи језгру да изврши системски позив

"Hello world!" program za Linuks u NASM stilu montaže koristeći C standardnu biblioteku[uredi | uredi izvor]

;
; Овај програм ради у 32-битном заштићеном режиму.
; gcc подразумевано веже стандардну C библиотеку

; build: nasm -f elf -F stabs name.asm
; link: gcc -o name name.o
;
; У 64-битном дугом режиму се могу користити 64-битни регистри (rax уместо eax, rbx уместо ebx, etc..)
; Такође променити "-f elf " за "-f elf64" у монтажној команди.
;
        global  main                                ;main мора бити дефинисан као да је компајлиран против C стандардне библиотеке
        extern  printf                              ;декларише коришћење ектерног симбола као што је printf декларисан у другом објектном модулу. Линкер касније решава ово.
        
segment .data ;секција за иницијализоване податке
	string db 'Hello world!', 0Ah ;стринг поруке са новолинијским карактером на крају (10 decimal)
                                                    ;стринг сада реферише на почетну адресу на којој је 'Hello, World' постављен. 

segment .text
main:
        push    string                              ;гурнути адресу првог карактера стринга на стек. Ово ће бити аргумент за printf
        call    printf                              ;зове printf
        add     esp, 4                              ;инкрементира показивач на стек за 4 бришући гурнути аргумент стринга
        ret                                         ;return

print "/bin/sh\n" program in 64-bit mode Linux[uredi | uredi izvor]

section .text
global _start, write
write:
	mov	al, 1 ; write syscall
	syscall
	ret
_start:
	mov	rax, 0x0a68732f6e69622f ; /bin/sh\n
	push	rax
	xor	rax, rax
	mov	rsi, rsp
	mov	rdi, 1
	mov	rdx, 8
	call	write
 
exit: ; just exit not a function
	xor	rax, rax
	mov	rax, 60
	syscall

Korišćenje zastavnog registra[uredi | uredi izvor]

Zastave su korišćene za poređenje u x86 arhitekturi. Kada je poređenje urađeno između dva podatka, CPJ postavlja relevantnu zastavu ili zastave. Prateći ovo, kondicione jump instrukcije se mogu koristiti za proveru zastava i grananje do koda koji se treba izvršiti, na primer:

	cmp	eax, ebx
	jne	do_something
	; ...
do_something:
	; овде се нешто ради..

Zastave se takođe korsite u x86 arhitekturi da se funkcije ili režimi upale i ugase. Na primer, da se ugase sva maskabilna prekidanja, može se koristiti sledeća funskcija:

	cli

Registri fleša se takođe mogu direktno adresirati. Nižih 8 bitova zastavinog registra se može uneti u ah koristeći lahf instrukciju. Ceo fleš registar se može staviti i skloniti sa steka koristeći instrukcije pushf, popf, int (uključujući into) i iret.

Korišćenje registra instrukcionog pokazivača[uredi | uredi izvor]

Instrukcioni pokazivač se zove ip u 16-bitnom režimu, eip u 32-bitnom režimu, i rip u 64-bitnom režimu. Registar instrukcionog pokazivača pokazuje na memorijsku adresu koju će procesor sledeći put pokušati da izvrši; ne može joj se direktno pristupiti u 16-bitnom ili 32-bitnom režimu, ali sekvenca kao što sledi se može napisati da se postavi adresa od next_line u eax:

	call	next_line
next_line:
	pop	eax

Ova sekvenca instrukcija generiše poziciono nezavistan kod jer call uzima instruckionom pokazivaču relativan trenutni operand opisujući ofset u bajtovima instrukcije ciljane instrukcije od sledeće instrukcije, u ovom slučaju 0.

Pisanje po instrukcijskom pokazivaču je jednostavno — jmp instrukcija postavlja instrukcioni pokazivač na ciljanu adresu, pa na primer sekvenca kao što sledi će staviti sadržaj eax u eip:

	jmp	eax

U 64-bitnom režimu, instrukcije mogu referencirati podatke relativne instrukcionom pokazivaču, pa ima manje potrebe za kopiranjem vrednosti instrukcionog pokazivača na drugi registar.

Spoljašnje veze[uredi | uredi izvor]

Manuals[uredi | uredi izvor]