Casa / Avatar / Formato dei dati e struttura delle istruzioni in linguaggio assembly. Riassunto: Piano: Prefazione. Linguaggio di assemblaggio e struttura dell'istruzione. La struttura del file exe (analisi semantica) La struttura del comando in linguaggio assembly contiene

Formato dei dati e struttura delle istruzioni in linguaggio assembly. Riassunto: Piano: Prefazione. Linguaggio di assemblaggio e struttura dell'istruzione. La struttura del file exe (analisi semantica) La struttura del comando in linguaggio assembly contiene

Argomento 1.4 Mnemonici dell'assemblatore. Struttura e formati dei comandi. Tipi di indirizzamento. Set di istruzioni per microprocessore

Piano:

1 Linguaggio assembler. Concetti basilari

2 Simboli del linguaggio assembly

3 Tipi di istruzioni assembler

4 Direttive di Assemblea

5 Set di istruzioni del processore

1 iolinguaggio assembly. Concetti basilari

linguaggio assemblyè una rappresentazione simbolica del linguaggio macchina. Tutti i processi nella macchina al livello hardware più basso sono guidati solo da comandi (istruzioni) del linguaggio macchina. Da ciò risulta chiaro che, nonostante il nome comune, il linguaggio assembly per ogni tipo di computer è diverso.

Un programma in linguaggio assembly è una raccolta di blocchi di memoria chiamati segmenti di memoria. Un programma può essere costituito da uno o più di questi segmenti di blocco. Ogni segmento contiene una raccolta di frasi linguistiche, ognuna delle quali occupa una riga separata di codice del programma.

Le dichiarazioni di assemblaggio sono di quattro tipi:

1) comandi o istruzioni che sono analoghi simbolici dei comandi della macchina. Durante il processo di traduzione, le istruzioni di montaggio vengono convertite nei comandi corrispondenti del set di istruzioni del microprocessore;

2) macro -le frasi del testo del programma, formalizzate in un certo modo, vengono sostituite da altre frasi durante la messa in onda;

3) direttive,che sono istruzioni al traduttore assembler per eseguire alcune azioni. Le direttive non hanno controparti nella rappresentazione della macchina;

4) righe di commento , contenente qualsiasi carattere, comprese le lettere dell'alfabeto russo. I commenti vengono ignorati dal traduttore.

­ Struttura del programma di montaggio. sintassi dell'assemblatore.

Le frasi che compongono un programma possono essere un costrutto sintattico corrispondente a un comando, una macro, una direttiva o un commento. Affinché il traduttore assembler possa riconoscerli, devono essere formati secondo determinate regole sintattiche. Per fare ciò, è meglio utilizzare una descrizione formale della sintassi della lingua, come le regole della grammatica. I modi più comuni per descrivere un linguaggio di programmazione come questo - diagrammi di sintassi e forme estese di Backus-Naur. Per uso pratico più comodo diagrammi di sintassi. Ad esempio, la sintassi delle istruzioni in linguaggio assembly può essere descritta utilizzando i diagrammi di sintassi mostrati nelle figure 10, 11, 12 seguenti.

Figura 10 - Formato della frase di assemblaggio


­ Figura 11 - Formato delle direttive

­ Figura 12 - Formato dei comandi e delle macro

Su questi disegni:

­ nome dell'etichetta- identificatore, il cui valore è l'indirizzo del primo byte della frase del codice sorgente del programma, che esso denota;

­ nome -un identificatore che distingue questa direttiva da altre direttive con lo stesso nome. A seguito dell'elaborazione da parte dell'assemblatore di una determinata direttiva, alcune caratteristiche possono essere assegnate a questo nome;

­ codice operativo (COP) e direttiva - questi sono simboli mnemonici per la corrispondente istruzione macchina, istruzione macro o direttiva del compilatore;

­ operandi -parti di un comando, una macro o una direttiva assembler, che denotano oggetti su cui vengono eseguite le azioni. Gli operandi Assembler sono descritti da espressioni con costanti numeriche e di testo, etichette di variabili e identificatori che utilizzano segni di operazione e alcune parole riservate.

I diagrammi di sintassi aiutano trova e quindi attraversa il percorso dall'input del diagramma (a sinistra) al suo output (a destra). Se esiste un tale percorso, la frase o la costruzione è sintatticamente corretta. Se non esiste un tale percorso, il compilatore non accetterà questa costruzione.

­ 2 Simboli del linguaggio assembly

I caratteri consentiti durante la scrittura del testo dei programmi sono:

1) tutte lettere latine: A-Z,az. In questo caso, le lettere maiuscole e minuscole sono considerate equivalenti;

2) numeri da 0 prima 9 ;

3) segni ? , @ , $ , _ , & ;

4) separatori , . () < > { } + / * % ! " " ? = # ^ .

Le frasi assembler sono formate da gettoni, che sono sequenze sintatticamente inseparabili di caratteri linguistici validi che hanno senso per il traduttore.

gettoni sono:

1) identificatori - sequenze di caratteri validi utilizzati per designare oggetti di programma come codici operativi, nomi di variabili e nomi di etichette. La regola per la scrittura degli identificatori è la seguente: un identificatore può essere costituito da uno o più caratteri;

2) stringhe di caratteri - sequenze di caratteri racchiuse tra virgolette singole o doppie;

3) numeri interi in uno dei seguenti sistemi numerici : binario, decimale, esadecimale. L'identificazione dei numeri durante la scrittura nei programmi assembler viene eseguita secondo determinate regole:

4) i numeri decimali non richiedono simboli aggiuntivi per la loro identificazione, ad esempio 25 o 139. Per l'identificazione nel codice sorgente del programma numeri binari occorre, dopo aver scritto gli zeri e gli uno compresi nella loro composizione, mettere il latino “ b”, ad esempio 10010101 b.

5) i numeri esadecimali hanno più convenzioni nella loro notazione:

Innanzitutto, sono costituiti da numeri. 0...9 , lettere minuscole e maiuscole dell'alfabeto latino un,b, c,d,e,f o UN,B,C,D,e,F.

In secondo luogo, il traduttore potrebbe avere difficoltà a riconoscere i numeri esadecimali a causa del fatto che possono essere costituiti solo dalle cifre 0...9 (ad esempio, 190845) o iniziare con una lettera dell'alfabeto latino (ad esempio, ef15). Per "spiegare" al traduttore che il lessema dato non è un numero decimale o un identificatore, il programmatore deve allocare in modo speciale il numero esadecimale. Per fare ciò, al termine della sequenza di cifre esadecimali che compongono il numero esadecimale, scrivi la lettera latina “ h". Questo è un prerequisito. Se un numero esadecimale inizia con una lettera, è preceduto da uno zero iniziale: 0 ef15 h.

Quasi ogni frase contiene una descrizione dell'oggetto su cui o con l'aiuto del quale viene eseguita un'azione. Questi oggetti sono chiamati operandi. Si possono definire così: operandi- si tratta di oggetti (alcuni valori, registri o celle di memoria) che sono interessati da istruzioni o direttive, oppure si tratta di oggetti che definiscono o perfezionano l'azione di istruzioni o direttive.

È possibile effettuare la seguente classificazione degli operandi:

­ operandi costanti o immediati;

­ operandi di indirizzo;

­ operandi spostati;

contatore di indirizzi;

­ registrare l'operando;

­ operandi di base e di indice;

­ operandi strutturali;

record.

Gli operandi sono componenti elementari che fanno parte dell'istruzione macchina, denotando gli oggetti su cui viene eseguita l'operazione. In un caso più generale, gli operandi possono essere inclusi come componenti in formazioni più complesse dette espressioni.

Espressioni sono combinazioni di operandi e operatori considerati nel loro insieme. Il risultato della valutazione dell'espressione può essere l'indirizzo di una cella di memoria o un valore costante (assoluto).

­ 3 Tipi di istruzioni assembler

Elenchiamo i tipi possibili dichiarazioni dell'assemblatore e regole sintattiche per la formazione di espressioni assembler:

­ operatori aritmetici;

