Limbaj de asamblare

limbaj de asamblare
Clasa de limba imperativ
Tipul de execuție asamblabile
Aparut in 1949
Extensie de fișier .asmsau [1].s
 Fișiere media la Wikimedia Commons

Limbajul de asamblare ( limba engleză  de asamblare ) - reprezentarea comenzilor procesorului într-o formă care poate fi citită de om. Limbajul de asamblare este considerat un limbaj de programare de nivel scăzut , spre deosebire de limbajele de nivel înalt care nu sunt legate de o anumită implementare a unui sistem de calcul. Programele scrise în limbaj de asamblare se traduc fără ambiguitate în instrucțiunile unui anumit procesor și, în majoritatea cazurilor, nu pot fi portate fără modificări semnificative pentru a rula pe o mașină cu un set de instrucțiuni diferit. Un asamblator este un program care convertește codul limbajului de asamblare în cod mașină; un program care efectuează o sarcină inversă se numește dezasamblator .

Istorie

Primii asamblatori au fost proiectați de Kathleen Booth în 1947 sub ARC2 [2] și de David Wheeler în 1948 sub EDSAC [3] , în timp ce termenul „asamblator” nu a fost folosit, numind pur și simplu limbajul „un set de instrucțiuni de bază”. " ( Setul de comenzi de bază în engleză  ) și, respectiv, "comenzi inițiale" ( comenzi inițiale în engleză ). Pentru prima dată, termenul „asamblator” pentru procesul de combinare a câmpurilor într-un cuvânt de control a început să fie folosit de rapoartele ulterioare despre EDSAC.  

De asemenea, în primele etape ale dezvoltării programării, a fost introdus conceptul de codare automată  - un limbaj de programare, ale cărui propoziții sunt practic similare ca structură cu comenzile și datele procesate ale unui anumit limbaj de mașină [4][ semnificația faptului? ] . Termenul nu este folosit în prezent.

Din punct de vedere istoric, dacă codurile de mașină sunt considerate prima generație de limbaje de programare, atunci limbajul de asamblare poate fi considerat a doua generație de limbaje de programare. . Deficiențele limbajului de asamblare, de exemplu, dificultatea dezvoltării unor sisteme software mari pe acesta, au condus ulterior la apariția limbajelor de a treia generație - limbaje de programare de nivel înalt (cum ar fi Fortran , Lisp , Cobol , Pascal ). , C și altele).

Sintaxă

Nu există o sintaxă a limbajului de asamblare folosită în mod obișnuit. Deoarece sistemele de instrucțiuni ale diferitelor procesoare diferă semnificativ, limbajele de asamblare pentru aceste procesoare diferă și ele. În plus, fiecare program de asamblare poate folosi o sintaxă diferită. În asamblatoarele pentru procesoare x86 , așa-numita sintaxă Intel este cea mai utilizată și, într-o măsură mai mică,  sintaxa AT&T .

Mnemonice

Construcția de bază a limbajului de asamblare este un cod mnemonic sau mnemonic - o scurtă reprezentare simbolică a unei instrucțiuni de procesor. De regulă, este format din mai multe caractere care indică acțiunea care trebuie întreprinsă (de exemplu, movpentru a trece dintr-un registru în altul, addpentru a adăuga valori etc.). De asemenea, mnemonicul poate include obiectul asupra căruia se efectuează operația (registru, memorie, stivă) sau alte caracteristici (influență asupra registrului steagurilor , condiții de execuție etc.), totuși, în alte dialecte, aceleași caracteristici pot fi specificat în operanzi.

De regulă, asamblatorul fiecărui procesor are propriul set tradițional de mnemonici, dar există asamblatori cu sintaxă multiplatformă (cum ar fi sintaxa AT&T), cu toate acestea, numai notațiile rămân multiplatforme în ele, codul unui procesor. nu poate fi transferat direct altuia.

Operanzi

Ca operanzi pot fi specificate registre, valori constante, adrese ale celulelor de memorie și porturi I/O , constante, etichete etc. Asambleri diferiți pot necesita o ordine diferită a operanzilor: în unele implementări, operatorul în care este scrisă valoarea este primul, în altele acesta este ultimul. De regulă, operanzii sunt separați de mnemonicii instrucțiunilor prin spații.

Literale

