LA CAMPANA

C'è chi ha letto questa notizia prima di te.
Iscriviti per ricevere gli ultimi articoli.
E-mail
Nome
Cognome
Come vuoi leggere La Campana?
Niente spam

La programmazione a livello di istruzione macchina è il livello minimo al quale è possibile programmare. Il sistema di istruzioni macchina deve essere sufficiente per eseguire le azioni richieste, impartendo istruzioni all'hardware del computer.

Ogni istruzione della macchina è composta da due parti:

  • sala operatoria - determinare "cosa fare";
  • operando - definizione di oggetti di elaborazione, "cosa fare con".

Un'istruzione macchina a microprocessore scritta in linguaggio assembly è una singola riga con la seguente forma sintattica:

comando / direttiva etichetta operando (s); commenti

In questo caso, il campo richiesto nella 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 sulla riga successiva, viene utilizzato il carattere barra rovesciata: \.

Per impostazione predefinita, il linguaggio assembly non distingue tra lettere maiuscole e minuscole durante la scrittura di comandi o direttive.

Esempi di righe di codice:

Conta db 1 ; Nome, direttiva, un operando
mov eax, 0 ; Comando, due operandi
cbw; Comando

tag

Etichetta in linguaggio assembly può contenere i seguenti caratteri:

  • tutte le lettere dell'alfabeto latino;
  • numeri da 0 a 9;
  • caratteri speciali: _, @, $,?.

Un punto può essere utilizzato come primo carattere di un'etichetta, ma alcuni compilatori sconsigliano l'uso di questo carattere. I nomi di assembler riservati (direttive, operatori, nomi di comandi) non possono essere utilizzati come etichette.

Il primo carattere nell'etichetta deve essere una lettera o un carattere speciale (ma non un numero). La lunghezza massima dell'etichetta è 31 caratteri. Tutte le etichette scritte in una riga che non contiene una direttiva assembler devono terminare con due punti:.

Comandi

Comando dice al traduttore quale azione dovrebbe intraprendere il microprocessore. In un segmento di dati, un comando (o una direttiva) definisce un campo, un'area di lavoro o una costante. Nel segmento di codice, l'istruzione definisce l'azione, come il trasferimento (mov) o l'aggiunta (add).

Direttive

L'assemblatore dispone di un numero di operatori che consentono di controllare il processo di assemblaggio e di generazione di un elenco. Questi operatori sono chiamati direttive ... Agiscono solo nel processo di assemblaggio del programma e, a differenza delle istruzioni, non generano codici macchina.

operandi

operando - un oggetto su cui viene eseguita un'istruzione macchina o un operatore di un linguaggio di programmazione.
Un'istruzione può avere uno o due operandi o nessun operando. Il numero di operandi è implicitamente specificato dal codice del comando.
Esempi:

  • Nessun operando ret; Return
  • Un operando inc ecx; Aumenta ecx
  • Due operandi aggiungono eax, 12; Aggiungi 12 a eax

Etichetta, comando (direttiva) e operando non devono iniziare in una posizione particolare nella stringa. Si consiglia comunque di scriverli in una colonna per una migliore leggibilità del programma.

Gli operandi possono essere

  • identificatori;
  • stringhe di caratteri racchiuse tra virgolette singole o doppie;
  • numeri interi in notazione binaria, ottale, decimale o esadecimale.
Identificatori

Identificatori - sequenze di caratteri validi utilizzati per designare oggetti del programma come codici operativi, nomi di variabili e nomi di etichette.

Regole per la scrittura degli identificatori.

  • L'identificatore può essere uno o più caratteri.
  • Le lettere dell'alfabeto latino, i numeri e alcuni caratteri speciali possono essere utilizzati come simboli: _,?, $, @.
  • L'identificatore non può iniziare con un carattere numerico.
  • L'identificatore può essere lungo fino a 255 caratteri.
  • Il traduttore accetta i primi 32 caratteri dell'identificatore e ignora il resto.
Commenti (1)

I commenti sono separati dalla riga eseguibile da a; ... In questo caso, tutto ciò che è scritto dopo il punto e virgola e fino alla fine della riga è un commento. L'uso dei commenti nel programma ne migliora la chiarezza, soprattutto quando lo scopo del set di istruzioni non è chiaro. Il commento può contenere qualsiasi carattere stampabile, compreso lo spazio. Un commento può occupare l'intera riga o seguire un comando sulla stessa riga.

Struttura del programma di montaggio

Un programma scritto in linguaggio assembly può essere composto da più parti, chiamate moduli ... Ciascun modulo può avere uno o più dati, stack e segmenti di codice definiti. Qualsiasi programma di assemblaggio completo deve includere un modulo principale, o principale, da cui iniziare la sua esecuzione. Un modulo può contenere segmenti di codice, segmenti di dati e segmenti di stack, dichiarati utilizzando le direttive appropriate. Prima di dichiarare i segmenti, è necessario specificare il modello di memoria utilizzando la direttiva .MODEL.

Un esempio di un programma di assemblaggio "non fare nulla":

686P
.MODELLO PIATTO, STDCALL
.DATI
.CODICE
COMINCIARE:

RET
FINE INIZIO

Questo programma contiene un solo comando del microprocessore. Questo comando è RET. Garantisce la corretta conclusione del programma. In generale, questo comando viene utilizzato per uscire da una procedura.
Il resto del programma è legato al lavoro del traduttore.
.686P - Comandi in modalità protetta Pentium 6 (Pentium II) consentiti. Questa direttiva seleziona il set di istruzioni assembler supportato specificando il modello del processore. La lettera P alla fine della direttiva informa il traduttore che il processore sta operando in modalità protetta.
.MODEL FLAT, stdcall è un modello di memoria flat. Questo modello di memoria viene utilizzato nel sistema operativo Windows. stdcall
.DATA - segmento di programma contenente dati.
.CODE - blocco del programma contenente il codice.
START è un'etichetta. Nel linguaggio assembly, le etichette svolgono un ruolo importante, il che non è il caso dei moderni linguaggi di alto livello.
END START - la fine del programma e un messaggio al traduttore che è necessario avviare l'esecuzione del programma dall'etichetta START.
Ogni modulo deve contenere una direttiva END per contrassegnare la fine codice sorgente programmi. Tutte le righe che seguono la direttiva END vengono ignorate. Se si omette la direttiva END, viene generato un errore.
L'etichetta specificata dopo la direttiva END comunica al traduttore il nome del modulo principale da cui inizia l'esecuzione del programma. Se il programma contiene un modulo, l'etichetta dopo la direttiva END può essere omessa.

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

Piano:

1 Linguaggio dell'Assemblea. Concetti basilari

2 Simboli del linguaggio assembly

3 Tipi di istruzioni assembler

4 Direttive dell'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 in linguaggio macchina (istruzioni). Quindi, è chiaro che, nonostante il nome generico, 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 serie di frasi linguistiche, ognuna delle quali occupa una riga separata di codice di programma.

Le frasi assembly sono di quattro tipi:

1) comandi o istruzioni, che sono analoghi simbolici delle istruzioni macchina. Nel processo di traduzione, le istruzioni assembler vengono convertite nei corrispondenti comandi del set di istruzioni del microprocessore;

2) macro -frasi del testo del programma che si formano in un certo modo, che vengono sostituite durante la trasmissione da altre frasi;

3) direttive,che sono istruzioni al traduttore assembler per eseguire alcune azioni. Le direttive non hanno analoghi nella rappresentazione delle macchine;

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

­ La struttura di un programma assembly. Sintassi dell'assieme.