­ operatori di turno;

­ operatori di confronto;

­ operatori logici;

­ operatore di indice;

­ digitare l'operatore di esclusione;

­ operatore di ridefinizione del segmento;

­ operatore di denominazione del tipo di struttura;

­ operatore per ottenere la componente segmento dell'indirizzo dell'espressione;

­ operatore get offset dell'espressione.

1 Direttive di Assemblea

­ Le direttive dell'Assembler sono:

1) Direttive di segmentazione. Nel corso della discussione precedente, abbiamo scoperto tutte le regole di base per scrivere istruzioni e operandi in un programma in linguaggio assembly. Rimane aperta la questione di come formattare correttamente la sequenza di comandi in modo che il traduttore possa elaborarli e il microprocessore possa eseguirli.

Considerando l'architettura del microprocessore, abbiamo appreso che ha sei registri di segmento, attraverso i quali può funzionare contemporaneamente:

­ con un segmento di codice;

­ con un segmento di pila;

­ con un segmento di dati;

­ con tre segmenti di dati aggiuntivi.

Fisicamente, un segmento è un'area di memoria occupata da comandi e (o) dati i cui indirizzi sono calcolati rispetto al valore nel registro di segmento corrispondente. Sintassi Descrizione segmento in assembler è la costruzione mostrata in Figura 13:


­ Figura 13 - Descrizione sintattica del segmento in assembler

È importante notare che la funzionalità di un segmento è in qualche modo più ampia della semplice suddivisione del programma in blocchi di codice, dati e stack. La segmentazione fa parte di un meccanismo più generale relativo a concetto di programmazione modulare. Implica l'unificazione della progettazione dei moduli oggetto creati dal compilatore, compresi quelli provenienti da diversi linguaggi di programmazione. Ciò consente di combinare programmi scritti in diverse lingue. È per l'implementazione di varie opzioni per tale unione che sono destinati gli operandi nella direttiva SEGMENT.

2) Elencare le direttive di controllo. Le direttive di controllo dell'elenco sono suddivise nei seguenti gruppi:

­ direttive generali per il controllo dell'elencazione;

­ direttive di output per includere l'elenco dei file;

­ direttive di output per blocchi di assembly condizionali;

­ direttive di output per l'elenco delle macro;

­ direttive per la visualizzazione delle informazioni sui riferimenti incrociati nell'elenco;

­ elencare le direttive di modifica del formato.

2 Set di istruzioni per il processore

Il set di istruzioni del processore è mostrato nella Figura 14.

Considera i principali gruppi di comandi.

­ Figura 14 - Classificazione delle istruzioni di montaggio

I comandi sono:

1 Comandi di trasferimento dati. Queste istruzioni occupano un posto molto importante nel set di istruzioni di qualsiasi processore. Svolgono le seguenti funzioni essenziali:

­ salvare in memoria il contenuto dei registri interni del processore;

­ copiare il contenuto da un'area di memoria all'altra;

­ scrittura su dispositivi I/O e lettura da dispositivi I/O.

In alcuni processori, tutte queste funzioni vengono eseguite da una singola istruzione MOV (per trasferimenti di byte - MOVB ) naso vari metodi indirizzamento degli operandi.

In altri processori oltre all'istruzione MOV ci sono molti altri comandi per eseguire le funzioni elencate. I comandi di trasferimento dati includono anche comandi di scambio di informazioni (la loro designazione si basa sulla parola Scambio ). Può essere possibile prevedere lo scambio di informazioni tra registri interni, tra due metà di un registro ( SCAMBIO ) o tra un registro e una locazione di memoria.

2 Comandi aritmetici. Le istruzioni aritmetiche trattano i codici operandi come codici binari o BCD numerici. Questi comandi possono essere suddivisi in cinque gruppi principali:

­ comandi per operazioni con punto fisso (addizione, sottrazione, moltiplicazione, divisione);

­ istruzioni in virgola mobile (addizione, sottrazione, moltiplicazione, divisione);

­ comandi di pulizia;

­ comandi di incremento e decremento;

­ comando di confronto.

3 Le istruzioni a virgola fissa operano sui codici nei registri del processore o nella memoria come farebbero con i normali codici binari. Le istruzioni in virgola mobile (virgola) utilizzano un formato di rappresentazione numerica con un esponente e una mantissa (di solito questi numeri occupano due posizioni di memoria consecutive). In moderno potenti processori il set di istruzioni in virgola mobile non è limitato a sole quattro operazioni aritmetiche, ma contiene anche molte altre istruzioni più complesse, ad esempio il calcolo di funzioni trigonometriche, funzioni logaritmiche e anche funzioni complesse necessario per l'elaborazione del suono e dell'immagine.

4 I comandi Clear sono progettati per scrivere un codice zero in un registro o in una cella di memoria. Questi comandi possono essere sostituiti da istruzioni di trasferimento a codice zero, ma istruzioni chiare speciali sono generalmente più veloci delle istruzioni di trasferimento.

5 Comandi di incremento (aumento di uno) e decremento

(riduzioni di uno) sono anche molto convenienti. In linea di principio potrebbero essere sostituite da istruzioni di aggiunta o sottrazione, ma l'incremento e il decremento sono più veloci dell'aggiunta e della sottrazione. Queste istruzioni richiedono un operando di ingresso che sia anche un operando di uscita.