Cel mai comun tip de date cu care pot lucra majoritatea procesoarelor este un număr întreg împachetat într-un cuvânt de mașină sau unul sau mai mulți octeți , mai rar un număr în virgulă mobilă . În programele în limbaj de asamblare, valorile date în diferite sisteme numerice sunt mult mai des folosite. În primul rând, în computerele cu un octet de opt biți, notația hexazecimală este adesea folosită , deoarece două cifre hexazecimale sunt plasate într-un octet. Unele valori pot fi scrise în coduri binare. La primele calculatoare cu un octet de șase biți, a fost întâlnit și sistemul de numere octale . Metodele de scriere pot diferi în diferite asamblare, de exemplu:

În plus, uneori este necesară specificarea blocurilor de date care sunt încărcate împreună cu codul programului, pentru care asamblatorul poate conține directive specializate. Asamblerii moderni pot sprijini, de asemenea, organizarea datelor sub forma diferitelor structuri .

Elemente de expresivitate

Asamblerii pot suporta diverse constructe pentru a face codul de asamblare mai ușor de citit, pentru a scuti programatorul de nevoia de a ține evidența adreselor de instrucțiuni și pentru a implementa elemente care sunt specifice limbajelor de nivel înalt.

Standarde de formatare a codului

De regulă, codul de asamblare nu utilizează indentare și paranteze operator caracteristice limbajelor de nivel înalt . Codul de asamblare este de obicei scris în mai multe coloane, care includ:

Acest mod de scriere reflectă particularitatea execuției programelor pe procesoare de uz general: la nivelul codurilor de mașină, programele sunt de obicei liniare, nu au structură și dintr-un loc în program se poate face o tranziție în alta, indiferent de unde se află începutul codului programului şi programul va continua execuţia din acel punct.locul unde s-a făcut transferul. Un exemplu de program în limbaj de asamblare pentru arhitectura PIC16 :

Din nou: movf 0x40 , W ; Copiați locația 0x40 (zecimală 64) în registrul W addlw 0x05 ; Adăugați constanta 5 în registrul W movwf PORTC ; Scrieți registrul W în portul de ieșire PORTC al microcontrolerului clrw ; ștergeți registrul W (această instrucțiune nu are operanzi) mergeți la Din nou ;Mergi la etichetă din nou

Avantaje și dezavantaje

Deoarece codul de asamblare este tradus fără ambiguitate în cod de mașină pentru un anumit procesor, acest lucru vă permite să utilizați mai pe deplin toate capacitățile procesorului, să reduceți numărul de operațiuni inutile „inactiv” și să utilizați alte metode de optimizare a codului de program care nu sunt disponibile. atunci când se utilizează compilatoare, totuși, dezvoltarea compilatoarelor de optimizare duce la faptul că calitatea codului pe care îl generează poate fi mai mare decât o poate scrie un programator de asamblare moderat calificat [5] . Mai mult, cu cât volumul programului este mai mare, cu atât câștigul din utilizarea limbajului de asamblare este mai mic.

Programele în limbaj de asamblare nu permit comportament nedefinit , cu toate acestea, în general, scrierea și depanarea codului în asamblare necesită mai mult efort. Controlul tipului nu este disponibil în assembler , motiv pentru care semnificația unei anumite valori și acțiunile permise asupra acesteia trebuie să fie controlate de programator însuși. Când scrieți programe în limbaj de asamblare, este necesară utilizarea constantă a stivei și a unui număr limitat de registre de uz general, precum și a indicatorilor, ceea ce necesită ca programatorul să fie atent și să aibă o memorie bună.

Programele în limbaj de asamblare sunt aproape imposibil de portat la o mașină cu o arhitectură sau un set de instrucțiuni diferite fără a rescrie programul, chiar dacă la scriere a fost folosit un dialect în limbaj de asamblare „mult-platformă”: arhitecturi diferite de procesor au seturi diferite de registre, steaguri, diferite dimensiuni de cuvinte ale mașinii și pot avea, de asemenea, comenzi foarte specializate care nu sunt disponibile pe alte platforme.

Programul de asamblare are mai multe oportunități de a interacționa cu hardware-ul și cu nucleul sistemului de operare . De exemplu, la primele computere de acasă și console de jocuri, s-ar putea să nu fi existat un temporizator încorporat cu o rezoluție suficient de mare, dar, în același timp, frecvența de ceas a procesorului era standard pentru toate dispozitivele de același tip, ceea ce a făcut posibilă să folosească procesorul ca temporizator, numărând numărul de cicluri pentru a executa anumite comenzi și inserând operații goale în locurile potrivite. În procesoarele moderne care utilizează circuite de optimizare a performanței încorporate, modificări dinamice ale frecvenței de ceas și sisteme complexe de întrerupere, și cu atât mai mult sub controlul sistemului de operare multitasking , astfel de tehnici au devenit imposibile, dar continuă să fie utilizate pe unele microcontrolere .