Le frasi che compongono il programma possono essere un costrutto sintattico corrispondente a un comando, macro, direttiva o commento. Affinché il traduttore assembler li riconosca, devono essere formati secondo determinate regole sintattiche. Il modo migliore per farlo è usare una descrizione formale della sintassi del linguaggio come le regole grammaticali. I modi più comuni per descrivere un linguaggio di programmazione come questo - diagrammi di sintassi e forme estese di Backus-Naur. Più conveniente per l'uso pratico diagrammi di sintassi. Ad esempio, la sintassi delle frasi assembler può essere descritta utilizzando i diagrammi di sintassi mostrati nelle seguenti figure 10, 11, 12.

Figura 10 - Formato frase di montaggio


­ Figura 11 - Formato delle direttive

­ Figura 12 - Formato comandi e macro

In queste cifre:

­ nome dell'etichetta- un identificatore, il cui valore è l'indirizzo del primo byte della frase del testo sorgente del programma, che designa;

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

­ codice operativo (COP) e direttiva - sono designazioni mnemoniche della corrispondente istruzione macchina, macro o direttiva traduttore;

­ operandi -parti di un comando, macro o direttiva assembler che designano gli oggetti da manipolare. Gli operandi assembler sono descritti da espressioni con costanti numeriche e di testo, etichette e identificatori di variabili utilizzando segni di operazione e alcune parole riservate.

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

­ 2 simboli lingua assembly

I caratteri consentiti durante la scrittura del testo del programma sono:

1) tutte le lettere latine: A-Z,a-z... 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 validi della lingua che sono significativi per il traduttore.

lessemi sono:

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

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

3) numeri interi di uno dei seguenti sistemi di numerazione : binario, decimale, esadecimale. L'identificazione dei numeri durante la loro scrittura nei programmi in linguaggio assembly 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è necessario dopo aver annotato gli zeri e gli uno che li compongono, mettere il latino “ B”, Ad esempio 10010101 B.

5) i numeri esadecimali hanno più convenzioni quando vengono scritti:

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 può avere difficoltà a riconoscere i numeri esadecimali perché possono consistere solo di cifre 0 ... 9 (ad esempio 190845) o iniziare con una lettera dell'alfabeto latino (ad esempio, ef15). Per "spiegare" al traduttore che un dato token non è un numero decimale o un identificatore, il programmatore deve selezionare un numero esadecimale in un modo speciale. Per fare ciò, alla fine della sequenza di cifre esadecimali che compongono un numero esadecimale, scrivi la lettera latina “ h”. esso condizione richiesta... Se un numero esadecimale inizia con una lettera, davanti ad esso viene scritto 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) su cui agiscono istruzioni o direttive, oppure sono oggetti che definiscono o chiariscono l'azione di istruzioni o direttive.

È possibile effettuare la seguente classificazione degli operandi:

­ operandi costanti o immediati;

­ indirizzo operandi;

­ operandi mobili;

contatore di indirizzi;

­ registro operando;

­ operandi base e indice;

­ operandi strutturali;

record.

Gli operandi sono componenti elementari da cui è formata una parte di un'istruzione macchina, che denota gli oggetti su cui viene eseguita un'operazione. In un caso più generale, gli operandi possono essere inclusi come componenti in formazioni più complesse, chiamate espressioni.

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

­ 3 Tipi di istruzioni assembler

Elenchiamo le possibili tipologie operatori assembler e regole sintattiche per la formazione di espressioni assembler:

­ operatori aritmetici;

­ operatori di turno;

­ operatori di confronto;

­ operatori logici;

­ operatore indice;

­ operatore di override del tipo;

­ operatore di ridefinizione del segmento;

­ operatore di denominazione del tipo di struttura;

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

­ operatore per ottenere l'offset di un'espressione.

1 Direttive per gli assemblatori

­ Le direttive dell'assemblatore sono:

1) Direttive di segmentazione. Nel corso della discussione precedente, abbiamo scoperto tutte le regole di base per scrivere comandi e operandi in un programma assembler. Resta aperta la questione di come formulare correttamente la sequenza dei comandi in modo che il traduttore li possa elaborare e il microprocessore li possa eseguire.

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 istruzioni e (o) dati, i cui indirizzi sono calcolati rispetto al valore nel registro di segmento corrispondente. La descrizione sintattica di un segmento in assieme è la costruzione mostrata in Figura 13:


­ Figura 13 - Descrizione sintattica di un segmento in assembler

È importante notare che la funzionalità di un segmento è in qualche modo più ampia rispetto alla semplice suddivisione di un programma in blocchi di codice, dati e stack. La segmentazione fa parte di più meccanismo comune Associato a il concetto di programmazione modulare. Presuppone l'unificazione del design dei moduli oggetto creati dal compilatore, inclusi quelli di diversi linguaggi di programmazione. Ciò consente di combinare programmi scritti in lingue diverse. Gli operandi nella direttiva SEGMENT hanno lo scopo di implementare varie varianti di tale unione.

2) Direttive per la gestione delle quotazioni. Le direttive di controllo degli elenchi sono suddivise nei seguenti gruppi:

­ direttive generali per il controllo degli elenchi;

­ direttive per l'output nell'elenco dei file inclusi;

­ direttive per l'output di blocchi di assembly condizionali;

­ direttive per elencare le macro;

­ direttive per l'output delle informazioni sui riferimenti incrociati all'elenco;

­ direttive per modificare il formato dell'elenco.

2 Set di istruzioni del processore

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

Consideriamo i principali gruppi di squadre.

­ Figura 14 - Classificazione delle istruzioni dell'assemblatore

Le squadre sono:

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

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

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

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

Su alcuni processori, tutte queste funzioni vengono eseguite da un singolo comando. MOV (per i trasferimenti di byte - MOVB ) ma con diversi metodi di indirizzamento degli operandi.

Su altri processori oltre al comando MOV ci sono molti altri comandi per eseguire le funzioni elencate. Inoltre, i comandi di trasferimento dati includono comandi di scambio di informazioni (la loro designazione si basa sulla parola Scambio ). 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 operando come codici numerici binari o BCD. Questi comandi possono essere suddivisi in cinque gruppi principali:

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

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

­ comandi di pulizia;

­ comandi di incremento e decremento;

­ comando di confronto

3 I comandi di operazioni a punto fisso funzionano con codici nei registri del processore o in memoria come con i normali codici binari. Le istruzioni in virgola mobile (punto) utilizzano il formato di rappresentazione dei numeri con ordine e mantissa (di solito questi numeri occupano due locazioni di memoria consecutive). In moderno potenti processori l'insieme di istruzioni in virgola mobile non si limita alle sole quattro operazioni aritmetiche, ma contiene molti altri comandi più complessi, ad esempio il calcolo di funzioni trigonometriche, funzioni logaritmiche e funzioni complesse necessarie per l'elaborazione di suoni e immagini.

4 Le istruzioni di cancellazione sono progettate per scrivere un codice zero in un registro o in una cella di memoria. Questi comandi possono essere sovrascritti con comandi di trasferimento zero, ma squadre speciali le pulizie sono in genere più veloci dell'inoltro dei comandi.

5 Comandi per incremento (aumento di uno) e decremento

(decrementi di uno) sono anche molto convenienti. In linea di principio possono essere sostituiti dall'addizione con uno o sottrae uno, ma incremento e decremento sono più veloci dell'addizione e della sottrazione. Queste istruzioni richiedono un operando di ingresso, che è anche un operando di uscita.

6 L'istruzione di confronto confronta due operandi di ingresso. Infatti, calcola la differenza tra questi due operandi, ma non forma un operando di uscita, ma cambia solo i bit nel registro di stato del processore in base al risultato di questa sottrazione. L'istruzione successiva che segue l'istruzione di confronto (di solito 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 collegamento a margherita di due sequenze di operandi in memoria.

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

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

­ spostamenti logici, aritmetici e ciclici;

­ controllo di bit e operandi;

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