6 L'istruzione Compare serve per confrontare due operandi di ingresso. Infatti calcola la differenza di questi due operandi, ma non forma l'operando di uscita, ma cambia solo i bit nel registro di stato del processore in base al risultato di questa sottrazione. L'istruzione che segue l'istruzione di confronto (solitamente un'istruzione di salto) analizzerà i bit nel registro di stato del processore ed eseguirà azioni in base ai loro valori. Alcuni processori forniscono istruzioni per il confronto a catena di due sequenze di operandi in memoria.

7 Comandi logici. Le istruzioni logiche eseguono operazioni logiche (bit per bit) sugli operandi, ovvero considerano i codici degli operandi non come un singolo numero, ma come un insieme di singoli bit. In questo differiscono dai comandi aritmetici. I comandi logici eseguono le seguenti operazioni di base:

­ AND logico, OR logico, addizione modulo 2 (XOR);

­ spostamenti logici, aritmetici e ciclici;

­ controllo di bit e operandi;

­ impostazione e cancellazione dei bit (flag) del registro di stato del processore ( PSW).

Squadre operazioni logiche consentono il calcolo bit per bit di funzioni logiche di base da due operandi di ingresso. Inoltre, l'operazione AND serve per forzare l'azzeramento dei bit dati (uno degli operandi è il codice maschera, in cui i bit che richiedono l'azzeramento sono posti a zero). L'operazione OR serve per forzare i bit impostati (come uno degli operandi, viene utilizzato il codice maschera, in cui i bit che richiedono l'impostazione a uno sono uguali a uno). L'operazione XOR viene utilizzata per invertire i bit dati (come uno degli operandi, viene utilizzato il codice maschera in cui i bit da invertire sono impostati a uno). Le istruzioni richiedono due operandi di ingresso e formano un operando di uscita.

8 I comandi di spostamento consentono di spostare il codice dell'operando un po' alla volta a destra (verso i bit inferiori) oa sinistra (verso i bit superiori). Il tipo di spostamento (booleano, aritmetico o ciclico) determina quale sarà il nuovo valore del bit più significativo (se spostato a destra) o meno significativo (se spostato a sinistra), e determina anche se il vecchio valore del più significativo il bit verrà memorizzato da qualche parte (se spostato a sinistra) o il bit meno significativo (se spostato a destra). Gli spostamenti rotanti consentono di spostare i bit del codice dell'operando in un cerchio (in senso orario quando si passa a destra o in senso antiorario quando si passa a sinistra). In questo caso, l'anello del cambio può includere o meno la bandiera di trasporto. Il bit del flag di riporto (se utilizzato) è impostato sul bit più significativo per la rotazione a sinistra e sul bit meno significativo per la rotazione a destra. Di conseguenza, il valore del bit dell'indicatore di riporto verrà riscritto nel bit meno significativo in uno spostamento ciclico a sinistra e nel bit più significativo in uno spostamento ciclico a destra.

9 Comandi di salto. I comandi di salto sono progettati per organizzare tutti i tipi di loop, rami, chiamate di subroutine, ecc., ovvero interrompono il flusso sequenziale del programma. Queste istruzioni scrivono un nuovo valore nel registro del contatore di istruzioni e quindi fanno sì che il processore salti non all'istruzione successiva nell'ordine, ma a qualsiasi altra istruzione nella memoria del programma. Alcuni comandi di salto consentono di tornare al punto da cui è stato effettuato il salto, mentre altri no. Se viene fornito un ritorno, i parametri del processore correnti vengono archiviati nello stack. Se non viene fornito alcun ritorno, i parametri del processore corrente non vengono salvati.

I comandi di salto senza tornare indietro sono divisi in due gruppi:

­ comandi di salti incondizionati;

­ istruzioni di salto condizionale.

Questi comandi usano le parole Branch (ramo) e Jump (salto).

Le istruzioni di salto incondizionato causano un salto a un nuovo indirizzo, non importa quale. Possono causare un salto al valore di offset specificato (avanti o indietro) o all'indirizzo di memoria specificato. Come operando di ingresso viene specificato il valore di offset o il nuovo valore di indirizzo.

I comandi di salto condizionale non provocano sempre un salto, ma solo quando vengono soddisfatte le condizioni specificate. Tali condizioni sono solitamente i valori dei flag nel registro di stato del processore ( PSW ). Cioè, la condizione di transizione è il risultato dell'operazione precedente che modifica i valori dei flag. In totale, possono esserci da 4 a 16 di queste condizioni di salto Alcuni esempi di comandi di salto condizionale:

­ salta se uguale a zero;

­ salta se diverso da zero;

­ salta se c'è un overflow;

­ salta se non c'è troppopieno;

­ salta se maggiore di zero;

­ salta se minore o uguale a zero.

Se la condizione di transizione è soddisfatta, un nuovo valore viene caricato nel registro del contatore di istruzioni. Se la condizione di salto non è soddisfatta, il contatore di istruzioni viene semplicemente incrementato e il processore seleziona ed esegue l'istruzione successiva in sequenza.

Specificamente per controllare le condizioni del ramo, viene utilizzata un'istruzione di confronto (CMP) che precede un'istruzione di salto condizionale (o anche più istruzioni di salto condizionale). Ma i flag possono essere impostati da qualsiasi altro comando, come un comando di trasferimento dati, qualsiasi comando aritmetico o logico. Nota che i comandi di salto in sé non cambiano i flag, il che ti consente semplicemente di inserire diversi comandi di salto uno dopo l'altro.

I comandi di interruzione occupano un posto speciale tra i comandi di salto con un ritorno. Queste istruzioni richiedono un numero di interrupt (indirizzo vettoriale) come operando di ingresso.

Conclusione:

Il linguaggio assembly è una rappresentazione simbolica del linguaggio macchina. Il linguaggio assembly per ogni tipo di computer è diverso. Un programma in linguaggio assembly è una raccolta di blocchi di memoria chiamati segmenti di memoria. Ogni segmento contiene una raccolta di frasi linguistiche, ognuna delle quali occupa una riga separata di codice del programma. Le istruzioni assembly sono di quattro tipi: comandi o istruzioni, macro, direttive, righe di commento.

I caratteri validi quando si scrive il testo dei programmi sono tutte lettere latine: A-Z,az. In questo caso, le lettere maiuscole e minuscole sono considerate equivalenti; figure da 0 prima 9 ; segni ? , @ , $ , _ , & ; separatori , . () < > { } + / * % ! " " ? = # ^ .

Si applicano i seguenti tipi di istruzioni assembler e regole di sintassi per la formazione di espressioni assembler. operatori aritmetici, operatori di spostamento, operatori di confronto, operatori logici, operatore di indice, operatore di ridefinizione del tipo, operatore di ridefinizione del segmento, operatore di denominazione del tipo di struttura, operatore di ottenimento del componente del segmento di indirizzo dell'espressione, operatore di ottenimento dell'offset dell'espressione.

Il sistema di comando è diviso in 8 gruppi principali.

­ Domande di prova:

1 Che cos'è il linguaggio assembly?

2 Quali simboli possono essere usati per scrivere comandi in assembler?

3 Cosa sono le etichette e qual è il loro scopo?

4 Spiegare la struttura delle istruzioni di montaggio.

5 Elenca 4 tipi di istruzioni assembler.

Affinché la macchina esegua comandi umani a livello hardware, è necessario impostare una determinata sequenza di azioni nel linguaggio degli "zeri e uno". L'Assembler diventerà un assistente in questa materia. Questa è un'utilità che funziona con la traduzione di comandi in linguaggio macchina. Tuttavia, scrivere un programma è un processo molto lungo e complesso. Questo linguaggio non ha lo scopo di creare luce e semplici azioni. Sul questo momento qualsiasi linguaggio di programmazione che usi (Assembler funziona alla grande) ti consente di scrivere attività speciali efficienti che influiscono notevolmente sul funzionamento dell'hardware. Lo scopo principale è creare micro-istruzioni e piccoli codici. Questo linguaggio fornisce più funzionalità rispetto, ad esempio, a Pascal o C.

Breve descrizione dei linguaggi assembly

Tutti i linguaggi di programmazione sono divisi in livelli: basso e alto. Qualsiasi sistema sintattico della "famiglia" di Assembler è diverso in quanto combina insieme alcuni dei vantaggi dei più comuni e lingue moderne. Sono anche collegati ad altri dal fatto che puoi utilizzare completamente il sistema informatico.

Una caratteristica distintiva del compilatore è la sua facilità d'uso. In questo si differenzia da quelli che funzionano solo con livelli elevati. Se viene preso in considerazione uno di questi linguaggi di programmazione, Assembler funziona due volte più velocemente e meglio. Per scriverci dentro programma leggero non ci vorrà molto.

Brevemente sulla struttura della lingua

Se parliamo in generale del lavoro e della struttura del funzionamento del linguaggio, possiamo dire con certezza che i suoi comandi sono pienamente coerenti con i comandi del processore. Cioè, l'assemblatore usa i codici mnemonici che sono più convenienti da scrivere per una persona.

A differenza di altri linguaggi di programmazione, Assembler utilizza etichette specifiche invece di indirizzi per scrivere le celle di memoria. Vengono tradotti nelle cosiddette direttive con il processo di esecuzione del codice. Si tratta di indirizzi relativi che non influiscono sul funzionamento del processore (non sono tradotti in linguaggio macchina), ma sono necessari al riconoscimento da parte dell'ambiente di programmazione stesso.

Ogni riga del processore ha la sua.In questa situazione, qualsiasi processo sarà corretto, compreso quello tradotto.

Il linguaggio assembly ha diverse sintassi, che saranno discusse nell'articolo.

Professionisti della lingua

L'adattamento più importante e conveniente del linguaggio assembly sarà che può essere utilizzato per scrivere qualsiasi programma per il processore, che sarà molto compatto. Se il codice è enorme, alcuni processi vengono reindirizzati a RAM. Allo stesso tempo, funzionano tutti abbastanza rapidamente e senza guasti, a meno che, ovviamente, non siano controllati da un programmatore qualificato.

Driver, sistemi operativi, BIOS, compilatori, interpreti, ecc. sono tutti programmi in linguaggio assembly.

Quando si utilizza un disassemblatore che si traduce da una macchina all'altra, è possibile comprendere facilmente come funziona questa o quell'attività di sistema, anche se non ci sono spiegazioni. Tuttavia, questo è possibile solo se i programmi sono leggeri. Sfortunatamente, è abbastanza difficile capire codici non banali.

Contro della lingua

Sfortunatamente, è difficile per i programmatori alle prime armi (e spesso professionisti) capire la lingua. L'assemblatore richiede descrizione dettagliata il comando richiesto. A causa del fatto che è necessario utilizzare le istruzioni della macchina, aumenta la probabilità di azioni errate e la complessità dell'esecuzione.

Per scrivere anche di più un semplice programma, il programmatore deve essere qualificato e il suo livello di conoscenza è sufficientemente alto. Lo specialista medio, purtroppo, scrive spesso codici errati.

Se la piattaforma per la quale viene creato il programma viene aggiornata, tutti i comandi devono essere riscritti manualmente - questo è richiesto dalla lingua stessa. L'assemblatore non supporta la funzione di regolazione automatica dello stato di salute dei processi e la sostituzione di eventuali elementi.

Comandi linguistici

Come accennato in precedenza, ogni processore ha il proprio set di istruzioni. Gli elementi più semplici che vengono riconosciuti da qualsiasi tipo sono i seguenti codici:


Usare le direttive

Programmazione di microcontrollori nel linguaggio (Assembler lo permette e fa un ottimo lavoro di funzionamento) del basso livello nella maggior parte dei casi finisce bene. È meglio utilizzare processori con risorse limitate. Per la tecnologia a 32 bit data lingua si adatta benissimo. Spesso puoi vedere le direttive nei codici. Cos'è questo? E a cosa serve?

Per cominciare, è necessario sottolineare che le direttive non sono tradotte in linguaggio macchina. Governano come funziona il compilatore. A differenza dei comandi, questi parametri, avendo varie funzioni, differiscono non a causa di processori diversi, ma a causa di un traduttore diverso. Tra le principali direttive figurano:


origine del nome

Qual è il nome della lingua - "Assembler"? Stiamo parlando di un traduttore e di un compilatore, che crittografano i dati. Dall'inglese Assembler non significa altro che un assemblatore. Il programma non è stato compilato a mano, è stata utilizzata una struttura automatica. Inoltre, al momento, utenti e specialisti hanno già cancellato la differenza tra i termini. Spesso l'assembler è chiamato linguaggi di programmazione, sebbene sia solo un'utilità.

A causa del nome collettivo generalmente accettato, alcune persone danno per scontato che esista un'unica lingua di basso livello (o norme standard per essa). In modo che il programmatore capisca quale struttura in questione, è necessario specificare per quale piattaforma viene utilizzato questo o quel linguaggio assembly.

strumenti macro

I linguaggi Assembler, che sono relativamente recenti, dispongono di funzionalità macro. Semplificano sia la scrittura che l'esecuzione di un programma. Grazie alla loro presenza, il traduttore esegue il codice scritto molte volte più velocemente. Quando crei una scelta condizionale, puoi scrivere un enorme blocco di comandi, ma è più facile usare le macro. Ti permetteranno di passare rapidamente da un'azione all'altra, nel caso in cui una condizione sia soddisfatta o meno.

Quando si utilizzano le direttive del linguaggio macro, il programmatore riceve le macro Assembler. A volte può essere ampiamente utilizzato, a volte lo è caratteristiche funzionali fino a una squadra. La loro presenza nel codice semplifica il lavoro con esso, lo rende più comprensibile e visivo. Tuttavia, dovresti comunque stare attento: in alcuni casi, le macro, al contrario, peggiorano la situazione.

Introduzione.

Viene chiamata la lingua in cui è scritto il programma originale ingresso lingua e la lingua in cui è tradotto per l'esecuzione da parte del processore - fine settimana linguaggio. Viene chiamato il processo di conversione di una lingua di input in una lingua di output trasmissione. Poiché i processori sono in grado di eseguire programmi in linguaggio macchina binario, che non viene utilizzato per la programmazione, è necessaria la traduzione di tutti i programmi sorgente. conosciuto due strade traduzioni: compilazione e interpretazione.

In compilazione il programma sorgente viene prima completamente tradotto in un programma equivalente nella lingua di destinazione, chiamato oggetto programma e quindi eseguito. Questo processo viene eseguito utilizzando uno speciale programmi, chiamato compilatore. Viene chiamato un compilatore per il quale il linguaggio di input è una rappresentazione simbolica del linguaggio macchina (output) dei codici binari assemblatore.

In interpretazioni ogni riga di testo del programma sorgente viene analizzata (interpretata) e il comando in essa specificato viene immediatamente eseguito. L'attuazione di questo metodo risiede con programma per interpreti. L'interpretazione richiede molto tempo. Per aumentarne l'efficienza, invece di elaborare ogni riga, l'interprete converte preliminarmente tutto comando stringhe in caratteri (

). La sequenza di simboli generata viene utilizzata per eseguire le funzioni assegnate al programma originale.

Il linguaggio assembly discusso di seguito viene implementato utilizzando la compilazione.

Caratteristiche della lingua.

Le caratteristiche principali dell'assemblatore:

● al posto dei codici binari, la lingua utilizza nomi simbolici - mnemonici. Ad esempio, per il comando di addizione (

) viene utilizzato il mnemonico

Sottrazioni (

moltiplicazione (

Divisioni (

ecc. I nomi simbolici sono usati anche per indirizzare le celle di memoria. Per programmare in linguaggio assembly, invece di codici binari e indirizzi, è necessario conoscere solo i nomi simbolici in cui traduce l'assembler codici binari;

ogni affermazione corrisponde un comando macchina(codice), ovvero esiste una corrispondenza biunivoca tra istruzioni macchina e operatori in un programma in linguaggio assembly;

● la lingua fornisce l'accesso a tutti gli oggetti e squadre. Le lingue alto livello non hanno tale capacità. Ad esempio, il linguaggio assembly consente di controllare un bit di registro flag e un linguaggio di alto livello (ad esempio,

) non ha questa capacità. Si noti che i linguaggi per la programmazione dei sistemi (ad esempio C) occupano spesso una posizione intermedia. In termini di accessibilità, sono più vicini al linguaggio assembly, ma hanno la sintassi di un linguaggio di alto livello;

● linguaggio assembly non è una lingua universale. Ogni gruppo specifico di microprocessori ha il proprio assemblatore. Le lingue di alto livello non hanno questo svantaggio.

A differenza dei linguaggi di alto livello, la scrittura e il debug di un programma in linguaggio assembly richiede molto tempo. Nonostante questo, il linguaggio assembly è diventato ampio utilizzo a causa delle seguenti circostanze:

● Un programma scritto in linguaggio assembly ha un significato taglie più piccole ed è molto più veloce di un programma scritto in un linguaggio di alto livello. Per alcune applicazioni, questi indicatori svolgono un ruolo primario, ad esempio molti programmi di sistema (compresi i compilatori), programmi nelle carte di credito, telefono cellulare, driver di dispositivo, ecc.;

● Alcune procedure richiedono l'accesso completo all'hardware, che di solito non è possibile in un linguaggio di alto livello. Questo caso include interrupt e gestori di interrupt in sistemi operativi, nonché controller di dispositivo in sistemi embedded che funzionano in tempo reale.

Nella maggior parte dei programmi, solo una piccola percentuale del codice totale è responsabile di una grande percentuale del tempo di esecuzione del programma. In genere, l'1% del programma è responsabile del 50% del tempo di esecuzione e il 10% del programma è responsabile del 90% del tempo di esecuzione. Pertanto, per scrivere programma specifico in condizioni reali vengono utilizzati sia l'assembler che uno dei linguaggi di alto livello.

Formato operatore in linguaggio assembly.

Un programma in linguaggio assembly è un elenco di comandi (istruzioni, frasi), ognuno dei quali occupa una riga separata e contiene quattro campi: un campo etichetta, un campo operazione, un campo operando e un campo commento. Ogni campo ha una colonna separata.

campo etichetta.

Per il campo etichetta è allocata la colonna 1. Un'etichetta è un nome simbolico, o identificatore, indirizzi memoria. È necessario per poter:

● effettuare una transizione condizionale o incondizionata al comando;

● ottenere l'accesso al luogo in cui sono archiviati i dati.

Tali affermazioni sono etichettate. Per designare un nome, vengono utilizzate lettere (maiuscole) dell'alfabeto inglese e numeri. Il nome deve iniziare con una lettera e terminare con due punti. L'etichetta dei due punti può essere scritta su una riga separata e l'opcode può essere scritto sulla riga successiva nella colonna 2, il che semplifica il lavoro del compilatore. L'assenza dei due punti rende impossibile distinguere tra un'etichetta e un codice operativo se si trovano su righe separate.

In alcune versioni del linguaggio assembly, i due punti vengono inseriti solo dopo le etichette delle istruzioni, non dopo le etichette dei dati e la lunghezza dell'etichetta può essere limitata a 6 o 8 caratteri.

Il campo etichetta non deve contenere gli stessi nomi, poiché l'etichetta è associata agli indirizzi dei comandi. Se durante l'esecuzione del programma non è necessario richiamare un comando o dati dalla memoria, il campo dell'etichetta rimane vuoto.

Campo codice transazione.

Questo campo contiene il comando mnemonico o pseudo-comando (vedi sotto). Il codice mnemonico del comando è scelto dagli sviluppatori del linguaggio. In linguaggio assembly

mnemonico selezionato per caricare il registro dalla memoria

), e per memorizzare il contenuto del registro - il mnemonico

). In linguaggi assembler

puoi usare lo stesso nome rispettivamente per entrambe le operazioni

Se la scelta dei nomi mnemonici può essere arbitraria, la necessità di utilizzare due istruzioni macchina è dovuta all'architettura del processore

I mnemonici del registro dipendono anche dalla versione dell'assembler (Tabella 5.2.1).

Campo operando.

Qui si trova Informazioni aggiuntive necessari per eseguire l'operazione. Nel campo degli operandi per le istruzioni di salto viene indicato l'indirizzo dove si vuole saltare, così come indirizzi e registri che sono operandi per l'istruzione macchina. Ad esempio, ecco gli operandi che possono essere utilizzati per processori a 8 bit

● dati numerici,

presentato in vari sistemi fare i conti. Per indicare il sistema numerico utilizzato, la costante è seguita da una delle lettere latine: B,

Rispettivamente binario, ottale, esadecimale, sistema decimale fare i conti (

potrebbe non essere registrato). Se la prima cifra del numero esadecimale è A, B, C,

Quindi viene aggiunto uno 0 (zero) insignificante davanti;

● codici dei registri interni del microprocessore e delle celle di memoria

M (fonti o destinatari di informazioni) sotto forma di lettere A, B, C,

M o i loro indirizzi in qualsiasi sistema numerico (ad esempio, 10V - indirizzo di registro

nel sistema binario);

● identificatori,

per le coppie di aeromobili registrati,

Le prime lettere B

H; per una coppia di accumulatore e registro delle funzioni -

; per il contatore del programma -

; per il puntatore dello stack -

● etichette indicanti gli indirizzi degli operandi o le istruzioni successive in condizionale

(quando la condizione è soddisfatta) e transizioni incondizionate. Ad esempio, operando M1 nel comando

significa la necessità di un passaggio incondizionato al comando, il cui indirizzo nel campo dell'etichetta è contrassegnato con l'identificatore M1;

● espressioni,

che sono costruiti collegando i dati discussi sopra usando operatori aritmetici e logici. Si noti che il modo in cui viene riservato lo spazio dati dipende dalla versione della lingua. Sviluppatori di linguaggi assembly per

Definisci parola) e successivamente introdotto Opzione alternativa.

che fin dall'inizio era nel linguaggio dei processori

Nella versione in lingua

Usato

definire una costante).

I processori elaborano operandi di diverse lunghezze. Per definirlo, gli sviluppatori di assembler hanno preso diverse decisioni, ad esempio:

II registri di diversa lunghezza hanno nomi diversi: EAX - per posizionare operandi a 32 bit (tipo

); AX - per 16 bit (tipo

e AN - per 8 bit (tipo

● per i processori

i suffissi vengono aggiunti a ogni codice operativo: suffix

Per tipo

; suffisso ".B" per tipo

per operandi di diversa lunghezza vengono utilizzati diversi opcode, ad esempio per caricare un byte, una halfword (

) e le parole nel registro a 64 bit utilizzano codici operativi

rispettivamente.

Campo dei commenti.

Questo campo fornisce spiegazioni sulle azioni del programma. I commenti non influiscono sul funzionamento del programma e sono destinati a una persona. Potrebbero essere necessari per modificare un programma che, senza tali commenti, potrebbe risultare del tutto incomprensibile anche a programmatori esperti. Un commento inizia con un carattere e viene utilizzato per spiegare e documentare i programmi. Il carattere iniziale di un commento può essere:

● punto e virgola (;) nelle lingue per i processori dell'azienda

Punto esclamativo(!) nelle lingue per

Ogni riga separata riservata a un commento è preceduta da un carattere iniziale.

Pseudo comandi (direttive).

Nel linguaggio assembly si possono distinguere due tipi principali di comandi:

di base istruzioni equivalenti al codice macchina del processore. Questi comandi eseguono tutte le elaborazioni fornite dal programma;

pseudo-comandi o direttive, progettato per servire il processo di traduzione del programma nel linguaggio delle combinazioni di codici. A titolo di esempio, nella tabella. 5.2.2 mostra alcuni pseudo-comandi dell'as-assembler

per la famiglia

.

Durante la programmazione, ci sono situazioni in cui, secondo l'algoritmo, la stessa catena di comandi deve essere ripetuta più volte. Per uscire da questa situazione, puoi:

● scrivere la sequenza di comandi desiderata ogni volta che si verifica. Questo approccio porta ad un aumento del volume del programma;

● organizzare questa sequenza in una procedura (subroutine) e richiamarla se necessario. Tale uscita ha i suoi inconvenienti: ogni volta si deve eseguire una speciale istruzione di chiamata di procedura e un'istruzione di ritorno, che, con una sequenza breve e di uso frequente, può ridurre notevolmente la velocità del programma.

Il più semplice e metodo efficace ripetizione ripetuta di una catena di comandi è da usare macro, che può essere pensato come uno pseudo-comando progettato per ritradurre un gruppo di comandi che si incontrano frequentemente in un programma.

Una macro, o istruzione macro, è caratterizzata da tre aspetti: definizione della macro, inversione della macro ed espansione della macro.

definizione macro

Questa è una designazione per una sequenza ripetuta ripetutamente di comandi di programma, utilizzata per i riferimenti nel testo del programma.

Una macro ha la seguente struttura:

Elenco di espressioni; definizione macro

Ci sono tre parti nella struttura di definizione della macro di cui sopra:

● intestazione

macro contenente il nome

Pseudo-comando

e una serie di parametri;

● punteggiato corpo macro;

● squadra

la laurea

definizioni macro.

Un set di parametri macro contiene un elenco di tutti i parametri forniti nel campo operando per il gruppo di istruzioni selezionato. Se questi parametri vengono forniti in precedenza nel programma, possono essere omessi nell'intestazione della definizione della macro.

Per il rimontaggio del gruppo di istruzioni selezionato, viene utilizzata una chiamata, composta dal nome

macro e lista parametri con altri valori.

Quando l'assembler incontra una definizione di macro durante la compilazione, la memorizza nella tabella di definizione della macro. Con successive apparizioni nel programma del nome (

) di una macro, l'assembler lo sostituisce con il corpo della macro.

Viene chiamato l'utilizzo di un nome macro come codice operativo macro-inversione(chiamata macro) e la sua sostituzione con il corpo della macro - macroespansione.

Se il programma è rappresentato come una sequenza di caratteri (lettere, numeri, spazi, punteggiatura e ritorni a capo per passare a nuova linea), quindi l'espansione macro consiste nel sostituire alcune catene di questa sequenza con altre catene.

L'espansione della macro avviene durante il processo di assemblaggio, non durante l'esecuzione del programma. Modi per manipolare stringhe di caratteri sono assegnati a strumenti macro.

Il processo di assemblaggio viene eseguito in due passaggi:

● Al primo passaggio, tutte le definizioni delle macro vengono mantenute e le chiamate alle macro vengono espanse. In questo caso, il programma sorgente viene letto e convertito in un programma in cui tutte le definizioni di macro vengono rimosse e ogni chiamata di macro viene sostituita da un corpo di macro;

● Il secondo passaggio elabora il programma ricevuto senza macro.

Macro con parametri.

Per lavorare con sequenze ripetute di comandi, i cui parametri possono assumere valori diversi, vengono fornite le definizioni delle macro:

● con effettivo parametri che vengono inseriti nel campo operando della chiamata macro;

● con formale parametri. Durante l'espansione della macro, ogni parametro formale che appare nel corpo della macro viene sostituito dal corrispondente parametro effettivo.

utilizzando macro con parametri.

Il programma 1 mostra due sequenze di comandi simili, diverse per il fatto che il primo scambia P e

E il secondo

Il programma 2 include una macro con due parametri formali P1 e P2. Durante l'espansione della macro, ogni carattere P1 all'interno del corpo della macro viene sostituito dal primo parametro effettivo (P,

), e il simbolo P2 viene sostituito dal secondo parametro effettivo (

) dal programma n. 1. In una chiamata macro

il programma 2 è contrassegnato: P,

Il primo parametro effettivo,

Il secondo parametro effettivo.

Programma 1

Programma 2

MOV EBX,Q MOV EAX,Pl

MOV Q,EAX MOV EBX,P2

MOV P,EBX MOV P2,EAX

Capacità estese.

Considera alcune funzionalità avanzate della lingua

Se una macro contenente un'istruzione di ramo condizionale e un'etichetta a cui saltare viene chiamata due o più volte, l'etichetta verrà duplicata (problema di duplicazione dell'etichetta), causando un errore. Pertanto, ad ogni chiamata viene assegnata (dal programmatore) un'etichetta separata come parametro. Nella lingua

l'etichetta è dichiarata locale (

) e grazie alle funzionalità avanzate, l'assemblatore genera automaticamente un'etichetta diversa ogni volta che la macro viene espansa.