Aplicație

Apariția asamblatorilor a facilitat foarte mult sarcina de programare a calculatoarelor timpurii, dar destul de repede complexitatea problemelor aplicate a necesitat utilizarea unor limbaje de nivel înalt. Cu toate acestea, aceste limbi au fost executate destul de lent și, în plus, nu au avut întotdeauna acces la toate capabilitățile hardware ale computerului. Pe măsură ce performanța mainframe-urilor și minicalculatoarelor au crescut și odată cu apariția limbilor precum C , relevanța limbajului de asamblare a început să scadă, dar a crescut din nou odată cu apariția microcalculatoarelor . De regulă, microprocesoarele timpurii aveau performanțe scăzute și o cantitate mică de memorie RAM disponibilă și, în plus, compilatoarele de limbi de înaltă calitate pentru limbaje de nivel înalt nu au apărut imediat pentru ei. Adesea, programele pentru computerele de acasă, inclusiv jocurile, au fost scrise în întregime în asamblator. Cu toate acestea, până la începutul secolului 21, compilatoarele de optimizare au fost adăugate la performanța în creștere a computerelor , ceea ce a generat un cod de mașină care a fost mai optim decât ar putea scrie un programator mediu. În plus, problema portabilității între diferite platforme a devenit importantă.

Limbajul de asamblare este folosit și în depanare și inginerie inversă , folosind programe de dezasamblare . Folosind dezasamblatorul, puteți controla execuția programului la nivelul instrucțiunilor mașinii, ceea ce este util, de exemplu, atunci când căutați locuri cu comportament nedefinit sau erori care apar atunci când lucrați cu pointeri.

Inserții de asamblare

Pentru a facilita dezvoltarea, a fost utilizată următoarea abordare: cea mai mare parte a codului este scrisă într-un limbaj de nivel înalt și numai secțiunile pentru care performanța este critică sau care necesită acces direct la resursele hardware ale computerului sunt scrise în asamblator.

Demoscenă

Exemple

Exemple

Salut Lume!

Program COM pentru MS-DOS în dialectul TASM .MODEL TINY CODE SEGMENT ASUME CS : CODE , DS : CODE ORG 100 h START : mov ah , 9 mov dx , OFFSET Msg int 21 h int 20 h Msg DB ' Hello World ' , 13 , 10 , ' $ END CODE ENDS START Program EXE pentru MS-DOS în dialectul TASM .MODEL SMALL .DATA msg DB ' Hello World ' , 13 , 10 , ' $ ' .CODE START: mov ax , @ DATA mov ds , axe mov ax , 0900 h lea dx , msg int 21 h mov ax , 4 C00h int 21 h sfârșitul începere Program pentru Linux / x86 în dialect NASM SECȚIUNEA .data msg: db " Bună ziua , lume " , 10 len: equ $-msg SECȚIUNEA .text global _start _start: mov edx , len mov ecx , msg mov ebx , 1 ; stdout mov eax , 4 ; scrie (2) int 0x80 mov ebx , 0 mov eax , 1 ; exit(2) int 0x80 Program pentru FreeBSD / x86 în dialectul NASM SECȚIUNEA .data msg: db " Bună ziua , lume " , 10 len: equ $-msg SECȚIUNEA .text global _start syscall: int 0x80 ret _start: push len push msg push 1 ; stdout mov eax , 4 ; write(2) call syscall add esp , 3 * 4 push 0 mov eax , 1 ; exit(2) apel syscall Program pentru Microsoft Windows în dialectul MASM .386 .model flat , opțiune stdcall casemap : niciunul include \ masm32 \ include \ windows.inc include \ masm32 \ include \ kernel32.inc includelib \ masm32 \ lib \ kernel32.lib .data msg db " Bună ziua , lume " , 13 , 10 len equ $-msg .date ? scris dd ? .code start: apăsați -11 apelați GetStdHandle push 0 push OFFSET scris push len push OFFSET msg push eax call WriteFile push 0 apel ExitProcess sfârşitul începutului Program de consolă pentru Windows în dialectul FASM format PE consola pornire intrare include ' include \ win32a.inc ' secţiunea ' .data ' date citibile mesaj scriere db ' Salut , lume ! ' , 0 secțiunea ' .code ' codul de pornire executabil citibil : ; CINVOKE macro în FASM. ; Vă permite să apelați funcții CDECL. cinvoke printf , mesaj cinvoke getch ; INVOKE este o macrocomandă similară pentru funcțiile STDCALL. invocați ExitProcess , secțiunea 0 .idata importați nucleul bibliotecii care pot fi citite , kernel32.dll , \ msvcrt , msvcrt.dll import kernel , \ ExitProcess , ' ExitProcess ' import msvcrt , \ printf , ' printf ' , \ getch , ' _getch ' Program Windows pe 64 de biți în dialectul YASM (folosind linker-ul Microsoft) ;yasm-1.0.0-win32.exe -f win64 HelloWorld_Yasm.asm ;setenv /Release /x64 /xp ;link HelloWorld_Yasm.obj Kernel32.lib User32.lib /entry:main /subsystem:windows /LARGEADDRESSAWARE64: NOBITSAWARE64 principal global extern MessageBoxA extern ExitProcess secțiunea .data mytit db ' Lumea pe 64 de biți a Windows și asamblatorului ... ' , 0 mymsg db ' Bună lume ! ' , 0 sectiunea .text main: mov r9d , 0 ; uType = MB_OK mov r8 , mytit ; LPCSTR lpCaption mov rdx , mymsg ; LPCSTR lpText mov rcx , 0 ; hWnd = HWND_DESKTOP apel MessageBoxA mov ecx , eax ; uExitCode = MessageBox(...) apelează ExitProcess ret Program pentru arhitectura Solaris și SPARC .section „.data” salut: .asciz „Hello World!\n” .secțiunea „.text” .align 4 .principal global principal: salvați %sp , -96 , %sp ! aloca memorie mov 4 , %g1 ! 4 = SCRIE ( apel de sistem ) mov 1 , %o0 ! 1 = STDOUT set salut , %o1 mov 14 , %o2 ! numărul de caractere ta 8 ! apel de sistem ! ieșire din program mov 1 , % g1 ! mutați 1 ( exit () syscall ) în %g1 mov 0 , %o0 ! mutați 0 ( adresa de retur ) în %o0 ta 8 ! apel de sistem