Le istruzioni logiche consentono di calcolare le funzioni logiche di base da due operandi di ingresso bit per bit. Inoltre, l'operazione AND viene utilizzata per cancellare forzatamente i bit specificati (un codice maschera viene utilizzato come uno degli operandi, in cui i bit da cancellare sono impostati a zero). L'operazione OR viene utilizzata per impostare forzatamente i bit specificati (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 "OR esclusivo" viene utilizzata per invertire i bit specificati (come uno degli operandi viene utilizzato un codice maschera, in cui i bit da invertire sono impostati su uno). Le istruzioni richiedono due operandi di ingresso e formano un operando di uscita.

8 I comandi di spostamento consentono di spostare bit per bit il codice dell'operando a destra (verso i bit di ordine inferiore) oa sinistra (verso i bit di ordine superiore). Il tipo di spostamento (logico, aritmetico o ciclico) determina quale sarà il nuovo valore del bit più significativo (in caso di spostamento a destra) o meno significativo (in caso di spostamento a sinistra) e determina anche se il valore precedente del bit più significativo (quando si sposta a sinistra) verrà salvato da qualche parte o il bit meno significativo (quando si sposta a destra). Gli spostamenti ciclici consentono di spostare i bit di un operando in modo circolare (in senso orario se spostati a destra o in senso antiorario se spostati a sinistra). In questo caso, la bandierina di trasporto può essere inclusa o meno nell'anello del cambio. Il bit del flag di riporto (se utilizzato) memorizza il valore del bit più significativo quando ciclato a sinistra e il bit meno significativo quando ciclato a destra. Di conseguenza, il valore del bit di flag di riporto verrà sovrascritto nel bit meno significativo quando si cicla a sinistra e nel bit più significativo quando ci si sposta a destra.

9 Comandi di transizioni. Le istruzioni di salto sono progettate per organizzare tutti i tipi di loop, rami, chiamate di subroutine, ecc., ovvero interrompono il flusso sequenziale del programma. Questi comandi scrivono un nuovo valore nel registro del contatore dei comandi e quindi fanno sì che il processore passi non al comando successivo nell'ordine, ma a qualsiasi altro comando nella memoria del programma. Alcuni comandi di transizione forniscono un ulteriore ritorno al punto da cui è stata effettuata la transizione, altri non lo prevedono. Se viene fornito il ritorno, i parametri correnti del processore vengono salvati nello stack. Se non viene fornito alcun ritorno, i parametri del processore correnti non vengono salvati.

I comandi di transizione senza backtracking sono divisi in due gruppi:

­ comandi di salto incondizionato;

­ comandi di salto condizionato.

Questi comandi usano le parole Ramo e salto.

Le istruzioni di salto incondizionato causano un salto a nuovo indirizzo non importa cosa. Possono causare una transizione a il valore specificato offset (avanti o indietro) o all'indirizzo di memoria specificato. Il valore di offset o il nuovo valore di indirizzo viene specificato come operando di ingresso.

Le istruzioni di salto condizionale non provocano sempre un salto, ma solo quando vengono soddisfatte le condizioni specificate. Queste 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. Possono esserci in totale da 4 a 16 di tali condizioni di salto Diversi esempi di comandi di salto condizionato:

­ transizione se uguale a zero;

­ transizione se non uguale a zero;

­ saltare se c'è troppo pieno;

­ saltare se non c'è troppo pieno;

­ transizione se maggiore di zero;

­ salta se minore o uguale a zero.

Se la condizione di transizione è soddisfatta, il nuovo valore viene caricato nel registro dei comandi. Se la condizione di salto non è soddisfatta, il contatore delle istruzioni viene semplicemente incrementato e il processore seleziona ed esegue l'istruzione successiva nell'ordine.

Il comando di confronto (CMP) che precede il comando di salto condizionato (o anche più comandi di salto condizionato) viene utilizzato in modo specifico per verificare le condizioni di salto. Ma i flag possono essere impostati da qualsiasi altro comando, ad esempio un comando di trasferimento dati, qualsiasi comando aritmetico o logico. Nota che gli stessi comandi di salto non cambiano i flag, il che ti consente solo di inserire diversi comandi di salto uno dopo l'altro.

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

Produzione:

Il linguaggio assembly è una rappresentazione simbolica di un 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 serie di frasi linguistiche, ognuna delle quali occupa una riga separata di codice di programma. Le frasi assembly sono di quattro tipi: comandi o istruzioni, macro, direttive, righe di commento.

Tutte le lettere latine sono caratteri validi durante la scrittura del testo del programma: A-Z,a-z... In questo caso le lettere maiuscole e minuscole sono considerate equivalenti; cifre da 0 prima 9 ; segni ? , @ , $ , _ , & ; separatori , . () < > { } + / * % ! " " ? = # ^ .

Si applicano i seguenti tipi di istruzioni assembler e regole sintattiche per la formazione di espressioni assembler. operatori aritmetici, operatori di spostamento, operatori di confronto, operatori logici, operatore indice, operatore di sostituzione del tipo, operatore di sostituzione del segmento, operatore di denominazione del tipo di struttura, operatore per ottenere il componente del segmento dell'indirizzo di un'espressione, operatore per ottenere l'offset di un'espressione.

Il sistema di comando è diviso in 8 gruppi principali.

­ Domande di controllo:

1 Che cos'è il linguaggio assembly?

2 Quali simboli possono essere utilizzati per scrivere comandi in linguaggio assembly?

3 Cosa sono le etichette e il loro scopo?

4 Spiegare la struttura dei comandi assembler.

5 Elenca 4 tipi di frasi assembler.

1. Architettura del PC ………………………………………………………… 5

    1.1. Registri.

    1.1.1 Registri scopo generale.

1.1.2. Registri di segmento

1.1.3 Registro flag

1.2. Organizzazione della memoria.

1.3. Presentazione dei dati.

1.3.1 Tipi di dati

1.3.2 Rappresentazione di caratteri e stringhe

2. Operatori del programma assembler ……………………………………

    1. Comandi in linguaggio assembly

2.2. Modalità di indirizzamento e formati di istruzioni della macchina

3. Pseudo-operatori ……………………………………………………….

3.1 Direttive sulla definizione dei dati

3.2 Struttura di un programma in linguaggio assembly

3.2.1 Segmenti di programma. Assumi direttiva

3.2.3 Direttiva sulla segmentazione semplificata

4. Assemblaggio e collegamento del programma ………………………….

5. Comandi per l'invio dei dati …………………………………………….

    5.1 Comandi Generali

    5.2 Comandi per lavorare con lo stack

5.3 Comandi I/O

5.4 Comandi di inoltro dell'indirizzo

5.5 Comandi per l'inoltro dei flag

6. Comandi aritmetici ……………………………………………….

    6.1 Operazioni aritmetiche su interi binari

6.1.1 Addizione e sottrazione

6.1.2 Comandi per incrementare e decrementare il ricevitore di uno

6.2 Moltiplicazione e divisione

6.3 Cambio di segno

7. Operazioni logiche ………………………………………………….

8. Turni e turni ciclici …………………………………………

9. Operazioni sulle stringhe ………………………………………………….

10. Logica e organizzazione dei programmi ………………………………………

10.1 Salti incondizionati

10.2 Salti condizionati

10.4 Routine in linguaggio assembly

10.5 Interrupt INT

10.6 Software di sistema

10.6.1.1 Lettura della tastiera.

10.6.1.2 Visualizzazione dei caratteri sullo schermo

10.6.1.3 Fine programmi.

10.6.2.1 Selezione delle modalità di visualizzazione

11. Memoria su disco ……………………………………………………… ..

11.2 Tabella di assegnazione dei file

11.3 I/O del disco

11.3.1 Scrivere un file su disco

11.3.1.1 Dati in formato ASCIIZ

11.3.1.2 Numero file

11.3.1.3 Crea file su disco

11.3.2 Lettura di un file su disco

introduzione

Il linguaggio assembly è una rappresentazione simbolica di un linguaggio macchina. Tutti i processi in un personal computer (PC) al livello hardware più basso sono guidati solo da comandi in linguaggio macchina (istruzioni). È impossibile risolvere veramente i problemi relativi all'hardware (o anche problemi dipendenti dall'hardware come il miglioramento delle prestazioni del programma) senza conoscere l'assemblatore.

