Kontakty Webpage přednášky: – Slajdy (MS PowerPoint): –ftp://ulita.ms.mff.cuni.cz/predn/PRG017 Technické informace (manuály ap.): –ftp://ulita.ms.mff.cuni.cz/techdoc/index.html Mail:
Registry
Příznaky - registr EFLAGS
Přístup do paměti Intel 386+ používá segmentaci dvousložkové adresy: SEGMENT : OFFSET –segmentová část je určena obsahem 16-bitového segmentového registru v podstatě se jedná o 14-bitový index do tabulky popisující segmenty –offsetová část (Effective address) je zformována s použitím explicitního nebo implicitního adresového módu Adresové módy (32-bitové): Base + Index * Scale +disp EAX EAX1 -- EBX EBX2 8bit ECX ECX416bit EDX EDX832bit ESI ESI EDI EDI EBP EBP ESP
Přístup do paměti - syntaxe Syntaxe zápisu paměťového operandu (TASM IDEAL): [ : ] Př.: moveax, [ DWORD fs : tabulka + edx ] addedx,[ symbol ] inc [ _DATA : counter ] …
Přístup do paměti - implicitní adresové módy Kromě explicitních (= v instrukci kódovaných) adresových módů existují i implicitní, např.: –nepřímá adresa s post-inkrementací popeax; [esp++] lodsb; [esi++] pro DF=0 –nepřímá adresa s post-dekrementací lodsb; [esi--] pro DF=1 –nepřímá adresa s pre-dekrementací pusheax; [--esp] –nepřímá adresa s 8-bitovým indexem xlat; [EBX+AL] –atd.
Instrukční soubor - obecná charakteristika CISC –široký repertoár někdy i dost složitých instrukcí repmovsb –paměťové operandy nejen v přesunových instrukcích add[ebx],eax –proměnná délka kódování i vykonávání instrukcí –implicitní operandy –neortogonalita Dvou-operandové instrukce addeax,ebx; eax = eax + ebx
Instrukční soubor - kuchařka Žádná instrukce nemá více než JEDEN explicitní paměťový operand S výjimkou konverzních instrukcí jsou u víceoperandových instrukcí vždy STEJNÉ šířky Žádná instrukce neśmí být kódována v délce větší než 15 bytů
Instrukční soubor - kódování instrukcí Instruction prefix Address-size prefix Operand-size prefix Segment override 0,1 byte Prefixes OpcodeModR/MSIBDisplacementImmediate 1,2 bytes0,1 byte 0,1,2,4 bytes0,1,2,4 byte Instruction encoding
Vícebytová data Intel = Little endian –významnější byty jsou umístěny na vyšších adresách Př.: moveax,[1000] –čte 32 bitů, tj. 4 byty, z adres 1000, 1001, 1002, 1003 –byte z adresy 1000 je NEJMÉNĚ významný, skončí v bitech 0-7 registru EAX –byte z adresy 1003 je NEJVÍCE významný, přesune se do bitů registru EAX
IS - přesunové instrukce NEMĚNÍ příznaky v EFLAGS Některé z nich používají implicitní operandy movr,r/m/im,r/i; op1 = op2 lear,m ; op1 = &op2 pushr/m/i ; stack op popr/m ; op stack Př.: moveax,ebx moveax,[ebx] moveax,10 mov[ebx],eax mov[DWORD ebx],10
IS - aritmetické instrukce Nastavují příznaky v EFLAGS ( CF, PF, AF, ZF, SF, OF ) Unární - jediný operand, zároveň cílový i zdrojový Binární - dva operandy, cílový/zdrojový a zdrojový addr,r/m/im,r/i; op1 = op1+op2 adc -”- ; op1 = op1+op2+CF sub -”- ; op1 = op1-op2 sbb -”- ; op1 = op1-op2-CF cmp -”- ; op1-op2 negr/m ; op = -op inc-”- ; op++ dec-”- ; op-- POZOR na chování příznaku Carry ( CF ): –inc, dec ho nemění –neg nastavuje pro operand != 0
IS - logické instrukce Nastavují příznaky v EFLAGS ( CF, PF, AF, ZF, SF, OF ) Unární - jediný operand, zároveň cílový i zdrojový Binární - dva operandy, cílový/zdrojový a zdrojový andr,r/m/im,r/i; op1 = op1&op2 or -”- ; op1 = op1|op2 xor -”- ; op1 = op1^op2 test -”- ; op1&op2 notr/m ; op = ~op POZOR na chování příznaku Parity ( PF ): –je nastavován podle dolních 8-bitů výsledku Carry ( CF ) je nulován
IS - rotace a posuny Nastavují příznaky v EFLAGS ( CF, PF, AF, ZF, SF, OF ) Počet bitů posunu určen přímým operandem nebo obsahem reg. CL Počet bitů posunu je omezen na 31! rclr/m,i/CL; rcrr/m,i/CL; rolr/m,i/CL; rorr/m,i/CL; shlr/m,i/CL; shrr/m,i/CL; sarr/m,i/CL; POZOR na chování rotací - nastavují pouze CF,OF OPCFOPCFOPCFOPCF OPCF 0 OPCF 0 OPCF
IS - instrukce skoků Nepodmíněné nebo podmíněné stavem příznaků v EFLAGS ( CF, PF, ZF, SF, OF ) Podmínky testují jeden i více příznaků Adresace relativní vzhledem k EIP, u nepřímé adresy absolutní jmpaddr; nepodmíněný skok j addr; skok s podmínkou Podmínkové kódy: Z, EZF=1P, PEPF=1 NZ, NEZF=0NP, POPF=0 C, B, NAECF=1A, NBECF=0 & ZF=0 NC, NB, AECF=0NA, BECF=1 | ZF=1 SSF=1G, NLEZF=0 & SF=OF NSSF=0GE, NLSF=OF OOF=1L, NGESF OF NOOF=0LE, NGZF=1 | SF OF
IS - instrukce skoků Př.: jmplabel; autorelativní jmpeax; absolutní jmp[ebx]; absolutní Podmíněné skoky jen přímá autorelativní adresa: jzlabel jnchynej_label jnaejeste_hynej_label
IS - instrukce volání podprogramu Návratovou adresu (absolutní) ukládají na zásobník Neexistují podmíněné varianty Adresace stejná jako u instrukcí skoků calladdr; volání podprogramu ret; návrat z podprogramu retimm8; návrat s úklidem zásobníku Př.: callNavesti_podprogramu call[tabulka+4*ebx]... ret8
IS -NEAR x FAR Vzhledem k segmentaci existují pro instrukce nepodmíněných skoků a volání podprogramu dvě varianty: –„Blízké“ (nebo také „krátké“, pův. NEAR) - skok/volání mění jen hodnotu registru EIP –„Vzdálené“ (také „dlouhé“, pův. FAR) - skok/volání mění hodnotu registrů EIP i CS Ve většině případů řeší volbu správné varianty asembler Pokud je třeba explicitní vynucení konkrétní varianty, je to možné: retf; FAR návrat z podprogramu retn; NEAR návrat z podprogramu jmpFAR label; FAR skok jmp[DWORD ebx]; NEAR skok (v 32-bitovém prostř.)
IS - blokové (řetězcové) instrukce Jediné instrukce umožňující dva paměťové operandy - implicitní V základní formě provedou jednu iteraci, tj.: –naznačenou operaci (přesun, porovnání) –aktualizaci zúčastněných ukazatelů ( ESI, EDI ) movs[BYTE edi], [esi]; [es:edi] = [esi] cmps[WORD edi], [esi]; [esi] - [es:edi] !!! scas[DWORD edi]; acc - [es:edi] lods[BYTE esi]; acc = [esi] stos[WORD edi]; [es:edi] = acc ins[BYTE edi],dx; [es:edi] = I/O[dx] outsdx,[WORD esi]; I/O[dx] = [esi] Existují i mnemoniky bez operandů: movsb= movs [BYTE edi], [esi] cmpsw=cmps [WORD edi], [esi] stosd=stos [DWORD edi]
IS - blokové instrukce 2 Směr aktualizace ukazatelů je volitelný - příznak DF v registru EFLAGS : –DF=0 zdola-nahoru (od nižších adres k vyšším); cld –DF=1 zhora-dolů (od vyšších adres k nižším); std Ex. i možnost opakovaného vykonání instrukce - prefixy REP, REPE, REPNE : while(counter!=0) {ack_int; string_op; counter--; if(!cond) break; } POZOR: (formálně) cílový operand [EDI] používá vždy segmentový registr ES Stejně tak nelze měnit způsob adresace (tj. registry ESI, EDI ) Dekrementace čítače je efektem prefixu REP, nikoliv instrukce samotné
IS - přesunové instrukce pro pokročilé xchgr,r/m; op1 op2 ldsr32,m48; DS:op1 = op2 les, lss, lfs, lgs Konverzní instrukce - mění šířku dat 8 16 nebo 16 32 bitů: movzxr,r/m; op1 = ZeroExt(op2) movsxr,r/m; op1 = SignExt(op2) cbw; ~ movsx ax,al cwd; ~ movsx dx:ax,ax cwde; ~ movsx eax,ax cdq; ~ movsx edx:eax,eax
IS - přesunové instrukce pro pokročilé xlatb; al = [ebx+al] Semaforové instrukce: xaddr/m,r; temp = op1 + op2 ; op2 = op1 ; op1 = temp cmpxchgr/m,r; if(acc==op1) { ZF=1; op1=op2; } else { ZF=0; acc=op1; }
IS - aritmetické instrukce - násobení a dělení Ruší příznaky v EFLAGS ( PF, AF, ZF, OF ), chování je definováno pouze pro CF, OF Implicitní operandy mulr/m8; AX = AL * op1 mulr/m16 ; DX:AX = AX * op1 mulr/m32 ; EDX:EAX = EAX * op1 imulrW,r/mW,iWrW,iW; op1 = op2 * op3 imulrW,r/mW; op1 *= op2 divr/m8; AL=AX/op1 AH=AX%op1 divr/m16; AX=DX:AX/op1 DX=DX:AX%op1 divr/m32; EAX=EDX:EAX/op1 EDX=(rem) idivr/m8,16,32; jako div
IS - bitové operace Manipulují s jednotlivými bity operandů Testování bitu: btr/mW,rWr/mW,i8; CF = op1[op2] Testování a následná změna bitu: btsr/mW,rWr/mW,i8; jako BT + set bit btrr/mW,rWr/mW,i8; jako BT + reset bit btcr/mW,rWr/mW,i8; jako BT + compl. bit Prohledávání posloupnosti bitů: bsfrW,r/mW; od bitu 0 15/31 bsrrW,r/mW; od bitu 15/31 0
IS - (h)různé Podmínkové kódy: set r/m8; op = Skoky: jecxzaddr; if(ecx!=0) goto addr loopdaddr; if(--ecx) goto addr Komunikace s periferiemi: inal,DX/i8 outDX/i8,al Konstrukty pro podporu VPJ: enteri16,i8 leave... nop
IS - a mnoho jiných... pusha, popa bound int, into, int3 aaa, aad, aam, aas daa, das pushfd, popfd sti, cli, std, cld, cmc lahf, sahf shld, shrd bswap, cmpxchg8b hlt...
IS - prefixy Některé prefixy jsou kódovány asemblerem automaticky na základě: –kontextu (např. typu sekce - prefixy velikosti operandu, adresy) –operandů instrukce (např. opět prefixy velikosti operandu, adresy, ale i segmentové prefixy) –mnemoniky instrukce (např. loop loopd - opět prefix velikosti operandu) Některé prefixy lze vynutit i specifickými pseudoinstrukcemi: –segmentové prefixy: segcs, segds, seges, segfs, seggs, segss –instrukční prefixy: rep, repe, repne, repz, repnz lock Př.: segfs movsb
IS - prefixy - lock Prefix lock –oproti původní implementaci na 8086 je jeho použití omezeno pouze na některé (smysluplné) instrukce: bt, bts, btr, btcm,r/i xchgm,r(aut) add, adc, sub, sbb and, or, xorm,r/i inc, dec, not, negm cmpxchg, xaddm,r Př.: lock bts [semaph],0