Exemple de programe pentru diferite microcontrolere

Programul ASM-51 pentru microcontrolerul AT89S52 ( familia MCS-51 )

Acest program trimite înapoi un caracter primit prin portul serial UART ("Echo"):

mov SCON , #50 h mov TH1 , #0 FDh orl TMOD , #20 h setb TR1 din nou: clr RI jnb RI , $ mov A , SBUF jnb RI , $ clr TI mov SBUF , A jnb TI , $ sjmp din nou Exemple de compilare a C în limbajul de asamblare pentru arhitectura ARM

Operații cu biți:

C:

z = ( a << 2 ) | ( b & 15 );

Asamblator:

ADR r4 , a ; obține adresa pentru un LDR r0 ,[ r4 ] ; obține valoarea unui MOV r0 , r0 , LSL #2 ; efectuează schimbul ADR r4 , b ; obține adresa pentru b LDR r1 ,[ r4 ] ; obțineți valoarea lui b ȘI r1 , r1 , #15 ; executa AND ORR r1 , r0 , r1 ; executa OR ADR r4 , z ; obține adresa pentru z STR r1 ,[ r4 ] ; stocați valoarea pentru z

Ramuri:

C:

dacă ( i == 0 ) { i = i + 10 ; }

Asamblator:

@(variabila i este în registrul R1 ) SUBS R1 , R1 , #0 ADDEQ R1 , R1 , #10

Cicluri:

C:

pentru ( i = 0 ; i < 15 ; i ++ ) { j = j + j _ }

Asamblator:

SUB R0 , R0 , R0 ; i -> R0 și i = 0 start CMP R0 , #15 ; sunt < 15? ADDLT R1 , R1 , R1 ; j = j + j ADDLT R0 , R0 , #1 ; i++ BLT start Program pentru microcontroler PIC16F628A ( arhitectura PIC )

În cazul în care 8 LED-uri sunt conectate la portul PORTB al microcontrolerului, programul le va porni după una:

LISTA p = 16 F628A __CONFIG 0309 H STATUS equ 0x003 RP0 equ 5 TRISB equ 0x086 PORTB equ 0x006 ORG 0x0000 ;Start vectorul du -te la start ;Sari la începutul codului principal start: bsf STATUS , RP0 ;Select bank 1 clrf TRISB ;Toți biții PORTB sunt ieșiți bcf STATUS , RP0 ;Select bank 0 led: movlw .170 ;Scrieți valoarea binară " 10101010 " în PORTB movwf PORTB ; Loop to PORTB; Sfârşit Program pentru microcontroler MSP430G2231 ( arhitectura MSP430 ) în Code Composer Studio .cdecls C , LIST , "msp430g2231.h" ;-------------------------------------- -------------- ------------------------------------ ---- .text ; Pornirea programului ;----------------------------------------------- ------ ------------------------------ RESET mov.w #0280 h , SP ; Inițializați stackpointer StopWDT mov.w #WDTPW+WDTHOLD,&WDTCTL ; Opriți WDT SetupP1 bis.b #001 h , & P1DIR ; Ieșire P1.0 ; Mainloop bit.b #010 h , & P1IN ; P1.4 mare/scăzut? jc ON ; jmp--> P1.4 este setat ; OFF bic.b #001 h , & P1OUT ; P1.0 = 0 / LED OFF jmp Mainloop ; ON bis.b #001 h , & P1OUT ; P1.0 = 1 / LED ON jmp Mainloop ; ; ;------------------------------------------------- ------------------------------ ; Vectori de întrerupere ;----------------------------------------------- ------ ------------------------------- .sect ".reset" ; MSP430 RESET Vector .scurt RESET ; .Sfârşit

Note

  1. https://cs.lmu.edu/~ray/notes/x86assembly/
  2. Considerații generale în proiectarea unui computer digital electronic multifuncțional Arhivat 24 martie 2020 la Wayback Machine de Andrew D. Booth și Kathleen HV Britten. al 2-lea. ediție. august 1947.
  3. 1985 Computer Pioneer Award „Pentru programarea în limbaj de asamblare”.
  4. GOST 19781-83 // Informatică. Terminologie: Manual de referință. Numărul 1 / Referent Ph.D. tehnologie. Științe Yu. P. Selivanov. - M . : Editura de standarde, 1989. - 168 p. - 55.000 de exemplare.  — ISBN 5-7050-0155-X .
  5. Chris Kaspersky. Războiul lumilor: Assembler vs. C (link indisponibil) . Consultat la 1 iunie 2010. Arhivat din original la 29 iulie 2010. 

Literatură

  • Galiseev GV Assembler pentru Win 32. Tutorial. - M . : Dialectică , 2007. - 368 p. - ISBN 978-5-8459-1197-1 .
  • Zubkov SV Assembler pentru DOS, Windows și UNIX. - M. DMK Press; SPb. Petru, 2006. - 608 p. — ISBN 5-94074-259-9 .
  • Kip Irvine. Limbajul de asamblare pentru procesoarele Intel = Limbaj de asamblare pentru computere bazate pe Intel. — M. : Williams , 2005. — 912 p. — ISBN 0-13-091013-9 .
  • Kalashnikov O. A. Asamblator? E simplu! Învățați să programați. - Sankt Petersburg. : BHV-Petersburg , 2007. - 384 p. — ISBN 978-5-94157-709-5 .
  • Chris Kaspersky. Arta dezasamblarii. - Sankt Petersburg. : BHV-Petersburg , 2008. - 896 p. - ISBN 978-5-9775-0082-1 ​​​​.
  • Vladislav Pirogov. Asamblator pentru Windows. - Sankt Petersburg. : BHV-Petersburg , 2007. - 896 p. - ISBN 978-5-9775-0084-5 .
  • Vladislav Pirogov. Asamblare si demontare. - Sankt Petersburg. : BHV-Petersburg , 2006. - 464 p. — ISBN 5-94157-677-3 .
  • Richard Simon. Referință pentru programator de sistem Microsoft Windows API.
  • Frunze A. V. Microcontrolere? E simplu! - T. 1.
  • Yurov V., Khoroshenko S. Asamblator: curs de formare. - Sankt Petersburg. : Peter , 1999. - S. 672. - ISBN 5-314-00047-4 .
  • Ablyazov R. Z. Programare în asamblator pe platforma x86-64. - M .: DMK Press , 2011. - S. 304. - ISBN 978-5-94074-676-8 .
  • Yurichev D., Înțelegerea limbajului de asamblare https://yurichev.com/writings/UAL-RU.pdf
  • Programarea practică a microcontrolerelor Atmel AVR în limbaj de asamblare .. - a 2-a. - BHV-Petersburg, 2014. - 368 p. - (Electronică). — ISBN 9785977533119 .

Link -uri