Assembler è una comoda forma di comandi direttamente per i componenti del PC e richiede la conoscenza delle proprietà e delle capacità del circuito integrato che contiene questi componenti, ovvero il microprocessore del PC. Pertanto, il linguaggio assembly è direttamente correlato all'organizzazione interna del PC. E non è un caso che quasi tutti i compilatori di linguaggio di alto livello supportino l'accesso al livello di programmazione in linguaggio assembly.

Un elemento della formazione di un programmatore professionista è necessariamente lo studio dell'assemblatore. Questo perché la programmazione in linguaggio assembly richiede la conoscenza dell'architettura del PC, che consente di creare programmi più efficienti in altri linguaggi e di combinarli con programmi in linguaggio assembly.

Il manuale affronta le problematiche della programmazione in linguaggio assembly per computer basati su microprocessori di Intel.

Questo tutorial è rivolto a chiunque sia interessato all'architettura del processore e alle basi della programmazione in linguaggio assembly, principalmente agli sviluppatori di software.

    Architettura del PC.

L'architettura del computer è una rappresentazione astratta di un computer, che riflette la sua organizzazione strutturale, circuitale e logica.

Tutti i computer moderni hanno alcune proprietà architettoniche comuni e individuali. Le proprietà individuali sono inerenti solo a un modello di computer specifico.

Il concetto di architettura del computer include:

    schema a blocchi del computer;

    mezzi e modalità di accesso agli elementi diagramma strutturale COMPUTER;

    set e disponibilità dei registri;

    organizzazione e modalità di indirizzamento;

    modalità di presentazione e formato dei dati informatici;

    set di istruzioni per computer;

    formati di istruzioni macchina;

    gestione delle interruzioni.

Gli elementi principali dell'hardware del computer: l'unità di sistema, la tastiera, i dispositivi di visualizzazione, le unità disco, i dispositivi di stampa (stampante) e varie strutture di comunicazione. Unità di sistemaè costituito da una scheda madre, alimentatore e slot di espansione per schede aggiuntive. La scheda di sistema contiene un microprocessore, memoria di sola lettura (ROM), RAM(RAM) e coprocessore.

      Registri.

All'interno del microprocessore, le informazioni sono contenute in un gruppo di 32 registri (16 registri utente, 16 registri di sistema), in una certa misura disponibili per l'uso da parte del programmatore. Poiché il tutorial è dedicato alla programmazione per il microprocessore 8088-i486, è più logico iniziare questo argomento discutendo i registri interni del microprocessore a disposizione dell'utente.

I registri utente sono utilizzati dal programmatore per scrivere programmi. Questi registri includono:

    otto registri a 32 bit (registri generici) EAX / AX / AH / AL, EBX / BX / BH / BL, ECX / CX / CH / CL, EDX / DX / DLH / DL, EBP / BP, ESI / SI, EDI/DI, ESP/SP;

    sei registri di segmento a 16 bit: CS, DS, SS, ES, FS, GS;

    registri di stato e di controllo: registro flag EFLAGS/FLAGS e registro puntatore istruzione EIP/IP.

La barra segna le parti di un singolo registro a 32 bit. Il prefisso E (esteso) indica l'uso di un registro a 32 bit. Per lavorare con i byte, vengono utilizzati registri con i prefissi L (basso) e H (alto), ad esempio AL, CH - che denotano i byte bassi e alti delle parti a 16 bit dei registri.

        Registri di uso generale.