consente di definire macro all'interno di altre macro. Questa funzione avanzata è molto utile se combinata con il collegamento condizionale del programma. Ritenere

SE WORDSIZE GT 16 M2 MACRO

La macro M2 può essere definita in entrambe le parti dell'istruzione

Tuttavia, la definizione dipende dal fatto che il programma venga assemblato su un processore a 16 o 32 bit. Se M1 non viene chiamato, la macro M2 non verrà definita affatto.

Un'altra funzionalità avanzata è che le macro possono chiamare altre macro, inclusi se stessi - ricorsivo chiamata. In quest'ultimo caso, per evitare un loop infinito, la macro deve passare a se stessa un parametro, che cambia ad ogni espansione, e anche dai un'occhiata questo parametro e terminare la ricorsione quando il parametro raggiunge un determinato valore.

Sull'uso delle macro in assembler.

Quando si utilizzano le macro, l'assemblatore deve essere in grado di eseguire due funzioni: salvare le definizioni delle macro e espandere le chiamate macro.

Salvataggio delle definizioni delle macro.

Tutti i nomi delle macro sono memorizzati in una tabella. Ogni nome è accompagnato da un puntatore alla macro corrispondente in modo che possa essere richiamato se necessario. Alcuni assemblatori hanno una tabella separata per i nomi delle macro, altri hanno una tabella comune in cui, insieme ai nomi delle macro, ci sono tutti i comandi e le direttive della macchina.

