X86 assembler: erinevus redaktsioonide vahel

Eemaldatud sisu Lisatud sisu
Resümee puudub
Resümee puudub
76. rida:
* EBX – baasregister – üldine baasregister adresseerimisel
* ECX – loendregister – tsükliloendur ja võrdlusregister
* EDX – andmeregister – laiend-akumulaator, aritmeetika ja andmete üldregister
Aadressiregistrid:
* ESP – pinuviit – viitab programmi pinu otsale (''stack pointer'')
113. rida:
* Laienduste registrid (MMX, SSE jms).
 
X86x86 registreid saab kasutada vastavate käskudekäskudega, näiteks MOV käsuga MOV. Et teha arvutusi, peab andmed lugema mälust registrisse ja siis pärast vajadusel tagasi mällu. Üldreeglina ei saa mäluga otseselt opereerida ja on vaja registreid. Näiteks:
<source lang="asm">
mov eax, [integer_value] ; load dword[integer_value]
121. rida:
mov [integer_value], eax ; write dword[integer_value]
</source>
Loeb globaalse muutuja '''integer_value''' registrisse ''EAX ''registrisse, liidab juurde '''4''', loeb globaalse muutuja '''other_value''' ja liidab selle ''EAX''-ile. Lõpuks kirjutatakse tulemus globaalsesse muutujasse '''integer_value'''.
 
Programmeerimiskeeles [[C keeles(programmeerimiskeel)|C]] oleks vastav koodijupp: "integer_value = integer_value + 4 + other_value;".
 
== Käsutüübid ==
X86x86 protsessoril on suur kogus erinevaid opkoode, kuid tähtsamad neist tuleks ka esile tuua.
 
=== MOV ja Adresseermineadresseermine ===
'''MOV ''' ''Move data:''. AndmeteKopeerib kopeerimineandmeid registrite ja mälu vahel. Inteli assembler süntaks järgib alati kuju '''DST <- SRC'''. Paar lihtsat näidet:
<source lang="asm">
mov eax, edx ; EAX dword <- EDX dword
135. rida:
mov ah, dl ; EAX hi <- EDX lo
</source>
'''MOVZX ''' ''Move with zero extend:''. Kopeerib andmed väiksema laiusega registrist suuremasse ja väärtustab ülejäänud bitid nullidega. Näiteks bait 0x28 (40) loetaks sisse kui 0x00000028:
<source lang="asm">
mov bl, 40 ; BL := 0x28
movzx eax, bl ; EAX := 0x00000028
</source>
'''MOVSX''' – ''Move with sign extend:''. Töötab nagu '''MOVZX''', aga arvestab ''sign ''-bitti. Näiteks negatiivne bait 0xE0 (-32) loetaks sisse kui 0xFFFFFFE0:
<source lang="asm">
mov bl, -32 ; BL := 0xE0
146. rida:
</source>
 
'''Adresseermimine'''==== -Adresseermimine X86====
x86 mäluadresseerimise saab kokku võtta valemiga '''[baas + indeks*skalaar + nihe]''', kus:
* Baas - Baasregisterbaasregister (nt. EBX), mis määrab baasaadressi.
* Indeks - Indeksregistriindeksregistri (nt. EAX) poolt määratud lisanihe.
* Skalaar - Indeksregistriindeksregistri kordaja (ainult 1,2,4,8).
* Nihe - Konstantnekonstantne lisanihe (nt. 32 vms täisarv).
Lühike näide, koos analoogse C programmiga:
<source lang="asm">
; static int array[4] = { 0, 1, 2, 3 };
157. rida ⟶ 158. rida:
; int i = 2;
; int a = ptr[i + 1];
mov ebx, array ; baasregister viitab Arrayarray-le
mov eax, 2 ; indeksregister i = #2 element
mov eax, [ebx + eax*4 + 4] ; a = ptr[i + 1]
169. rida ⟶ 170. rida:
Seega on võimalikke kombinatsioone piisavalt iga vastava juhu jaoks.
=== Põhikäsud ===
'''push''' – ''Push to stack:''. Lükkab väärtuse ''stack ''-segmenti ja lahutab ESP registrist väärtuse laiuse.
<source lang="asm">
push eax ; lükkab EAX-i väärtuse pinusse
push dword[array] ; lükkab 4 baiti aadressilt @array pinusse
</source>
'''pop''' – ''Pop from stack:''. Võtab väärtuse ''stack ''-segmendist ja liidab ESP registrile väärtuse laiuse.
<source lang="asm">
pop dword[array] ; korjab pinust väärtuse ja kirjutab aadressile @array
pop eax ; korjab pinust väärtuse ja kirjutab registrisse EAX
</source>
'''lea''' – ''Load effective address:''. Arvutab adresseeringu aadressi ning salvestab selle aadressi. Mälust ei loeta midagi.
<source lang="asm">
lea ebx, [array] ; @array aadress liigutatud EBX-i, sama mis ''mov ebx, array''
186. rida ⟶ 187. rida:
 