EAX / AX / AH / AL (Registro dell'accumulatore) - batteria... Utilizzato nelle moltiplicazioni e divisioni, nelle operazioni di I/O e in alcune operazioni sulle stringhe.

EBX / BX / BH / BL - registro di base(registro di base), spesso utilizzato per indirizzare i dati in memoria.

ECX / CX / CH / CL - contatore(registro di conteggio), utilizzato come contatore del numero di ripetizioni del loop.

EDX / DX / DH / DL - registro dati(registro dati), utilizzato per memorizzare i dati intermedi. È obbligatorio in alcuni comandi.

Tutti i registri di questo gruppo consentono l'accesso alle loro parti "inferiori". Solo le parti inferiori a 16 e 8 bit di questi registri possono essere utilizzate per l'autoindirizzamento. I 16 bit superiori di questi registri non sono disponibili come oggetti indipendenti.

Per supportare i comandi di elaborazione di riga che consentono l'elaborazione sequenziale di catene di elementi con una lunghezza di 32, 16 o 8 bit, vengono utilizzati i seguenti:

ESI/SI (registro indice sorgente) - indice fonte... Contiene l'indirizzo dell'elemento di origine corrente.

EDI/DI (registro indice di destinazione) - indice ricevitore(destinatario). Contiene l'indirizzo corrente nella stringa del destinatario.

Nell'architettura del microprocessore, una struttura dati - uno stack - è supportata a livello hardware-software. Ci sono comandi speciali e registri speciali per lavorare con lo stack. Va notato che lo stack è riempito verso indirizzi più piccoli.

ESP / SP (registro puntatore stack) - Registrati puntatore pila... Contiene il puntatore alla parte superiore dello stack nel segmento dello stack corrente.

EBP / BP (registro del puntatore di base) - registro puntatore base stack... Progettato per organizzare l'accesso casuale ai dati all'interno dello stack.

1.1.2. Registri di segmento

Nel modello software del microprocessore, ci sono sei registri di segmento: CS, SS, DS, ES, GS, FS. La loro esistenza è dovuta alle specificità dell'organizzazione e dell'uso della RAM da parte dei microprocessori Intel. L'hardware del microprocessore supporta l'organizzazione strutturale del programma composto da segmenti. Per indicare i segmenti disponibili in questo momento si intendono i registri di segmento. Il microprocessore supporta i seguenti tipi di segmento:

    Segmento di codice. Contiene i comandi del programma. Per accedere a questo segmento, utilizzare il registro CS (registro del segmento di codice) - registro codice segmento... Contiene l'indirizzo del segmento di istruzione macchina a cui ha accesso il microprocessore.

    Segmento di dati. Contiene i dati elaborati dal programma. Per accedere a questo segmento, utilizzare il registro DS (registro del segmento di dati) - registro dati di segmento che memorizza l'indirizzo del segmento dati del programma corrente.

    Segmento di pila. Questo segmento rappresenta un'area di memoria chiamata stack. Il microprocessore organizza lo stack secondo il principio: first "in", first "out". Il registro SS (stack segment register) viene utilizzato per accedere allo stack - registro del segmento dello stack contenente l'indirizzo del segmento dello stack.

    Segmento di dati aggiuntivo. I dati elaborati possono trovarsi in tre segmenti di dati aggiuntivi. Per impostazione predefinita, si presume che i dati si trovino nel segmento di dati. Quando si utilizzano segmenti di dati aggiuntivi, i loro indirizzi devono essere specificati in modo esplicito utilizzando prefissi di override di segmento speciali nel comando. Gli indirizzi dei segmenti di dati aggiuntivi devono essere contenuti nei registri ES, GS, FS (registri di segmenti di dati di estensione).

        Registri di controllo e di stato

Il microprocessore contiene diversi registri che contengono informazioni sullo stato sia del microprocessore stesso che del programma i cui comandi sono attualmente caricati nella pipeline. Esso:

Registro puntatore comando EIP/IP;

    registra i flag EFLAGS / FLAGS.

Utilizzando questi registri, è possibile ottenere informazioni sui risultati dell'esecuzione del comando e influenzare lo stato del microprocessore stesso.

EIP / IP (registro del punto di istruzione) - puntatore squadre... Il registro EIP/IP è largo 32 o 16 bit e contiene l'offset dell'istruzione successiva da eseguire rispetto al contenuto del registro del segmento CS nel segmento dell'istruzione corrente. Questo registro non è direttamente accessibile, ma può essere modificato tramite comandi di salto.

EFLAGS / BANDIERE (Registro delle bandiere) - Registrati bandiere... Profondità bit 32/16 bit. I singoli bit di questo registro hanno uno scopo funzionale specifico e sono chiamati flag. Un flag è un bit che assume un valore 1 ("flag è impostato") se viene soddisfatta una determinata condizione e un valore 0 ("flag è cancellato") altrimenti. La parte inferiore di questo registro è completamente analoga al registro FLAGS per i8086.

1.1.3 Registro flag

Il registro dei flag è a 32 bit e ha il nome EFLAGS (Figura 1). I singoli bit del registro hanno uno scopo funzionale specifico e sono chiamati flag. Ad ognuno di essi viene assegnato un nome specifico (ZF, CF, ecc.). I 16 bit inferiori di EFLAGS rappresentano il registro flag FLAGS a 16 bit utilizzato durante l'esecuzione di programmi scritti per i microprocessori i086 e i286.

Fig. 1 Registro delle bandiere

Alcuni flag sono comunemente indicati come flag di condizione; cambiano automaticamente quando vengono eseguiti i comandi e fissano alcune proprietà del loro risultato (ad esempio, se è uguale a zero). Altre bandiere sono chiamate bandiere di stato; cambiano dal programma e influenzano l'ulteriore comportamento del processore (ad esempio, gli interrupt di blocco).

Flag di condizione:

CF (porta bandiera) - portare bandiera... Assume il valore 1 se, sommando numeri interi, appare un'unità di sillabazione che non "entra" nella griglia di bit, oppure se, sottraendo numeri senza segno, il primo di essi è inferiore al secondo. Nei comandi shift, in CF viene impostato un bit che è andato oltre la griglia dei bit. CF acquisisce anche le caratteristiche del comando di moltiplicazione.

OF (bandiera di overflow) - bandiera di overflow... È impostato a 1 se, sommando o sottraendo numeri interi con segno, il risultato è un risultato maggiore in valore assoluto del valore ammissibile (la mantissa è traboccata ed è "arrampicata" nel bit di segno).

ZF (bandiera zero) - bandiera zero... È impostato su 1 se il risultato del comando era uguale a 0.

SF (segnaletica) - bandiera cartello... È impostato a 1 se l'operazione sui numeri con segno ha esito negativo.

PF (flag di parità) - bandiera parità... Uguale a 1 se il risultato del comando successivo contiene un numero pari di binari. Di solito viene considerato solo per operazioni di I/O.

AF (bandiera ausiliaria) - bandiera di trasporto extra... Corregge le peculiarità dell'esecuzione di operazioni su numeri binari-decimali.

Flag di stato:

DF (bandiera di direzione) - bandiera di direzione... Imposta la direzione di visualizzazione delle righe nei comandi stringa: con DF = 0, le righe vengono scansionate "in avanti" (dall'inizio alla fine), con DF = 1 - nella direzione opposta.

IOPL (livello di privilegio di input/output) - Livello di privilegio I/O. Viene utilizzato nella modalità protetta del microprocessore per controllare l'accesso ai comandi di I/O, a seconda del privilegio del compito.

NT (attività nidificata) - flag di nidificazione delle attività. Viene utilizzato nella modalità protetta del microprocessore per registrare il fatto che un'attività è annidata all'interno di un'altra.

Contrassegno di sistema:

IF (flag di interruzione) - bandiera di interruzione... Se IF = 0, il processore smette di rispondere agli interrupt in arrivo; se IF = 1, il blocco dell'interrupt viene rilasciato.

TF (bandiera trappola) - traccia bandiera... Se TF = 1, dopo l'esecuzione di ogni istruzione, il processore effettua un interrupt (con numero 1), che può essere utilizzato durante il debug del programma per rintracciarlo.

RF (segnale di ripresa) - riprendere la bandiera... Utilizzato quando si gestiscono gli interrupt dai registri di debug.

VM (modalità virtuale 8086) - bandiera 8086 virtuale. 1-processore funziona in modalità virtuale 8086. 0-processore funziona in modalità reale o protetta.

AC (verifica allineamento) - bandiera di controllo dell'allineamento. Progettato per consentire il controllo dell'allineamento quando si accede alla memoria.

      Organizzazione della memoria.

Viene chiamata la memoria fisica a cui il microprocessore ha accesso RAM ( o memoria ad accesso casuale - RAM). La RAM è una catena di byte che hanno un proprio indirizzo univoco (il suo numero), chiamato fisico. L'intervallo di valori per gli indirizzi fisici va da 0 a 4 GB. Il meccanismo di gestione della memoria è completamente basato sull'hardware.

L'hardware del microprocessore supporta diversi modelli di utilizzo della RAM:

    modello segmentato... In questo modello, la memoria per i programmi è suddivisa in aree di memoria contigue (segmenti) e il programma stesso può accedere solo ai dati che si trovano in questi segmenti;

    modello di pagina... In questo caso, la RAM è considerata come un insieme di blocchi di dimensione fissa di 4 KB. L'applicazione principale di questo modello è associata all'organizzazione della memoria virtuale, che consente ai programmi di utilizzare uno spazio di memoria più grande del volume memoria fisica... Per un microprocessore Pentium, la possibile memoria virtuale può arrivare fino a 4 TB.

L'uso e l'implementazione di questi modelli dipende dalla modalità di funzionamento del microprocessore:

    Modalità indirizzo reale (modalità reale). La modalità è simile al funzionamento del processore i8086. È necessario per il funzionamento dei programmi sviluppati per i primi modelli di processore.

    Modalità protetta. In modalità protetta, diventa possibile multitasking elaborazione delle informazioni, protezione della memoria con un meccanismo di privilegio a quattro livelli e relativo paging.

    Modalità 8086 virtuale. In questa modalità, diventa possibile eseguire diversi programmi per i8086. In questo caso, è possibile il funzionamento di programmi in modalità reale.

La segmentazione è un meccanismo di indirizzamento che consente l'esistenza di più spazi di indirizzi indipendenti. Un segmento è un blocco di memoria indipendente e supportato dall'hardware.

Ogni programma nel caso generale può essere costituito da un numero qualsiasi di segmenti, ma ha accesso diretto a tre principali: codice, dati e stack - e da uno a tre segmenti di dati aggiuntivi. Sistema operativo posiziona i segmenti di programma nella RAM a specifici indirizzi fisici, quindi inserisce i valori di questi indirizzi nei registri corrispondenti. All'interno di un segmento, il programma accede agli indirizzi relativi all'inizio del segmento in modo lineare, cioè partendo dall'indirizzo 0 e terminando con un indirizzo pari alla dimensione del segmento. Indirizzo relativo o pregiudizio, che il microprocessore utilizza per accedere ai dati all'interno di un segmento si chiama efficace.

Formazione di un indirizzo fisico in modalità reale

In modalità reale, l'intervallo di modifica dell'indirizzo fisico è compreso tra 0 e 1 MB. La dimensione massima del segmento è 64 KB. Quando si fa riferimento a uno specifico indirizzo fisico La RAM è determinata dall'indirizzo dell'inizio del segmento e dall'offset all'interno del segmento. L'indirizzo di inizio del segmento è preso dal registro di segmento corrispondente. In questo caso, il registro di segmento contiene solo i 16 bit superiori dell'indirizzo fisico dell'inizio del segmento. I quattro bit inferiori mancanti di un indirizzo a 20 bit si ottengono spostando il valore del registro di segmento a sinistra di 4 bit. L'operazione di spostamento viene eseguita nell'hardware. Il valore a 20 bit risultante è l'indirizzo fisico reale corrispondente all'inizio del segmento. Questo è indirizzo fisicoè specificato come una coppia: segmento: offset, dove segmento sono i primi 16 bit dell'indirizzo iniziale del segmento di memoria a cui appartiene la cella, e offset è l'indirizzo a 16 bit di questa cella, conteggiato dall'inizio di questa memoria segmento (valore 16 * segmento + offset fornisce l'indirizzo assoluto della cella). Se, ad esempio, il registro CS memorizza il valore 1234h, allora la coppia di indirizzi 1234h: 507h definisce un indirizzo assoluto pari a 16 * 1234h + 507h = 12340h + 507h = 12847h. Tale coppia è scritta sotto forma di una doppia parola e (come per i numeri) in una forma "invertita": la prima parola contiene un offset e la seconda - un segmento, e ciascuna di queste parole a sua volta è presentata in una forma "invertita". Ad esempio, la coppia 1234h: 5678h sarà scritta così: | 78 | 56 | 34 | 12 |.

Questo meccanismo per la formazione di un indirizzo fisico consente di rendere il software rilocabile, cioè non dipende dagli indirizzi specifici del suo caricamento in RAM.

Strutture assemblatrici

Gli array che abbiamo considerato sopra sono una raccolta di elementi dello stesso tipo. Ma spesso nelle applicazioni diventa necessario considerare un certo insieme di dati. tipi diversi come un tipo unico.

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

Ad esempio, abbiamo esaminato il Listato 4 in precedenza, in cui abbiamo lavorato con un array di elementi a tre byte. Ciascun elemento, a sua volta, rappresentava due elementi di tipo diverso: un campo contatore di un byte e un campo di due byte che poteva contenere altre informazioni 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.

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

A-priorità struttura è un tipo di dati costituito da un numero fisso di elementi di tipo diverso.

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

    Chiedere modello di struttura .

    Per definizione, ciò significa definire un nuovo tipo di dati, che può essere successivamente utilizzato per definire variabili di questo tipo.

    Definire istanza di struttura .

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

    Organizzare accesso agli elementi della struttura .

È molto importante che tu capisca la differenza tra descrizione struttura nel programma e la sua definendo.

Descrivere la struttura nel programma significa solo indicare il suo schema o modello; nessuna memoria è allocata.

Questo modello può essere considerato solo come informazione per il traduttore sulla posizione dei campi e sui loro valori predefiniti.

Definire struttura significa indicare al traduttore di allocare memoria e assegnare un nome simbolico a quest'area di memoria.

È possibile descrivere la struttura in un programma solo una volta, ma è possibile definirla un numero qualsiasi di volte.

Descrizione del modello di struttura

La descrizione del modello di struttura ha la seguente sintassi:

nome_struttura STRUC

struct_name FINISCE

Qui è una sequenza di direttive che descrivono i dati db, dw, dd, dq e dt.

I loro operandi determinano la dimensione dei campi e, se necessario, i valori iniziali. Questi valori verranno probabilmente inizializzati nei campi corrispondenti durante la definizione della struttura.

Come abbiamo notato durante la descrizione del modello, non viene allocata memoria, poiché si tratta solo di informazioni per il traduttore.

Posizione Il template nel programma può essere arbitrario, ma, seguendo la logica del traduttore one-pass, deve trovarsi fino al 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.

Consideriamo di lavorare con strutture sull'esempio della modellazione di un database di dipendenti di un determinato dipartimento.

Per semplicità, al fine di evitare i problemi di conversione delle informazioni durante l'immissione, converremo che tutti i campi sono simbolici.

Definiamo la struttura record di questo database con il seguente template:

Definire i dati con un tipo di struttura

Per utilizzare la struttura descritta utilizzando il modello nel programma, è necessario definire una variabile con il tipo di questa struttura. Per questo, viene utilizzata la seguente sintassi:

[nome variabile] nome_struttura

    nome variabile- identificatore di una variabile di questo tipo strutturale.

    Il nome della variabile è facoltativo. Se non lo specifichi, verrà semplicemente allocata un'area di memoria della dimensione della somma delle lunghezze di tutti gli elementi della struttura.

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

    Anche il suo incarico è facoltativo.

    Se l'elenco è incompleto, tutti i campi della struttura per questa variabile 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 di struttura. Se, quando definiamo una nuova variabile con il tipo di questa struttura, siamo d'accordo con tutti i valori del campo nel suo modello (cioè, impostato per impostazione predefinita), allora devi solo scrivere parentesi angolari.

    Per esempio: vincitore lavoratore.

Ad esempio, definiamo più variabili con il tipo della struttura sopra descritta.

Metodi per lavorare con la struttura

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

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

    espressione_indirizzo- l'identificativo di una variabile di qualche tipo strutturale o di un'espressione tra parentesi secondo le regole sintattiche sotto indicate (Fig. 1);

    nome_campo_struttura- il 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. La sintassi di un'espressione di indirizzo in un operatore di accesso al campo della struttura

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

Ad esempio, estrai in ascia i valori del 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, poiché a causa del principio di archiviazione dei dati "Byte meno significativo indirizzo almeno significativo" la cifra dell'età più alta sarà inserita in al, e il più giovane - in ah.

Per regolare basta usare il comando xchg al, ah:

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

oppure puoi fare così:

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

Che dire delle dimensioni e di come organizzare l'indicizzazione degli elementi dell'array?

Analogamente ad altri identificatori definiti nel programma, il traduttore assegna il nome del tipo di struttura e il nome della variabile del tipo di struttura all'attributo type. Il valore di questo attributo è la dimensione in byte occupata dai campi di questa struttura. Puoi recuperare questo valore usando l'operatore genere.

Dopo che la dimensione di un'istanza di struttura è diventata nota, non è difficile organizzare l'indicizzazione in una matrice di strutture.

Per esempio:

Come faccio a copiare un campo da una struttura al campo corrispondente di un'altra struttura? O come si copia 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 prodotti. E se questo ha successo, allora la soddisfazione morale si ottiene non meno, e forse di più, che da una meravigliosa cena con una casalinga. Il grado di questa soddisfazione, mi sembra, dipende dal grado di amore per la tua professione.

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

La presenza dei seguenti due tipi di dati nel linguaggio è probabilmente spiegata dal desiderio della "padrona di casa" di utilizzare l'area di lavoro del tavolo (RAM) nel modo più efficiente possibile durante la preparazione del cibo o per l'immissione dei prodotti (dati del programma ).

Struttura delle istruzioni in linguaggio assembly La programmazione a livello di istruzione macchina è il livello minimo al quale è possibile la programmazione del computer. Il set di istruzioni della macchina deve essere sufficiente per eseguire le azioni richieste impartendo istruzioni all'hardware della macchina. Ogni istruzione macchina è composta da due parti: una operativa che definisce "cosa fare" e un operando che definisce gli oggetti di elaborazione, ovvero cosa fare. Un'istruzione macchina a microprocessore scritta in linguaggio assembly è una singola riga della forma seguente: etichetta istruzione / operando/i direttivo/i; commenti L'etichetta, il comando/la direttiva e l'operando sono separati da almeno uno spazio o un carattere di tabulazione. Gli operandi dei comandi sono separati da virgole.

Struttura dell'istruzione in linguaggio assembly Un'istruzione in linguaggio assembly indica al traduttore quale azione deve intraprendere il microprocessore. Le direttive assembler sono parametri specificati nel testo del programma che influiscono sul processo di assemblaggio o sulle proprietà del file di output. L'operando specifica il valore dei dati iniziali (nel segmento di dati) o gli elementi su cui agire con il comando (nel segmento di codice). Un'istruzione può avere uno o due operandi o nessun operando. Il numero di operandi è implicitamente specificato dal codice del comando. Se è necessario continuare un comando o una direttiva sulla riga successiva, viene utilizzato il carattere barra rovesciata: "". Per impostazione predefinita, l'Assembler non distingue tra lettere maiuscole e minuscole nella scrittura di comandi e direttive. Esempi di direttiva e comando Conteggio db 1; Nome, direttiva, un operando mov eax, 0; Comando, due operandi

Gli identificatori sono sequenze di caratteri validi utilizzati per indicare nomi di variabili e nomi di etichette. L'identificatore può essere costituito da uno o più dei seguenti caratteri: tutte le lettere dell'alfabeto latino; numeri da 0 a 9; caratteri speciali: _, @, $,? ... Un punto può essere utilizzato come primo carattere dell'etichetta. I nomi di assembler riservati (direttive, operatori, nomi di comandi) non possono essere utilizzati come identificatori. Il primo carattere dell'identificatore deve essere una lettera o un carattere speciale. La lunghezza massima dell'identificatore è di 255 caratteri, ma il traduttore accetta i primi 32, ignora il resto. Tutte le etichette scritte in una riga che non contiene una direttiva assembler devono terminare con i due punti ":". Etichetta, comando (direttiva) e operando non devono iniziare in una posizione particolare nella stringa. Si consiglia di annotarli in una colonna per una migliore leggibilità del programma.

Etichette Tutte le etichette scritte in una riga che non contiene una direttiva assembler devono terminare con i due punti ":". Etichetta, comando (direttiva) e operando non devono iniziare in una posizione particolare nella stringa. Si consiglia di annotarli in una colonna per una migliore leggibilità del programma.

Commenti L'utilizzo dei commenti in un programma migliora la chiarezza, soprattutto quando l'intento del set di istruzioni non è chiaro. I commenti iniziano su qualsiasi riga del modulo sorgente con un punto e virgola (;). Tutti i caratteri a destra di “; »Alla fine della riga c'è un commento. Il commento può contenere qualsiasi carattere stampabile, compreso lo spazio. Un commento può occupare l'intera riga o seguire un comando sulla stessa riga.

La struttura di un programma in linguaggio assembly Un programma scritto in linguaggio assembly può essere costituito da più parti, chiamate moduli, in ciascuna delle quali è possibile definire uno o più dati, stack e segmenti di codice. Qualsiasi programma completo in linguaggio assembly deve includere un modulo principale, o principale, da cui inizia la sua esecuzione. Un modulo può contenere segmenti di programma, segmenti di dati e uno stack, dichiarato utilizzando le direttive appropriate.

Modelli di memoria Prima di dichiarare i segmenti, è necessario specificare il modello di memoria utilizzando una direttiva. MODEL modificatore memory_model, call_convention, OS_type, stack_parameter Modelli di memoria di base del linguaggio assembly: Modello di memoria Indirizzamento del codice Indirizzamento dei dati Sistema operativo Interlacciamento del codice e dei dati TINY NEAR MS-DOS Consentito SMALL NEAR MS-DOS, Windows No MEDIUM FAR NEAR MS-DOS, Windows No COMPACT NEAR FAR MS-DOS, Windows No LARGE FAR MS-DOS, Windows No ENORME LONTANO MS-DOS, Windows No NEAR Windows 2000, Windows XP, Windows Consentito FLAT NEAR NT,

Modelli di memoria Il modello minuscolo funziona solo nelle applicazioni MS-DOS a 16 bit. In questo modello, tutti i dati e il codice si trovano in un segmento fisico. La dimensione file di programma in questo caso non supera i 64 KB. Il modello piccolo supporta un segmento di codice e un segmento di dati. I dati e il codice vengono indirizzati il ​​più vicino possibile quando si utilizza questo modello. Il modello medio supporta più segmenti di codice e un segmento di dati, con tutti i collegamenti nei segmenti di codice considerati lontani per impostazione predefinita e i collegamenti in un segmento di dati come vicini. Il modello compatto supporta più segmenti di dati utilizzando l'indirizzamento dei dati lontani e un segmento di dati vicino. Il modello grande supporta più segmenti di codice e più segmenti di dati. Per impostazione predefinita, tutti i riferimenti al codice e ai dati sono considerati lontani. Il modello enorme è quasi equivalente al modello con memoria grande.

Modelli di memoria Il modello piatto presuppone una configurazione del programma non segmentata e viene utilizzato solo su sistemi operativi a 32 bit. Questo modello è simile al modello minuscolo in quanto i dati e il codice sono contenuti in un singolo segmento a 32 bit. Sviluppare un programma per il modello piatto prima della direttiva. modello piatto una delle direttive dovrebbe essere collocata:. 386,. 486,. 586 o. 686. La scelta della direttiva di selezione del processore determina l'insieme di istruzioni disponibili durante la scrittura dei programmi. La lettera p dopo la direttiva di selezione del processore indica una modalità di funzionamento protetta. L'indirizzamento di dati e codice è vicino, con tutti gli indirizzi e i puntatori a 32 bit.

Modelli di memoria. MODEL modificatore memory_model, call_convention, OS_type, stack_parameter Il parametro modificatore viene utilizzato per definire i tipi di segmenti e può assumere i seguenti valori: use 16 (i segmenti del modello selezionato sono usati come 16 bit) use 32 (segmenti del modello selezionato sono usati come 32 bit). Il parametro call_convention viene utilizzato per determinare come vengono passati i parametri quando si chiama una procedura da altri linguaggi, inclusi i linguaggi di alto livello (C++, Pascal). Il parametro può assumere i seguenti valori: C, BASIC, FORTRAN, PASCAL, SYSCALL, STDCALL.

Modelli di memoria. Modificatore MODEL memory_model, call_ convention, os_type, stack_parameter OS_type è l'OS_DOS predefinito ed è attualmente l'unico valore supportato per questo parametro. Stack_parameter è impostato su: NEARSTACK (il registro SS è DS, i dati e le aree dello stack si trovano nello stesso segmento fisico) FARSTACK (il registro SS non è uguale a DS, i dati e le aree dello stack si trovano in segmenti fisici diversi). L'impostazione predefinita è NEARSTACK.

Un esempio di un programma "non fare nulla". 686 P. MODELLO PIATTO, STDCALL. DATI. CODICE START: RET END START RET - comando a microprocessore. Garantisce la corretta conclusione del programma. Il resto del programma è legato al lavoro del traduttore. ... 686 P - Comandi in modalità protetta Pentium 6 (Pentium II) consentiti. Questa direttiva seleziona il set di istruzioni assembler supportato specificando il modello del processore. ... MODEL FLAT, stdcall è un modello di memoria flat. Questo modello di memoria viene utilizzato nel sistema operativo Windows. stdcall è la convenzione di chiamata della procedura utilizzata.

Un esempio di un programma "non fare nulla". 686 P. MODELLO PIATTO, STDCALL. DATI. CODICE INIZIO: RET FINE START. DATA è un segmento di programma contenente dati. Questo programma non usa lo stack, quindi segment. STACK è mancante. ... CODE è un segmento del programma che contiene il codice. START è un'etichetta. END START - la fine del programma e un messaggio al compilatore che il programma deve essere avviato dall'etichetta START. Ogni programma deve contenere una direttiva END per contrassegnare la fine del codice sorgente del programma. Tutte le righe che seguono la direttiva END vengono ignorate L'etichetta specificata dopo la direttiva END comunica al traduttore il nome del modulo principale da cui parte il programma. Se il programma contiene un modulo, l'etichetta dopo la direttiva END può essere omessa.

Traduttori di lingua assembly Un traduttore è un programma o mezzi tecnici che converte un programma in uno dei linguaggi di programmazione in un programma nel linguaggio di destinazione chiamato codice oggetto. Oltre a supportare i mnemonici delle istruzioni macchina, ogni traduttore ha il proprio insieme di direttive e macro-strumenti, che spesso sono incompatibili con qualsiasi cosa. I principali tipi di traduttori di linguaggio assembly: MASM (Microsoft Assembler), TASM (Borland Turbo Assembler), FASM (Flat Assembler) - un assemblatore multi-pass gratuito scritto da Tomasz Grishtar (polacco), NASM (Netwide Assembler) - un assemblatore gratuito per Architettura Intel x 86, è stato creato da Simon Tatham in collaborazione con Julian Hall ed è attualmente sviluppato da un piccolo team di sviluppo su Source. Fucina. netto.

Src = "https://present5.com/presentation/-29367016_63610977/image-15.jpg" alt = "(! LANG: Microsoft Broadcast Visual Studio 2005 1) Creare un progetto selezionando File-> Nuovo-> Progetto e "> Traduzione del programma in Microsoft Visual Studio 2005 1) Creare un progetto selezionando File-> Nuovo-> Progetto e specificando il nome del progetto (hello.prj) e il tipo progetto: Win 32 Project. opzioni aggiuntive della procedura guidata del progetto specificare "Progetto vuoto".

Src = "https://present5.com/presentation/-29367016_63610977/image-16.jpg" alt = "(! LANG: trasmissione del programma a Microsoft Visual Studio 2005 2) Nella struttura del progetto (Visualizza-> Esplora soluzioni) Inserisci"> Трансляция программы в Microsoft Visual Studio 2005 2) В дереве проекта (View->Solution Explorer) добавить файл, в котором будет содержаться текст программы: Source. Files->Add->New. Item.!}