Quando si incontra una macro durante l'assemblaggio creato:

nuovo elemento tavoli con il nome della macro, il numero di parametri e un puntatore ad un'altra tabella di definizione della macro in cui verrà memorizzato il corpo della macro;

● elenco formale parametri.

Il corpo della macro, che è semplicemente una stringa di caratteri, viene quindi letto e memorizzato nella tabella di definizione della macro. I parametri formali che si verificano nel corpo del loop sono contrassegnati carattere speciale.

Rappresentazione interna di una macro

dall'esempio sopra per il programma 2 (p. 244) è:

MOV EAX, MOV EBX, MOV MOV e

dove il punto e virgola viene utilizzato come carattere di ritorno a capo e la e commerciale & viene utilizzato come carattere del parametro formale.

Estensione di chiamata macro.

Ogni volta che viene incontrata una definizione di macro durante l'assemblaggio, viene archiviata nella tabella delle macro. Quando viene chiamata una macro, l'assembler sospende temporaneamente la lettura dei dati di input dal dispositivo di input e inizia a leggere il corpo della macro salvata. I parametri formali estratti dal corpo della macro sono sostituiti dai parametri effettivi e forniti dal bando. Una e commerciale & davanti ai parametri permette all'assemblatore di riconoscerli.

Sebbene esistano molte versioni di assembler, i processi di assemblaggio hanno caratteristiche comuni e sono simili in molti modi. Il lavoro di un assemblatore a due passaggi è considerato di seguito.

