Introduktion till Assembly
Förord
Det här är den första av några kommande artiklar om lågnivåspråket Assembly, förkortat ASM. I denna artikeln avser jag att först presentera en liten FAQ där jag tar upp några generella frågor om assembly, och sedan register i assembly. I de kommande artiklarna kommer jag skriva om andra viktiga ämnen inom assembly.Innehåll
»»
Relaterade artiklar
» Introduktion till Assembly - Del 2: Instruktioner» Introduktion till Assembly - Del 3: Hello World!
» Introduktion till Assembly - Del 4: Stacken
» Introduktion till Assembly - Del 5: Globala variabler
» Introduktion till Assembly - Del 6: Procedurer och funktioner
FAQ
• F: Vad är Assembly?• S: Assembly är ett lågnivå programmeringspråk som bygger på principen att du "får" det du skriver ("what you write is what you get"). Med andra ord finns det ingen kompilerare, eftersom koden du skriver inte går igenom samma process som exempelvis ett program skrivet i C. Assembly-kod går igenom två steg för att producera den binära filen: assemblern översätter assembly-koden till objektkod eller maskinkod (som ofta sparas i en fil med namnet från källkodsfilen och har filändelsen "obj") som i sin tur sedan bearbetas av länkaren och som också producerar den exekverbara programfilen. En C-kompilerare går nästan igenom samma steg, den har ett extra steg: den översätter först C-koden till assembly-kod.
• F: Vad kommer jag behöva under dina artiklars gång?
• S: Du kommer behöver ett textredigeringsprogram (Anteckningar blir bra) och en assembler. Vi kommer använda oss av MASM (Microsoft Macro Assembler) som går att finna på masm32.com eller MSDN (VC++ Express krävs också om du laddar ned MASM från MSDN). Sedan ser jag helst att du är bekant med programmering sedan tidigare, helst C eller C++, alltså att du känner till vad variabler, minneshantering osv, är.
• F: Varför ska jag lära mig assembly?
• S: Det finns flera "pros" med att kunna assembly: du lär dig ett lågnivåspråk som ofta används vid hårdvaruprogrammering, BIOS-programmering, optimering för prestanda (eller storlek) och drivrutiner av olika slag. Med andra ord, du befinner dig på en av de lägsta nivåerna och kan "tala" direkt med datorn i assembly, något som är begränsat i andra högnivåspråk. Du kan optimera din kod precis hur mycket du vill och möjligen kan för hand, något som är betydligt krångligare i högnivåspråk. I högnivåspråk kan du också optimera din kod, men i slutändan är det ex. C-kompileraren som sköter den verkliga kod-optimeringen. Det är vedertaget att C-kompilerare i dag är väldigt skickliga på att optimera kod, men de är begränsade då de bara följer vissa av människor fördefinierade mönster under optimeringsprocessen, och därför är det många människor som vänder sig till assembly när de vill optimera sin kod själva för hand med eller utan processorsarkitekturer så som SSE(2/3). Vidare kräver assembly-skrivna program inga s k "runtime" filer för att köras, såvida de inte använder funktioner ur ex. Microsofts CRT. Att kunna assembly är också nyttigt om du ska klura ut programkrascher med hjälp av ex. en minnesdumpsfil genererad av Windows eller Dr. Watson.
Register
I assembly finns det ett 20-tal register. Av dessa finns det åtta (8) register du kan använda, de övriga är reserverade för bl a operativsystemet och bör inte användas över huvud taget såvida du inte vill ha en s k BSOD eller en programkrasch, eller om du är 100% säker på vad du gör. Ett register är en speciell arbetarplats i processorn som är avsedd för att användas med processorns instruktioner. De register som bör användas och betecknas som "för allmänt bruk" är EAX, EBX, ECX, EDX, ESI, EDI, EBP och ESP. Samtliga är 32-bitars register (regel: alla register som börjar på E och är tre bokstäver långa är 32-bitars). Oftast bör du inte använda EBP eller ESP då de används i procedurer för att läsa/skriva till parametrar eller allokera utrymme för lokala variabler. ESP används internt av instruktioner så som PUSH och POP.Egentligen har du oftast bara användning av de fyra första registerna i den ovanstående listan, ESI och EDI används ibland av API-funktioner eller för att hantera data och bör därmed reserveras först innan de används. Dessutom bär de icke på ett 8-bitars BYTE register under sig (som EAX och de andra tre gör). EAX, EBX, ECX och EDX bär på ett WORD-register (16-bitars) och detta registret i sin tur bär på två BYTE-register som är 8-bitar stora vardera. Nedan finner du en tabell på hur de olika registerna är uppbyggda.
EAX | EBX | ECX | EDX | ESI | EDI | EBP | ESP |
AX | BX | CX | DX | SI | DI | BP | SP |
AH | BH | CH | DH | ||||
AL | BL | CL | DL |
AX, BX, CX, DX, SI, DI, BP och SP är 16-bitars register och AH/AL, BH/BL, CH/CL, och DH/DL är 8-bitars register. H står för "High" och betyder att registret utgör de högsta bitarna av 16-bitars registret det tillhör, L står för "Low" och betyder det motsatta. 8-bitars register är således oftast smidigast för att hantera enskilda BYTES, 16-bitars register är smidigast för att hantera WORDS och 32-bitars register kan hantera samtliga datatyper, dvs BYTES, WORDS och DWORDS (32-bitars, oftast minnesadresser). Nedan följer ett par exempel.
mov eax,1000000 ; flytta värdet 1000000 till EAX
mov ax,20000 ; flytta värdet 20000 till AX
mov ah,100 ; flytta värdet 100 till AH
mov al,100 ; flytta värdet 100 till AL
mov cx,ax ; flytta AX till CX
mov dl,al ; flytta AL till DL
sub dl,10 ; substrahera 10 från DL
add cl,dl ; addera DL med CL
add al,cl ; addera CL med AL
not al ; invertera AL
Du kan flytta register av olika bitstorlekar till andra register, men om destinationsregistret är större än källregistret så bör du använda MOVZX ("move with zero extend") instruktionen för att fylla de resterande bitarna i registret med 0.
mov ax,1000 ; ax=1000
mov cx,10 ; cx=10
mul cx ; ax*=cx
add ax,200h ; ax+=0x200 (512)
mov dx,ax ; dx=ax
movzx eax,dx ; giltigt
add dx,2
mov eax,dx ; ogiltigt (assemblerfel)
Förutom register i assembly finns det också minnesallokering du kan dra nytta av samt stacken, som vi kommer gå igenom i någon av de kommande artiklarna.
Pelle Johansson
Se http://www.derigomedia.com/hack/arkiv/hack20070110.html