Traduzione del programma in Microsoft Visual Studio 2005 3) Selezionare il tipo di file Code C++, ma specificare il nome con l'estensione. asm:

Traduzione del programma in Microsoft Visual Studio 2005 5) Impostare le opzioni del compilatore. Seleziona per bottone giusto nel file di progetto del menu Regole di compilazione personalizzate ...

Traduzione del programma in Microsoft Visual Studio 2005 e selezionare Microsoft Macro Assembler nella finestra che appare.

Traduzione del programma in Microsoft Visual Studio 2005 Verifica facendo clic con il pulsante destro del mouse su Hello. asm della struttura del progetto del menu Proprietà e impostare Generale-> Strumento: Microsoft Macro Assembler.

Src = "https://present5.com/presentation/-29367016_63610977/image-22.jpg" alt = "(! LANG: trasmissione del programma a Microsoft Visual Studio 2005 6) Compila il file scegliendo Build-> Build hello. Prj."> Трансляция программы в Microsoft Visual Studio 2005 6) Откомпилировать файл, выбрав Build->Build hello. prj. 7) Запустить программу, нажав F 5 или выбрав меню Debug->Start Debugging.!}

Programmazione in SO Windows La programmazione in SO Windows si basa sull'utilizzo di funzioni API (Application Program Interface, ad es. applicazione software). Il loro numero raggiunge il 2000. Il programma per Windows consiste in gran parte di tali chiamate. Tutte le interazioni con dispositivi esterni e risorse del sistema operativo avvengono, di regola, attraverso tali funzioni. Sala operatoria Sistema Windows utilizza un modello di memoria piatta. L'indirizzo di qualsiasi locazione di memoria sarà determinato dal contenuto di un registro a 32 bit. Esistono 3 tipi di strutture di programma per Windows: finestra di dialogo (finestra principale - finestra di dialogo), struttura console o senza finestre, struttura classica (finestra, wireframe).