Assemblatore a due passaggi.

Il programma è composto da un numero di operatori. Pertanto, sembrerebbe che la seguente sequenza di azioni possa essere utilizzata durante il montaggio:

● tradurlo in linguaggio macchina;

● trasferire il codice macchina ricevuto in un file e la parte corrispondente dell'elenco - in un altro file;

● ripetere le procedure di cui sopra fino alla trasmissione dell'intero programma.

Tuttavia, questo approccio non è efficiente. Un esempio è il cosiddetto problema collegamento principale. Se la prima istruzione è un salto all'istruzione P alla fine del programma, l'assemblatore non può tradurla. Deve prima determinare l'indirizzo dell'operatore P, e per questo è necessario leggere l'intero programma. Viene richiamata ogni lettura completa del programma originale passaggio. Mostriamo come possiamo risolvere il problema del riferimento diretto utilizzando due passaggi:

al primo passaggio raccogliere e memorizzare tutte le definizioni dei simboli (comprese le etichette) nella tabella e, al secondo passaggio, leggere e assemblare ogni operatore. Questo metodo è relativamente semplice, ma il secondo passaggio attraverso il programma originale richiede ulteriore tempo di I/O;

● al primo passaggio, convertire programma in una forma intermedia e salvalo in una tabella, e il secondo passaggio viene eseguito non secondo il programma originale, ma secondo la tabella. Questo metodo di assemblaggio consente di risparmiare tempo, poiché al secondo passaggio non vengono eseguite operazioni di I/O.

Primo passaggio.

Scopo del primo passaggio- costruire una tabella dei simboli. Come notato in precedenza, un altro obiettivo del primo passaggio è salvare tutte le definizioni delle macro ed espandere le chiamate man mano che vengono visualizzate. Pertanto, sia la definizione del carattere che l'espansione della macro si verificano nello stesso passaggio. Il simbolo può essere uno dei due etichetta, o significato, a cui viene assegnato un nome specifico utilizzando la direttiva -you:

;Valore - dimensione del buffer

Dando un significato ai nomi simbolici nel campo dell'etichetta dell'istruzione, l'assemblatore imposta essenzialmente gli indirizzi che ciascuna istruzione avrà durante l'esecuzione del programma. Per fare ciò, l'assemblatore durante il processo di assemblaggio salva contatore di indirizzi di istruzioni(

) come variabile speciale. All'inizio del primo passaggio, il valore della variabile speciale viene impostato su 0 e incrementato dopo ogni comando elaborato della lunghezza di quel comando. A titolo di esempio, nella tabella. 5.2.3 mostra un frammento del programma che indica la lunghezza dei comandi ei valori dei contatori. Le tabelle vengono generate durante il primo passaggio nomi di simboli, direttive e codici operativi, e se necessario letterale tavolo. Un valore letterale è una costante per la quale l'assemblatore riserva automaticamente memoria. Notiamo subito che i processori moderni contengono istruzioni con indirizzi diretti, quindi i loro assemblatori non supportano i valori letterali.

Tabella dei simboli

contiene un elemento per ogni nome (Tabella 5.2.4). Ogni elemento della tabella dei simboli contiene il nome stesso (o un puntatore ad esso), il suo valore numerico e talvolta alcune informazioni aggiuntive, che possono includere:

● la lunghezza del campo dati associato al simbolo;

● bit di rimappatura della memoria (che indicano se il valore di un simbolo cambia se il programma viene caricato ad un indirizzo diverso da quello previsto dall'assemblatore);

● informazioni sulla possibilità di accedere al simbolo dall'esterno della procedura.

I nomi simbolici sono etichette. Possono essere specificati utilizzando gli operatori (ad esempio,

Tabella delle direttive.

Questa tabella elenca tutte le direttive, o pseudo-comandi, che si verificano durante l'assemblaggio di un programma.

Tabella dei codici di operazione.

Per ogni codice operativo, la tabella ha colonne separate: designazione codice operativo, operando 1, operando 2, valore esadecimale del codice operativo, lunghezza dell'istruzione e tipo di istruzione (Tabella 5.2.5). I codici operazione sono divisi in gruppi a seconda del numero e del tipo di operandi. Il tipo di comando determina il numero del gruppo e specifica la procedura che viene chiamata per elaborare tutti i comandi in quel gruppo.

Secondo passaggio.

Scopo del secondo passaggio- creare un programma oggetto e stampare, se necessario, un protocollo di montaggio; informazioni di output necessarie al linker per collegare le procedure che sono state assemblate in momenti diversi in un file eseguibile.

Nel secondo passaggio (come nel primo) le righe contenenti le affermazioni vengono lette ed elaborate una dopo l'altra. L'operatore originale e l'output da esso derivato in esadecimale oggetto il codice può essere stampato o memorizzato nel buffer per la stampa successiva. Dopo aver azzerato il contatore degli indirizzi dei comandi, viene chiamata l'istruzione successiva.

Il programma originale può contenere errori, ad esempio:

il simbolo dato non è definito o definito più di una volta;

● L'opcode è rappresentato da un nome non valido (a causa di un errore di battitura), non è provvisto di un numero sufficiente di operandi o ha troppi operandi;

● nessun operatore

Alcuni assemblatori possono rilevare un simbolo non definito e sostituirlo. Tuttavia, nella maggior parte dei casi, quando viene trovata un'istruzione con un errore, l'assembler visualizza un messaggio di errore sullo schermo e tenta di continuare il processo di assemblaggio.

Articoli dedicati al linguaggio assembly.

Informazioni generali sul linguaggio assembly

Il linguaggio simbolico assembly consente di eliminare ampiamente le carenze della programmazione in linguaggio macchina.

Il suo principale vantaggio è che in linguaggio assembly tutti gli elementi del programma sono rappresentati in forma simbolica. La trasformazione dei nomi dei comandi simbolici nei loro codici binari è responsabilità di programma speciale- assembler, che libera il programmatore dal lavoro laborioso ed elimina gli inevitabili errori.

I nomi simbolici introdotti durante la programmazione in linguaggio assembly, di regola, riflettono la semantica del programma e l'abbreviazione dei comandi, la loro funzione principale. Ad esempio: PARAM - parametro, TABLE - tabella, MASK - maschera, ADD - addizione, SUB - sottrazione, ecc. n.Tali nomi sono facilmente ricordati dal programmatore.

Per la programmazione in linguaggio assembly è necessario disporre di strumenti complessi rispetto alla programmazione in linguaggio macchina: servono sistemi informatici basati su microcomputer o PC con un set periferiche(tastiera alfanumerica, display a caratteri, floppy disk drive e stampante), nonché sistemi residenti o di programmazione incrociata per i tipi di microprocessori richiesti. Il linguaggio assembly consente di scrivere ed eseguire il debug in modo efficiente di programmi molto più complessi rispetto al linguaggio macchina (fino a 1 - 4 KB).

I linguaggi assembly sono orientati alla macchina, ovvero dipendono dal linguaggio macchina e dalla struttura del microprocessore corrispondente, poiché assegnano un nome simbolico specifico a ciascuna istruzione del microprocessore.

I linguaggi assembly forniscono un aumento significativo della produttività dei programmatori rispetto ai linguaggi macchina e allo stesso tempo mantengono la capacità di utilizzare tutte le risorse hardware accessibili dal software del microprocessore. Ciò consente a programmatori esperti di scrivere programmi che vengono eseguiti in un tempo più breve e occupano meno memoria rispetto ai programmi scritti in un linguaggio di alto livello.

A tal proposito, quasi tutti i programmi di controllo dei dispositivi di I/O (driver) sono scritti in linguaggio assembly, nonostante la presenza di una gamma abbastanza ampia di linguaggi di alto livello.

Utilizzando il linguaggio assembly, il programmatore può impostare i seguenti parametri:

mnemonico (nome simbolico) di ogni comando del linguaggio macchina del microprocessore;

formato standard per le righe di un programma descritto in assembler;

formato per specificare vari modi opzioni di indirizzamento e comando;

formato per specificare costanti di carattere e costanti di tipo intero in vari sistemi numerici;

pseudo-comandi che controllano il processo di assemblaggio (traduzione) del programma.

In linguaggio assembly, il programma viene scritto riga per riga, ovvero viene assegnata una riga per ciascuna istruzione.

Per i microcomputer costruiti sulla base dei tipi più comuni di microprocessori, possono esserci diverse varianti del linguaggio assembly, tuttavia, di solito una ha una distribuzione pratica: questo è il cosiddetto linguaggio assembly standard

La programmazione a livello di istruzioni macchina è il livello minimo a cui è possibile la programmazione. Il sistema di istruzioni della macchina deve essere sufficiente per attuare le azioni richieste impartendo istruzioni all'hardware del computer.

Ogni istruzione macchina è composta da due parti:

operativo - determinare "cosa fare";

· operando - definizione di oggetti di elaborazione, "cosa fare con".

L'istruzione macchina del microprocessore, scritta in linguaggio assembly, è un'unica riga con la seguente forma sintattica:

etichetta comando/operandi direttivi ;commenti

In questo caso, un campo obbligatorio in una riga è un comando o una direttiva.

L'etichetta, il comando/la direttiva e gli operandi (se presenti) sono separati da almeno uno spazio o un carattere di tabulazione.

Se è necessario continuare un comando o una direttiva nella riga successiva, viene utilizzato il carattere barra rovesciata: \.

Per impostazione predefinita, il linguaggio assembly non distingue tra lettere maiuscole e minuscole nei comandi o nelle direttive.

Indirizzamento diretto: L'indirizzo effettivo è determinato direttamente dal campo di offset dell'istruzione macchina, che può avere una dimensione di 8, 16 o 32 bit.

mov eax, somma ; ax = somma

L'assembler sostituisce sum con il corrispondente indirizzo memorizzato nel segmento dati (di default, indirizzato dal registro ds) e inserisce il valore memorizzato in address sum nel registro eax.

indirizzamento indiretto a sua volta ha i seguenti tipi:

Indirizzamento di base indiretto (registro);

Indirizzamento di base indiretto (registro) con offset;

· indirizzamento indiretto dell'indice;

· indirizzamento indiretto dell'indice di base.

Indirizzamento di base indiretto (registro). Con questo indirizzamento, l'indirizzo effettivo dell'operando può trovarsi in uno qualsiasi dei registri scopo generale, ad eccezione di sp/esp e bp/ebp (questi sono registri specifici per lavorare con un segmento dello stack). Sintatticamente in un'istruzione, questa modalità di indirizzamento è espressa racchiudendo il nome del registro tra parentesi quadre.

spostare l'asse, ; eax = *esi; *esi valore all'indirizzo esi

Strutture in linguaggio assembly

Gli array che abbiamo considerato sopra sono una raccolta di elementi dello stesso tipo. Ma spesso nelle applicazioni è necessario considerare un determinato insieme di dati tipo diverso come un singolo tipo.

Questo è molto rilevante, ad esempio, per i programmi di database, dove è necessario associare ad un oggetto una raccolta di dati di diverso tipo.

Ad esempio, in precedenza abbiamo esaminato il Listato 4, che funzionava con una matrice di elementi a tre byte. Ogni elemento, a sua volta, era costituito da due elementi di tipo diverso: un campo contatore a un byte e un campo a due byte che poteva contenere alcune informazioni in più necessarie per l'archiviazione e l'elaborazione. Se il lettore ha familiarità con uno dei linguaggi di alto livello, allora sa che un tale oggetto viene solitamente descritto utilizzando un tipo di dati speciale - strutture.

Per migliorare l'usabilità del linguaggio assembly, è stato introdotto anche questo tipo di dati.

Per definizione struttura è un tipo di dati costituito da un numero fisso di elementi di diverso tipo.

Per utilizzare le strutture in un programma, devi fare tre cose:

    Chiedere modello di struttura .

    In sostanza, questo significa definire un nuovo tipo di dati, che può essere successivamente utilizzato per definire variabili di questo tipo.

    Definire istanza della struttura .

    Questa fase prevede l'inizializzazione di una variabile specifica con una struttura predefinita (utilizzando un modello).

    Organizzare accedere ai membri della struttura .

È molto importante che tu capisca fin dall'inizio qual è la differenza tra descrizione strutture nel programma e le sue definizione.

descrivere struttura in un programma significa solo indicare il suo schema o modello; la memoria non è allocata.

Questo modello può essere considerato solo come un'informazione per il traduttore sulla posizione dei campi e sul loro valore predefinito.

Definire struttura significa istruire il traduttore ad allocare memoria e assegnare un nome simbolico a questa area di memoria.

È possibile descrivere la struttura nel programma una sola volta e definirla un numero qualsiasi di volte.

Descrizione del modello di struttura

La dichiarazione del modello di struttura ha la seguente sintassi:

nome_struttura STRUC

nome_struttura FINE

Qui è una sequenza di direttive di descrizione dei dati db, dw, gg, dq e dt.

I loro operandi determinano la dimensione dei campi e, facoltativamente, i valori iniziali. Questi valori eventualmente inizializzeranno i campi corrispondenti quando la struttura sarà definita.

Come abbiamo già notato descrivendo il modello, non viene allocata memoria, poiché si tratta solo di informazioni per il traduttore.

Posizione template nel programma può essere arbitrario, ma, seguendo la logica del traduttore one-pass, deve essere posizionato prima del punto in cui è definita la variabile con il tipo di questa struttura. Cioè, quando si descrive una variabile con il tipo di una struttura in un segmento di dati, il suo modello deve essere posizionato all'inizio del segmento di dati o prima di esso.

Prendi in considerazione l'idea di lavorare con le strutture utilizzando l'esempio della modellazione di un database di dipendenti di un determinato dipartimento.

Per semplicità, per evitare i problemi di conversione delle informazioni in fase di input, concorderemo sul fatto che tutti i campi siano simbolici.

Definiamo la struttura dei record di questo database con il seguente schema:

Definizione dei dati con un tipo di struttura

Per utilizzare la struttura descritta con l'ausilio del template nel programma, è necessario definire una variabile con il tipo di tale struttura. Per questo viene utilizzata la seguente sintassi:

[nome variabile] nome_struttura

    nome della variabile- identificatore variabile del tipo strutturale dato.

    La specifica di un nome di variabile è facoltativa. Se non viene specificato, verrà semplicemente allocata un'area di memoria con la dimensione della somma delle lunghezze di tutti gli elementi della struttura.

    elenco di valori- un elenco separato da virgole dei valori iniziali degli elementi della struttura racchiusi tra parentesi angolari.

    Anche il suo compito è facoltativo.

    Se l'elenco è incompleto, tutti i campi della struttura per la variabile data vengono inizializzati con i valori del modello, se presenti.

    È consentito inizializzare singoli campi, ma in questo caso i campi mancanti devono essere separati da virgole. I campi mancanti verranno inizializzati con i valori del modello struct. Se, quando definiamo una nuova variabile con il tipo di questa struttura, siamo d'accordo con tutti i valori di campo ​​nel suo modello (cioè impostato di default), allora devi solo scrivere parentesi angolari.

    Per esempio: lavoratore vincitore.

Ad esempio, definiamo diverse variabili con il tipo di struttura sopra descritto.

Metodi di struttura

L'idea di introdurre un tipo strutturale in qualsiasi linguaggio di programmazione è quella di combinare variabili di diversi tipi in un unico oggetto.

Il linguaggio deve fornire un mezzo per accedere a queste variabili all'interno di una particolare istanza di struct. Per fare riferimento in un comando a un campo di qualche struttura, viene utilizzato un operatore speciale - simbolo ". " (punto). Viene utilizzato nella seguente sintassi:

    indirizzo_espressione- un identificatore variabile di qualche tipo strutturale o un'espressione tra parentesi secondo le regole sintattiche di seguito indicate (Fig. 1);

    nome_campo_struttura- nome del campo dal modello di struttura.

    Questo, infatti, è anche un indirizzo, o meglio, l'offset del campo dall'inizio della struttura.

Quindi l'operatore" . " (punto) valuta l'espressione

Riso. 5. Sintassi di un'espressione di indirizzo in un operatore di accesso al campo della struttura

Dimostriamo sull'esempio della struttura che abbiamo definito lavoratore alcune tecniche per lavorare con le strutture.

Ad esempio, estrai in ascia valori di campo con l'età. Poiché è improbabile che l'età di una persona abile sia superiore a 99 anni, dopo aver inserito il contenuto di questo campo di caratteri nel registro ascia sarà conveniente convertirlo in rappresentazione binaria con il comando aad.

Fai attenzione, perché a causa del principio di archiviazione dei dati "byte basso con indirizzo basso" verrà inserita la cifra più alta dell'età al, e il più giovane in Ah.

Per correggerlo basta usare il comando xchg al, ah:

mov ax, parola ptr sotr1.age ;at al age sotr1

ed è possibile così:

Ulteriore lavoro con un array di strutture viene eseguito allo stesso modo di un array unidimensionale. Qui sorgono diverse domande:

Come gestire le dimensioni e come organizzare l'indicizzazione degli elementi dell'array?

Come altri identificatori definiti nel programma, il traduttore assegna al nome del tipo di struttura e al nome della variabile con il tipo di struttura un attributo di tipo. Il valore di questo attributo è la dimensione in byte occupata dai campi di questa struttura. È possibile estrarre questo valore utilizzando l'operatore genere.

Una volta note le dimensioni di un'istanza di struttura, l'organizzazione dell'indicizzazione in un array di strutture non è particolarmente difficile.

Per esempio:

Come copiare un campo da una struttura al campo corrispondente di un'altra struttura? O come copiare l'intera struttura? Copiamo il campo nome terzo impiegato nel settore nome quinto dipendente:

mas_sotr lavoratore 10 dup()

mov bx,offset mas_sotr

mov si,(tipo lavoratore)*2 ;si=77*2

mov di,(tipo lavoratore)*4 ;si=77*4

Mi sembra che il mestiere di programmatore prima o poi faccia sembrare una persona una brava casalinga. Lui, come lei, è costantemente alla ricerca di dove salvare qualcosa, tagliare e fare una cena meravigliosa con un minimo di cibo. E se questo riesce, allora la soddisfazione morale non è minore, e forse maggiore, che da una splendida cena dalla massaia. Il grado di questa soddisfazione, mi sembra, dipende dal grado di amore per la propria professione.

D'altra parte, i progressi nello sviluppo di software e hardware rilassano in qualche modo il programmatore, e molto spesso c'è una situazione simile al noto proverbio sulla mosca e l'elefante: per risolvere qualche piccolo problema, sono necessari strumenti pesanti coinvolti, la cui efficacia, nel caso generale, è significativa solo quando si realizzano progetti relativamente grandi.

La presenza nel linguaggio delle seguenti due tipologie di dati è probabilmente dovuta al desiderio della “padrona di casa” di utilizzare l'area di lavoro del tavolo (RAM) nel modo più efficiente possibile durante la preparazione dei cibi o per la collocazione dei prodotti (dati del programma ).