=== Aritmeetika ja Loogika ===
'''add,sub''' – ''Integer Addition/Subtraction:''. liidabLiidab/lahutab kaks operandi ja salvestab tulemuse esimesse operandi.
<source lang="asm">
add eax, 4 ; eax += 4
193. rida ⟶ 194. rida:
sub eax, 10 ; eax -= 10
</source>
'''inc,dec''' – ''Integer Increment/Decrement:''. suurendabSuurendab/vähendab operaatorit 1 võrra.
<source lang="asm">
inc eax ; ++eax
199. rida ⟶ 200. rida:
inc dword[ebx] ; ++[ebx]
</source>
'''imul''' – ''Integer Signed Multiplication:''. omabOmab kahte erinevat süntaksit. Esimene variant korrutab kaks operandi ja paigutab tulemuse esimesse operandi. Teine süntaks korrutab teise ja kolmanda operandi ning paigutab tulemuse esimesse operandi.
<source lang="asm">
imul eax, edx ; eax *= edx
206. rida ⟶ 207. rida:
imul eax, [ebx], 10 ; eax = [ebx]*10
</source>
'''idiv''' – ''Integer Signed Division:''. jagabJagab 64-bitise täisarvu EDX:EAX määratud väärtusega läbi. EDX tuleb vajadusel käsitsi nullida. Tulem on alati EAX registris ja jagatise jääk on EDX registris. Operand ei saa olla EDX register või vahetu väärtus.
<source lang="asm">
xor edx, edx ; edx ^= edx; -> edx = 0
213. rida ⟶ 214. rida:
idiv eax ; eax /= eax
</source>
'''and, or, xor''' – ''Bitwise logical and, or and, exclusive or''. KasutameTeostab bitt-loogilisiloogilised tehteidtehted kahe operandi vahel,. paigutadesTulem tulemipaigutatakse esimesse operandi.
<source lang="asm">
xor edx, edx ; edx ^= edx
220. rida ⟶ 221. rida:
and eax, 0x0F ; eax &= 0x0F
</source>
'''not''' – ''Bitwise logical not''. Pöörab bitid ümber. Väärtus võib olla register või adresseeritud mälu.
<source lang="asm">
not eax ; eax = !eax
not dword[ebx] ; *ebx = !*ebx
</source>
'''neg''' – ''Arithmetic negate''. Negatiivselt väärtustabVäärtustab täisarvu selle vastandarvuga i = -i.
<source lang="asm">
neg eax ; eax = -eax
</source>
'''shl,shr''' – ''Logical Shift Left/Right''. Nihutab bitte loogiliselt vasakule/paremale, üle ääre nihutatud bitid kaovad ja lisatud bitid on nullid. Näiteks 0b10011100 << 2 = 0b00111000
<source lang="asm">
shl eax, 1 ; eax = eax << 1 ; sama kui eax*2
235. rida ⟶ 236. rida:
shr eax, 2 ; eax = eax >> 2 ; sama kui eax/4
</source>
'''sar,sal''' – ''Arithmetic Shift Left/Right''. Nihutab bitte aritmeetiliselt vasakule/paremale. Arvestab, et tegu võib olla negatiivse arvuga ning säilitab vajadusel negatiivsusbiti.
<source lang="asm">
movsx eax, 0b10000000
243. rida ⟶ 244. rida:
 