Chiamata Funzioni di Windows API Nel file della guida, qualsiasi funzione API è rappresentata come tipo nome_funzione (FA 1, FA 2, FA 3) Tipo - il tipo del valore restituito; ФАх - un elenco di argomenti formali nell'ordine in cui vengono visualizzati, ad esempio int Message. Casella (HWND h. Wnd, LPCTSTR lp. Text, LPCTSTR lp. Caption, UINT u. Type); Questa funzione visualizza una finestra con un messaggio e un pulsante (o pulsanti) di uscita. Significato dei parametri: h. Wnd - handle alla finestra in cui apparirà la finestra del messaggio, lp. Testo - il testo che apparirà nella finestra, lp. Didascalia - il testo nella didascalia della finestra, u. Tipo - il tipo della finestra, in particolare, è possibile definire il numero di pulsanti di uscita.

Chiamare le funzioni API di Windows int Message. Casella (HWND h. Wnd, LPCTSTR lp. Text, LPCTSTR lp. Caption, UINT u. Type); Quasi tutti i parametri delle funzioni API sono in realtà numeri interi a 32 bit: HWND è un numero intero a 32 bit, LPCTSTR è un puntatore a 32 bit a una stringa, UINT è un numero intero a 32 bit. Il suffisso "A" viene spesso aggiunto al nome della funzione per passare a versioni più recenti delle funzioni.

Chiamare le funzioni API di Windows int Message. Casella (HWND h. Wnd, LPCTSTR lp. Text, LPCTSTR lp. Caption, UINT u. Type); Quando si utilizza MASM, è necessario aggiungere @N N alla fine del nome, il numero di byte che gli argomenti passati occupano nello stack. Per le funzioni API Win 32, questo numero può essere definito come il numero di argomenti n per 4 (byte in ogni argomento): N = 4 * n. Il comando CALL assembler viene utilizzato per chiamare la funzione. In questo caso, tutti gli argomenti della funzione vengono passati ad essa tramite lo stack (comando PUSH). La direzione del passaggio degli argomenti: DA SINISTRA A DESTRA - BASSO SU. Il primo argomento da inserire nello stack è u. Tipo. Chiamata la funzione specificata sarà simile a questo: CALL Message. Scatola. [e-mail protetta]

Chiamare le funzioni API di Windows int Message. Casella (HWND h. Wnd, LPCTSTR lp. Text, LPCTSTR lp. Caption, UINT u. Type); Il risultato dell'esecuzione di qualsiasi funzione API è, di regola, un numero intero che viene restituito nel registro EAX. La direttiva OFFSET è un "segmento offset" o, in termini di alto livello, un "puntatore" all'inizio di una riga. La direttiva EQU, come #define nel linguaggio C, definisce una costante. La direttiva EXTERN dice al traduttore che la funzione o l'identificatore è esterno al modulo dato.

Un esempio del programma "Ciao a tutti!" ... 686 P. MODELLO PIATTO, STDCALL. STACK 4096. DATA MB_OK EQU 0 STR 1 DB "Il mio primo programma", 0 STR 2 DB "Ciao a tutti", 0 HW DD? Messaggio ESTERNO. Scatola. [e-mail protetta]: VICINO. CODICE START: PUSH MB_OK PUSH OFFSET STR 1 PUSH OFFSET STR 2 PUSH HW CALL Messaggio. Scatola. [e-mail protetta] RIT FINE AVVIO

La direttiva INVOKE Il traduttore di lingua MASM consente anche di semplificare la chiamata di funzioni utilizzando lo strumento macro - la direttiva INVOKE: funzione INVOKE, parametro1, parametro2, ... In questo caso, non è necessario aggiungere @ 16 alla chiamata di funzione; i parametri sono scritti esattamente nell'ordine in cui sono indicati nella descrizione della funzione. i parametri vengono inseriti nello stack tramite il traduttore. per utilizzare la direttiva INVOKE, è necessario disporre di una descrizione del prototipo della funzione utilizzando la direttiva PROTO nella forma: Messaggio. Scatola. A PROTO: DWORD,: DWORD Se il programma utilizza molte funzioni API Win 32, è consigliabile utilizzare la direttiva include C: masm 32includeuser 32. inc

LA CAMPANA

C'è chi ha letto questa notizia prima di te.
Iscriviti per ricevere gli ultimi articoli.
E-mail
Nome
Cognome
Come vuoi leggere La Campana?
Niente spam