=== Programmivoo käsud ===
Programmivoo käske kasutatakse programmi loogiliseks juhtimiseks. Madalamal tasemel implementeeritakse nende käskudakäskudega if/else/while käitumist.
 
'''jmp''' – ''Unconditional jump''. Hüppab määratud sümbolile, muutes programmi käivitusasukohta. Otseselt muutub EIP register.
<source lang="asm">
jmp begin ; jumpshüppab tosildi label '"begin'" juurde
</source>
'''jcondition''' – ''Conditional jump''. Hüppab sümbolile ainul siis, kui kindel tingimus on täidetud. Need käsud sõltuvad protsessori FLAGS registrist. Kõige tähtsamad bitid on Zero Flag (ZF) ja Sign Flag (SF). Kõik aritmeetilised käsud mõjutavad protsessori FLAGS registrit. Näiteks käsk ''xor eax, eax'' tõstab Zero Flagi (ZF). Täpsemalt saab lugeda FLAGS registrist Wikipedias.
<source lang="asm">
je label ; jump if equal (ZF=1)
266. rida ⟶ 267. rida:
jecxz label ; jump if ECX register == 0
</source>
'''cmp''' – ''Signed compare''. Teostab märgitundliku lahutustehte kahe operandi vahel ja uuendab protsessori FLAGS registrit. Märgatavalt ZF ja SF. Võrdluskäsku kasutame ainult siis, kui on vaja võrrelda kahe operandi vahet (suurem/väiksem?).
<source lang="asm">
cmp [len], 0 ; len ?? 0
273. rida ⟶ 274. rida:
jg .loop ; eax > edx ? .loop
</source>
'''test''' – ''Equality test''. Teostab loogilise AND tehte kahe operandi vahel ja uuendab FLAGS registrit. Uuenevad ZF ja SF. Test käsku kasutame ainult siis kui on vaja testida kahe operandi võrdsust või juhul kui mõni register on väärtusega 0.
<source lang="asm">
test eax, ecx ; eax ?? ecx
280. rida ⟶ 281. rida:
jz .loop1 ; eax == 0 ? .loop1
</source>
'''loop''' – ''Looping instruction''. Teostab tsüklihüppe juhul kui ECX != 0 ja vähendab ECX-i 1 võrra.
<source lang="asm">
mov eax, 0 ; sum = 0
291. rida ⟶ 292. rida:
 
==Näited==
Paar näidet WindowsWindowsi ja LinuxLinuxi platvormi peal lihtsast [[Hello Worldworld]] programmist. ''' Microsoft Macro Assembler''' '' (MASM)'' töötab ainult WindowsWindowsi platvormil ning on üpriski keerukas ja detailne.
 
'''Netwide Assembler''' ''(NASM) ''töötab mitme platvormi peal ning on sisult väga lihtne. NASM on populaarne just Linux/Unix -keskkonnas. Linuxi peal on kompileerimine väga sarnane, seega on NASM väga hea valik multiplatvormseks arenduseks.
 
=== "Hello world!" 32-bitbitine MASM (Windows) ===
<source lang="asm">
; Hello World programm
303. rida ⟶ 304. rida:
; \masm32\bin\link.exe /ENTRY:main /SUBSYSTEM:CONSOLE helloworld.obj
;
.386 ; kasuta x386386 käsustikku
.model flat, stdcall ; 32-bit, stdcall win32 API jaoks
 
360. rida ⟶ 361. rida:
</source>
 
=== "Hello world!" 32-bitbitine NASM (Linux) ===
<source lang="asm">
; ----------------------------------------------------
399. rida ⟶ 400. rida:
* [[Programmeerimiskeel_Assembler|Programmeerimiskeel Assembler]]
* [[Assemblerkeel]]
* [[X86x86]]
* [[C (programmeerimiskeel)|C]]
 
==Välislingid==
*[https://en.wikipedia.org/wiki/X86_instruction_listings| Wikipedia: X86 instruction listings]
*[https://en.wikipedia.org/wiki/X86_assembly_language| Wikipedia: X86 Assembly Language]
*[https://en.wikibooks.org/wiki/X86_Assembly| Wikibooks: X86 Assembly]
*[http://www.cs.virginia.edu/~evans/cs216/guides/x86.html| University of Virginia: X86 Assembly]