Programare în coduri mașină și limbaj de asamblare. Directivele de bază pentru asamblare

Determinați dispozitivul pentru care este compilat

Parametrii trecuți directivei sunt o secvență de expresii separate prin virgule. Fiecare expresie trebuie să fie fie un număr din intervalul (-128..255), fie

rezultatul calculului trebuie să dea un rezultat în același interval, în caz contrar numărul se trunchiază la un octet, și FĂRĂ să emită avertismente.

Dacă o directivă primește mai mult de un parametru și segmentul de program curent este, atunci parametrii sunt împachetati în cuvinte (primul parametru este octetul mic) și dacă

numărul de parametri este impar, apoi ultima expresie va fi trunchiată la un octet și scrisă ca un cuvânt cu octetul cel mai semnificativ egal cu zero, chiar dacă urmează altul

Directiva DB.

Sintaxă:
LABEL: .DB expression_list

Exemplu:
.CSEG
const: .DB 0, 255, 0b01010101, -128, 0xaa

Parametrii trecuți directivei sunt o secvență de expresii separate prin virgule. Fiecare expresie trebuie să fie fie un număr din intervalul (-32768..65535), fie

ca urmare a calculului, acesta trebuie sa dea un rezultat in acelasi interval, in caz contrar numarul este trunchiat la un cuvant, si FARA a da avertismente.

Sintaxă:
LABEL: .DW expressionlist

Exemplu:
.CSEG
varlist: .DW 0, 0xffff, 0b1001110001010101, -32768, 65535

Sintaxă:
.ENDMACRO

Exemplu:
.MACRO SUBI16 ; Începerea unei definiții macro
subi r16,low(@0) ; Scădeți octetul mic al primului parametru
sbci r17,high(@0) ; Scădeți octetul înalt al primului parametru
.ENDMACRO

EQU – Setează expresia constantă

Directiva EQU atribuie o valoare unei etichete. Această etichetă poate fi folosită ulterior în expresii. O etichetă a cărei valoare este atribuită de această directivă nu poate fi

este reatribuit și valoarea sa nu poate fi modificată.

Sintaxă:
.EQU label = expresie

Exemplu:
.EQU io_offset = 0x23
.EQU porta = io_offset + 2

CSEG; Începutul segmentului de date
clr r2 ; Ștergeți registrul r2
out porta,r2 ; Scrieți în portul A

ESEG – segment EEPROM

Directiva ESEG definește începutul segmentului EEPROM. Dosarul original poate consta din mai multe segmente EEPROM, care sunt combinate într-un singur segment în timpul compilării.

Un segment EEPROM constă de obicei numai din directive,

href="#DW - Definiți cuvânt(e) constant(e) în memoria programului și EEPROM">DW

și semne. Segmentele EEPROM au propriile lor

contoare de poziție de octeți. Directiva poate fi folosită pentru a plasa

variabile în locul necesar în EEPROM. Directiva nu are parametri.

Sintaxă:
.ESEG

Exemplu:
var1: .BYTE 1 ; rezerva 1 octet pentru var1
tabel: .BYTE tab_size ; rezerva tab_size octeți.

ESEG
eevar1: .DW 0xffff ; inițializați 1 cuvânt în EEPROM

EXIT – Ieșiți din fișier

Când compilatorul întâlnește o directivă EXIT, se oprește compilarea. a acestui dosar. Dacă directiva este utilizată într-un fișier atașat (vezi directiva

href="#INCLUDE - Include alt fișier">INCLUDE

), apoi compilarea continuă de la linia care urmează directivei INCLUDE.

Dacă fișierul nu este imbricat, atunci compilarea se oprește.

Sintaxă:
.IEȘIRE

Exemplu:
.IEȘIRE ; Ieșiți din acest fișier

INCLUDE – Atașați un alt fișier

După ce a întâlnit o directivă INCLUDE, compilatorul deschide fișierul specificat în ea, îl compilează până când fișierul se termină sau este întâlnită directiva

href="#EXIT - Ieșiți din acest fișier">EXIT

, apoi continuă compilarea fișierului inițial din linia care urmează directivei

INCLUDE. Fișierul atașat poate conține și directive INCLUDE.

Sintaxă:
.INCLUDE „nume fișier”

Exemplu:
; fișier iodefs.asm:
.EQU sreg = 0x3f ; Registrul de stare
.EQU sphigh = 0x3e ; Indicator de stivă octet înalt
.EQU splow = 0x3d ; Octet scăzut al indicatorului stivei

; fișierul incdemo.asm
.INCLUSE iodefs.asm ; Definițiile portului de cuib
în r0,sreg ; Citiți registrul de stare

LIST – Activați generarea listelor

Directiva LIST îi spune compilatorului să creeze o listă. Lista este o combinație de cod de asamblare, adrese și coduri operaționale. De

În mod implicit, generarea de liste este activată, dar această directivă este utilizată împreună cu directiva pentru a obține liste ale părților individuale ale fișierelor sursă.

Sintaxă:
.LISTĂ

Exemplu:

LISTMAC – Activați extinderea macrocomenzilor în listare

După directiva LISTMAC, compilatorul va afișa conținutul macrocomenzii în listă. În mod implicit, lista arată doar apelul macro și cel transmis

Opțiuni.

Sintaxă:
.LISTMAC

Exemplu:
.MACRO MACX ; Definiție macro
adăugați r0,@0 ; Corpul macro
eor r1,@1

LISTMAC; Activați extinderea macrocomenzii
MACX r2,r1; Apelarea unei macrocomenzi (corpul macrocomenzii va fi afișat în listă)

MACRO – Începutul unei macrocomenzi

Definiția unei macrocomenzi începe cu directiva MACRO. Numele macro-ului este transmis directivei ca parametru. Dacă întâlniți un nume de macrocomandă mai târziu în textul programului,

compilatorul înlocuiește acest nume cu corpul macrocomenzii. O macrocomandă poate avea până la 10 parametri, care sunt accesați prin @0-@9 în corpul său. Când sunt apelați, parametrii sunt listați

separate prin virgule. Definiția macro se termină cu o directivă.

În mod implicit, numai apelul macro este inclus în listare pentru a extinde macro, trebuie să utilizați directiva; Macrocomanda din listă este afișată cu semnul +.

Sintaxă:
.MACRO nume de macrocomandă

Exemplu:
.MACRO SUBI16 ; Începutul definiției macro
subi @1,low(@0) ; Scădeți octetul mic al parametrului 0 din parametrul 1
sbci @2,high(@0) ; Scădeți octetul mare al parametrului 0 din parametrul 2
.ENDMACRO ; Sfârșitul definiției macro

CSEG; Începutul segmentului de program
SUBI16 0x1234,r16,r17 ; Scădeți 0x1234 din r17:r16

NOLIST – Dezactivează generarea listelor

Directiva NOLIST îi spune compilatorului să nu mai genereze liste. Lista este o combinație de cod de asamblare, adrese și

coduri de operare. În mod implicit, generarea listelor este activată, dar poate fi dezactivată de această directivă. În plus, această directivă poate fi utilizată

împreună cu o directivă de obținere a listelor pieselor individuale

fișiere sursă

Sintaxă:
.NOLIST

Exemplu:
.NOLIST ; Dezactivați generarea înregistrării
.INCLUDE „macro.inc” ; Fișierele atașate nu vor fi
.INCLUSE "const.def" ; afișat în listare
.LISTA ; Activați generarea înregistrării

ORG – Setați poziția în segment

Directiva ORG setează contorul de poziție la o valoare dată, care este transmisă ca parametru. Pentru segmentul de date, setează contorul de poziție la

SRAM (RAM), pentru un segment de program acesta este contorul de program, iar pentru un segment EEPROM aceasta este poziția în EEPROM. Dacă directiva este precedată de o etichetă (pe aceeași linie), atunci

Eticheta este plasată la adresa specificată în parametrul directivei. Înainte de a începe compilarea, contorul de program și contorul EEPROM sunt egale cu zero, iar contorul RAM este egal cu 32

(deoarece adresele 0-31 sunt ocupate de registre). Vă rugăm să rețineți că contoarele de octeți sunt folosite pentru RAM și EEPROM, iar contoarele de cuvinte sunt folosite pentru segmentul de program.

Sintaxă:
.ORG expresie

Exemplu:
.DSEG; Începutul segmentului de date

ORG 0x37 ; Setați adresa SRAM la 0x37
variabilă: .BYTE 1 ; Rezervați un octet la adresa 0x37H

CSEG
.ORG 0x10 ; Setați contorul de programe la 0x10
mov r0,r1 ; Această comandă va fi localizat la adresa 0x10

SET – Setează echivalentul simbolic variabil al unei expresii

Directiva SET atribuie o valoare unui nume. Acest nume poate fi folosit ulterior în expresii. În plus, spre deosebire de directivă

href="#EQU - Setați un simbol egal cu o expresie">EQU

valoarea numelui poate fi modificată printr-o altă directivă SET.

Sintaxă:
.SET nume = expresie

Exemplu:
.SET io_offset = 0x23
.SET porta = io_offset + 2

CSEG; Începutul segmentului de cod
clr r2 ; Ștergeți registrul 2

La scrierea programelor în limbaj Asamblare se folosesc directive care indică compilatorului locația programului în memorie, definesc macro-uri, inițializează memoria etc. Lista directivelor și descrierile acestora sunt date în Tabel. 1.8. Toate directivele încep cu un punct. Să enumerăm pe scurt funcțiile îndeplinite de directive în fiecare segment.

Un segment de program se deschide cu directiva .CSEG. Dacă programul începe cu acest segment, directiva poate lipsi. Într-un segment de program, puteți utiliza directiva .ORG pentru a indica începutul segmentului.

Directiva .DB într-un segment definește un octet sau un grup de octeți de constante scrise în memoria Flash. Directiva .DW definește un cuvânt sau un grup de cuvinte care sunt scrise în memorie ca constante. Începutul constantelor de înregistrare este determinat de eticheta care precede directiva corespunzătoare. Constantele enumerate sunt separate prin virgule.

Directiva .DEF atribuie un nume simbolic registrului. Directivele .EQU, .SET atribuie o valoare numelui. Un nume căruia i se atribuie o valoare de către directiva .EQU nu poate fi reatribuit, iar valoarea nu poate fi modificată. Un nume atribuit de o directivă .SET poate fi schimbat de o altă directivă .SET.

Directiva .DEVICE specifică tipul de microcontroler țintă care va fi folosit pentru a executa programul. Prezența acestei directive permite controale pentru instrucțiunile programului în legătură cu dispozitiv fizic, atenționând cu privire la imposibilitatea executării anumitor instrucțiuni, dimensiunea memoriei utilizate etc.

Directiva .INCLUDE cu un nume de fișier este folosită pentru a include un alt fișier în textul programului.

Tabelul 1.8. Lista directivelor

Directivă

Descriere

Rezervați octeți în RAM

Segment de program

Definiți un octet - o constantă în memoria Flash sau

Atribuiți un nume simbolic unui registru

Specifică dispozitivul pentru care este compilat

program

Segment de date

Definește un cuvânt în memoria Flash sau EEPROM

Sfârșitul macro-ului

Setați expresia constantă

Segmentul EEPROM

Ieșiți din fișier

Atașați un alt fișier

Activați generarea înregistrării

Activați extinderea macrocomenzii în înregistrare

Începutul macro

Dezactivați generarea înregistrării

Setați poziția în segment

Setați o variabilă la o expresie echivalentă

Directivele .MACRO și .ENDMACRO încadrează definiția macro. O definiție macro poate avea până la 10 parametri cu nume fixe @0,…,@9. La apelarea unei definiții macro, parametrii sunt specificați ca o listă în ordine numerică.

Segmentul de date începe cu directiva .DSEG. Directivele .ORG și .BYTE pot fi utilizate într-un segment. Directiva.BYTE specifică numărul de octeți care vor fi accesați în timpul execuției programului. Zona rezervată începe la adresa specificată de etichetă înainte de directivă.

Segmentul de tip EEPROM începe cu directiva .ESEG. Directivele .ORG, .DB, .DW pot fi utilizate într-un segment. Directiva .DB într-un segment specifică unul sau un grup de octeți care urmează să fie scrisi în EEPROM. Directiva.DW definește un cuvânt sau un grup de cuvinte scrise în memoria EEPROM în perechi de 2 octeți. Începutul înregistrării octeților și cuvintelor este determinat de eticheta care precede directiva corespunzătoare.

Directivele .LIST, .NOLIST, .LISTMAC sunt folosite pentru a controla rezultatul unei liste.

Limbajul de programare în limbajul de asamblare include întotdeauna coduri de mașină ale microcontrolerului, dar acest lucru nu se limitează la setul de comenzi ale acestui limbaj. Ideea este că trebuie să fiți capabil să gestionați procesul de difuzare a programului în sine. O listă completă de directive este dată în descrierea limbii, iar unele dintre ele vor fi discutate în detaliu aici.

Primul lucru care este incomod atunci când utilizați numai instrucțiuni ale mașinii este necesitatea de a reține ce date se află în ce celulă de memorie. Când citiți un program, este dificil să distingem constantele de variabile, deoarece acestea diferă în comenzi doar prin tipul de adresare. Această dificultate poate fi depășită folosind identificatori. Puteți atribui un identificator oricărei celule de memorie și, prin urmare, puteți lucra cu acest identificator ca variabilă.

directiva equ vă permite să atribuiți nume variabilelor și constantelor. Acum puteți atribui o adresă unei variabile într-un singur loc și puteți utiliza identificatorul de variabilă în tot programul. Adevărat, programatorul este responsabil pentru utilizarea identificatorului ca variabilă, cu toate acestea, dacă în procesul de scriere a unui program este necesar să se schimbe adresa unei variabile, acest lucru se poate face într-un singur loc în program, mai degrabă decât să treacă prin întregul program, dând seama dacă numărul 10 este o constantă în această comandă specială, adresa celulei sau numărul de repetări din ciclu. Toate modificările necesare vor fi făcute chiar de traducător. Un exemplu de atribuire a variabilelor este dat în exemplul prezentat în Lista 1.


Listarea 1. Atribuirea variabilelor folosind directiva equ

După cum se poate observa în exemplul de mai sus, utilizarea identificatorilor crește semnificativ înțelegerea programului, deoarece numele variabilei afișează funcția pentru care această variabilă este responsabilă.

Folosind directiva equ, puteți aloca nu numai variabile, ci și constante. După cum am menționat mai devreme, dacă identificatorul va fi folosit ca variabilă sau ca constantă depinde de comenzile și tipurile de adrese pe care le folosește programatorul.

Odată ce un identificator este atribuit, acesta nu poate fi schimbat în viitor, iar dacă încercați să atribuiți din nou exact același nume de identificator, va fi afișat un mesaj de eroare.

setare directivă. Dacă este necesar în diverse locuri programele atribuie numere diferite aceluiași identificator, atunci trebuie să utilizați directiva set. Utilizarea acestei directive este complet identică cu cea a directivei equ, deci nu va fi ilustrată cu un exemplu.

Constantele atribuite de directiva equ pot fi folosite doar într-o singură comandă. Destul de des este necesar să lucrați cu un tabel de constante, cum ar fi un tabel de conversie, tabele functii elementare sau sindroame de cod rezistent la zgomot. Astfel de constante nu sunt utilizate în etapa de translație, ci sunt stocate în memoria programului microcontrolerului. Pentru a introduce constante în memoria programului microcontrolerului, se folosesc directivele db și dw.

directiva db folosit pentru a stoca constante de un singur octet în memoria programului. Un exemplu de utilizare a directivei db este prezentat în Lista 2.


Lista 2. Atribuirea constantelor folosind directiva db

Acest exemplu folosește o subrutină de funcție care convertește un număr zecimal binar într-un cod cu șapte segmente. La această funcție cod zecimal binar este transmis prin acumulator și prin același registru codul de șapte segmente este returnat programului apelant.

În directiva db, puteți specifica mai multe constante simultan, separate prin virgulă. Le puteți folosi pe toate în același timp, dar de obicei are sens să furnizați fiecărei constante un comentariu, așa cum sa făcut în exemplul anterior. În acest fel programul devine mai ușor de înțeles și este mai ușor de găsit greșeala.

Aceeași directivă facilitează notarea inscripțiilor care ulterior vor trebui afișate pe afișajul încorporat sau pe ecranul de afișare computer universal, conectat la dispozitivul în curs de dezvoltare printr-o interfață. Un exemplu de utilizare a directivei db pentru a introduce inscripții în memoria programului microcontrolerului este prezentat în Figura 3.

Figura 3. Utilizarea directivei db pentru a scrie inscripții în memoria programului microcontrolerului.

directiva dw vă permite să stocați numere de doi octeți în memoria programului. În această directivă, ca și în directiva db, numerele pot fi introduse separate prin virgule. Un exemplu de listare a unui fragment de program este prezentat în Figura 4.

Figura 4. Aplicarea directivei dw.

Figura 4 prezintă un fragment din lista de programe, astfel încât să puteți urmări ce octeți sunt introduși în memoria programului microcontrolerului. Coloana din dreapta listei conține adresele în care vor fi introduse numerele care sunt operanzii directivei dw. Coloana următoare arată numere de doi octeți care vor fi stocate în memoria programului microcontrolerului. Vă rugăm să rețineți că, deși primii doi operanzi constau dintr-o singură cifră, patru sunt stocați în memoria microcontrolerului cifre hexazecimale(număr de doi octeți).

La traducerea textului sursă al programelor, se presupune că prima instrucțiune se află la adresa zero. Adresa comenzilor ulterioare depinde de lungime și număr echipele anterioare. Un exemplu de listare a secțiunii inițiale a programului este prezentat în Figura 5.

Figura 5. Exemplu de listare de programe.

Uneori trebuie să localizați o comandă la o anumită adresă. Acest lucru este necesar cel mai adesea atunci când se utilizează întreruperi, când prima instrucțiune a programului de gestionare a întreruperilor trebuie să fie localizată exact pe vectorul de întrerupere. Acest lucru se poate face folosind comanda nop pentru a umple golurile dintre vectorii de întrerupere, dar este mai bine să folosiți directiva ORG.

directiva org este destinat să scrie valoarea operandului său în contorul de adrese de segment. Adică, folosind această directivă, puteți plasa o comandă (sau date) în memoria microcontrolerului la orice adresă. Un exemplu de utilizare a directivei ORG pentru a plasa rutine de întrerupere pe vectori de întrerupere este prezentat în Figura 6.

Figura 6. Exemplu de utilizare a directivei ORG.

De remarcat că atunci când se utilizează această directivă, este posibilă o situație în care programatorul ordonă traducătorului să plaseze cod nou program într-un loc deja scris, astfel încât utilizarea acestei directive este permisă numai în cazuri extreme. De obicei, aceasta este utilizarea vectorilor de întrerupere.

directiva de utilizare Când se utilizează întreruperi, timpul ocupat de gestionarea întreruperilor programului este critic. Acest timp poate fi redus semnificativ prin alocarea unei bănci separate de registre pentru procesarea întreruperii. Puteți selecta o bancă separată de registre utilizând directiva USING. Numărul de bancă al registrelor utilizate este indicat în directivă ca operand. Un exemplu de utilizare a directivei USING pentru rutina pentru întreruperile de service de la temporizatorul 0 este prezentat în Figura 7.

Figura 7. Exemplu de utilizare a directivei USING.

Directiva CALL. Sistemul de comandă al microcontrolerului MCS-51 utilizează trei comenzi de sărituri necondiționate. Alegerea unei anumite instrucțiuni depinde de locația acesteia în memoria programului, dar programatorul nu știe de obicei acest lucru. Ca rezultat, pentru a evita erorile, trebuie să utilizați cea mai lungă comandă LJMP. Acest lucru are ca rezultat programe mai lungi și încărcare suplimentară a editorului de linkuri. Traducatorul poate alege cea mai buna varianta comenzi de sărituri necondiționate. Pentru a face acest lucru, în loc de o comandă de microcontroler, ar trebui să utilizați directiva de apel.

Directivele rămase sunt menite să controleze segmente și, prin urmare, vor fi discutate mai târziu atunci când discutăm despre lucrul cu programe cu mai multe module.

Literatură:

Împreună cu articolul „Directive privind limbajul de programare ASM-51” se citește:


http://site/Progr/progr.php

Să ne amintim că directivele (pseudo-operatorii) sunt instrucțiuni pentru asamblator, acestea sunt procesate numai atunci când programul este asamblat (tradus). Iată câteva dintre directivele utilizate în mod obișnuit.

Directive privind definirea identificatorului

Atribuiți identificatorului cu numele dat un text sau o valoare numerică (expresie). Formatul directivei:

nume EQU text

nume = valoare numerică (expresie)

Diferența dintre pseudo-operatorii EQU și =:

l EQU - atribuie o valoare permanent (nu poate fi schimbat), textul poate fi o expresie simbolică, numerică sau mixtă definind o constantă, adresă, alt nume simbolic, etichetă etc.;

l = - realizează atribuirea curentă (valoarea poate fi reatribuită, dar numai în timpul traducerii, desigur); atribuie numai expresie numerică, care conțin transformări matematice simple care vor fi efectuate în timpul translației (de exemplu: const + 1, 15H*4, 3*12/4 etc.).

Directive privind definirea datelor

Folosit pentru a identifica variabile și câmpuri de memorie. Formatul directivei

[nume] D* expresie [,expresie] [,...].

Cuvintele cheie D* ar putea fi:

l DB - definește octet (1 octet);

l DW - definiți un cuvânt (2 octeți);

l DD - definiți un cuvânt dublu (4 octeți);

l DQ - definiți 8 octeți;

l DT - definiți 10 octeți.

Directivele în cauză declară o variabilă (nume) sau atribuie valori inițiale câmpurilor (celulelor) de memorie; rezervă în memorie (cu atribuire ulterioară a valorii) unul sau mai mulți octeți - DB, cuvinte - DW, cuvinte duble- DD etc.

Expresia arată câte elemente de memorie trebuie alocate și ce date ar trebui să fie conținute acolo. Expresia ar putea fi:

l constanta:
const DB 56; const DW 1936; const DD 3FFH.
Asigurați-vă că luați în considerare intervalul și capacitatea unui octet, cuvânt etc.; deci, pentru DB constanta nu poate fi mai mare de 255, pentru DW - 65.535, pentru DD -



l 65 535 2 – 1 = 4 294 967 295;

l vector sau tabel:
tabel1 DB 30, 4, –15, 0, 0, 0, 56; tabelul 2 DW 1936, 3004, 56, 15.
Într-un pseudo-operator puteți plasa un șir de până la 132 de poziții și, în loc să repetați aceeași valoare de mai multe ori (0 în tabelul 1), puteți utiliza pseudo-operatorul DUP (duplicat):
tabel1 DB 30, 4, –15, 3 dup(0), 56);

l un șir de caractere:
str1 DB „Ați introdus prea multe număr mare";
str2 DB „Comandă proastă”;
în pseudo-operatorul DB linia poate conține 255 de caractere, în toate celelalte (DW, DD, DQ, DT) - doar 2 caractere.

l câmp gol:
pol 1 DB ?; pole2 DW 12 dup(?),
în același timp, nu se scrie nimic în elementele de memorie rezervate când programul este încărcat (nu se scrie 0, ca, de exemplu, în directiva pole3 DW 5 dup(0), ci celulele de memorie sunt pur și simplu rezervate);

l nume variabilă simbolică:
var1 DW disp; var2 DD vector
(o variabilă este definită de adresa alteia; nu este nevoie să specificați offset în directive, deoarece numele variabilei este perceput ca adresa sa). Această opțiune este potrivită, de exemplu, pentru stocarea adreselor celulelor de memorie, a etichetelor care pot fi referite într-un program (var1 DW disp), iar dacă variabila se află în același segment cu comanda de referință, atunci este suficient să specificați doar offset-ul ca adresa (2 octeți), adică vă puteți descurca cu DW; dacă variabila se află într-un alt segment, atunci trebuie să specificați atât segmentul, cât și offset-ul (4 octeți în total), adică ar trebui să utilizați DD (var2 DD vector);

l cu o expresie simplă:
fn1 DB 80*3; fn2 DW (disp) + 256, calculat, desigur, numai atunci când programul este tradus.

Directive pentru definirea segmentelor și procedurilor

Un segment este definit de pseudo-operatori:

segment_name segment

segname se termină

Într-un program, puteți utiliza 4 segmente (în funcție de numărul de registre de segmente) și pentru fiecare, specificați registrul de segment corespunzător folosind pseudo-operatorul ASSUME (asumați - atribuiți), de exemplu:

presupune CS:codeseg, DS:dataseg, SS:stackseg

Directiva ASSUME register_seg:seg_name [,..], în special, ASSUME cs:codeseg, specifică că registrul selectat pentru segmentul seg_name (codeseg) este CS.

Directiva ASSUME este urmată de explicitîncărcați adresa de început a segmentului de date în registrul DS:

Procedura este definită de pseudo-operatori:

nume_procedura proc...

nume_procedură endp

La definirea unei proceduri după cuvânt cheie proc trebuie să specifice atributul distanță aproape sau departe; dacă acest atribut nu este prezent, atunci valoarea implicită este aproape. De obicei, procedura ar trebui să se încheie cu o comandă ret (retur). Dacă o procedură este declarată ca fiind apropiată, atunci apelul trebuie făcut din același segment; dacă procfar, atunci din orice segment (în acest caz, comanda ret va scoate două cuvinte din stivă la întoarcere: pentru IP și pentru CS).

Directive privind controlul difuzării

Sunt mai multe dintre ele, cel mai des folosit este END. Directiva END marchează sfârșitul programului și îi spune asamblatorului unde să termine traducerea. Format: END [nume_program].

Proceduri de programare pentru lucrul cu dispozitive de intrare/ieșire

Procedurile I/O dintr-un PC sunt de obicei efectuate folosind întreruperi. Compoziția și utilizarea principalelor tipuri de întreruperi și funcții de serviciu ale întreruperii DOS 21H sunt discutate în lucrări. Mai jos vom discuta pe scurt problemele legate de programarea întreruperilor I/O numai pentru afișarea informațiilor pe afișaj și intrarea tastaturii. Problemele de ieșire a informațiilor către o imprimantă și de lucru cu fișiere sunt discutate în lucru.

Programare display

Setarea modurilor de operare și schimbul de date cu afișajul poate fi efectuată folosind întreruperile BIOS de tip 10H, iar datele pot fi transmise pe afișaj folosind întreruperi DOS tip 21H.

Operații video cu întrerupere DOS 21H

l Ieșire simbol pe ecran: AH = 2 sau AH = 6 și DL<>0FFh. Registrul DL trebuie să conțină codul ASCII al caracterului. Exemplu de fragment de program (ieșirea simbolului „C”):

mov DL, 43H; 43H este codul ASCII pentru caracterul C

l Ieșirea unui șir de caractere: AH = 9 (funcția cea mai frecvent utilizată). Registrele DS:DX trebuie să conțină adresa de pornire a șirului de caractere, care trebuie să se termine cu caracterul $. Un exemplu de fragment de program (afișând textul „ieșire un șir de caractere $”):

Text db "șir de caractere de ieșire $"

mov DX, text offset; aceasta este adresa liniei de ieșire

l I/O din fișier prin număr logic. Numerele logice standard ale fișierelor identifică tipul și dispozitivul I/O:

l 0 - intrare de la tastatură;

l 1 - ieșire pe ecranul de afișare;

l 2- afișează un mesaj de eroare;

l 3- I/O activat dispozitiv extern;

l 4- imprimare.

Funcția AH = 3Fh a întreruperii 21H este utilizată pentru intrare, funcția AH = 40h a întreruperii 21H este utilizată pentru ieșire. Registrul CX este pre-setat cu numărul de octeți de intrare/ieșire, iar registrul DX este pre-setat cu adresa de pornire a câmpului de memorie pentru I/O. Dacă procedura I/O se finalizează cu succes, indicatorul de transport CF este șters și numărul de octeți efectiv transferați este returnat în registrul AX. Dacă operațiunea eșuează, indicatorul CF este setat la 1 și un cod de eroare este scris în registrul AX.

Exemplul de mai jos conține un fragment de program de afișat pe ecran fisier text Text care conține 50 de octeți.

text db 50 dup(" ")

mov BX, 1; specificând dispozitivul de ieșire

mov CX, 50 ;indică numărul de octeți care urmează să fie scos

mov DX, text offset; precizând adresa de pornire

; câmp de memorie care conține text

Unul dintre cele mai importante elemente ale acestei părți a cărții sunt exemple de programe în codurile mașiniiși în limbajul ASSEMBLARE. În imprimările acestor programe va trebui să folosim acest lucru

numite DIRECTIVE DE MONTAJ și acum, probabil, cel mai mult oră convenabilă pentru a face o idee despre ce este.

Ne vom uita la următoarele directive: ORG, EQU, DEFB, DEFW, DEFM și END, dar înainte de a începe să le luăm în considerare, trebuie să înțelegem ferm:

1. Directivele ASAMBLARE nu sunt comenzi ale procesorului Z8 0 și în acest sens nu au nicio legătură cu codul mașinii Z8 0.

2. ASSEMBLER este un program care traduce (traduce) textul scris de tine sub formă de mnemonici în cod obiect, care este codul mașinii. Și aceste directive ASSEMBLY sunt niște comenzi pentru programul de asamblare. Ele nu sunt traduse și nu vor fi incluse în codul obiect, dar vă vor face mai ușor să scrieți și, cel mai important, să citiți programul scris în mnemotec.

3. Există foarte multe programe de ASAMBLARE și fiecare dintre ele poate avea propriile sale directive. Ei pot avea aceleași directive, dar prezente cerințe diferite la utilizarea lor. Într-un cuvânt, trebuie să stabiliți metode specifice de utilizare a directivelor ASSEMBLY conform instrucțiunilor pentru programul de asamblare pe care îl utilizați (de exemplu, EDITAS, GENS 3, GENS 4, ZEUS etc.). Și, deși nu există standarde, totuși, unele concepte fundamentale pot fi încă identificate și ne vom concentra asupra lor.

3.1. Comentarii.

Vom începe cu cel mai simplu lucru - comentarii. Sunt scrise după simbolul „;”. (punct virgulă).

Desigur, înțelegeți că tot ceea ce este comentarii nu este compilat în codul mașinii de către ASSEMBLY - acest lucru nu este de niciun folos. Ele servesc doar pentru a vă face mai convenabil să vă ocupați de o listă pe care altcineva sau dvs. ați compilat-o, dar cu mult timp în urmă.

De exemplu:

10 60001 LD E,A 2 0

După cum puteți vedea, linia poate

; Încărcat în registrul E care conține -; presa de baterie. ; A scăzut cu unu.

doar din comentariu.

Etichete.

Etichetele simplifică foarte mult scrierea programelor în mnemonicii ASSEMBLY. În operațiunile de salt JP, JR, DJNZ și subrutinele de apelare CALL, nu puteți specifica adresa la care doriți să săriți, ci înlocuiți o etichetă. Pe de altă parte, când scrieți comenzi pentru această adresă, puneți și un marcaj acolo, De exemplu:

10 60001 ÎNCEPE LD B,0 4

20 60003 AGAIN INC HL

40 60005 DJNZ, DIN NOU

3.2.

250 260 270

60110 60111 60113

LD A,(HL) CP 80H JR NZ,ÎNCEPE

După cum puteți vedea, este foarte convenabil. Puteți vedea imediat că de la linia 40 întoarcerea este la eticheta AGAIN dacă registrul B nu ajunge la zero. Linia 270 revine la eticheta BEGIN.

Cu siguranță are sens să alegeți un nume pentru etichetă care să se potrivească cu semnificația operației efectuate - acest lucru face lista de programe mai ușor de citit și de înțeles.

În timpul compilării, programul de asamblare însuși va calcula valorile decalajelor necesare în instrucțiunile procesorului și le va înlocui în loc de etichete. Deci, de exemplu, în linia 40 în loc de DJNZ din nou codul obiect va conține DJNZ FCH, care este același lucru.

În exemplul anterior, am folosit etichetele foarte puțin. Cert este că atât referirea la etichetă, cât și eticheta în sine au fost în aceeași procedură. Dar dacă doriți să accesați o etichetă care se află într-o altă procedură pe care ați scris-o și ați compilat-o ieri și dacă trebuie să faceți tranziția la o procedură ROM și doriți să utilizați eticheta? În acest caz, directiva EQU vă va ajuta. Acesta atribuie o valoare numerică etichetei. Desigur, în timpul compilării această directivă nu este convertită în niciun fel în cod mașină, dar dacă există referințe la această etichetă în textul programului, atunci valoarea preluată din directiva EQU va fi înlocuită.

De exemplu, în programul dvs. trebuie să apelați în mod repetat procedurile ROM, să spuneți CLEAR (1EACH=7 8 52) și OUT-LINE (1856H=6230). Apoi, la începutul programului, specificați

de exemplu numindu-le CLEAR

directivă

valorile la mărcile lor, n

și OUT L.

CLAR

EQU 7 8 52

OUT L

EQU 62 3 0

ETICHETA

EQU 60016

apel

le stii pe astea

proceduri sau

prin marcaj.

60001

LD HL, (Etichetă)

60004

LD BC, 0008

60007

LD DE, (04 52)

60010

Apelați CLEAR

60013

Sunați-l pe L

60016

Pe loc

iti datorez

a avertiza,

exemple

din punct de vedere

software

exemple despre cum sunt folosite anumite directive ASSEMBLY și dacă aveți nevoie de un sens real în exemple, atunci îl veți obține puțin mai târziu, în capitolele următoare, unde vom analiza tehnici practice de programare.

Să aruncăm o altă privire la exemplul anterior. În rândul 30, trimitem perechii de registre HL ceea ce este conținut în adresa indicată de eticheta LABEL, care, conform directivei EQU, indică adresa 60016.

Deci, celulele 60016 și 60017 conțin unele date care pot fi utilizate ulterior de program. Puteți trimite singur aceste date către celule înainte de compilare. Și nu trebuie să utilizați codul de mașină pentru asta. Valorile inițialeîn celulele de memorie puteți seta folosind directivele DEFB, DEFW și DEFM.

DEFB - DEFINE BYTE - setează un octet.

DEFW - DEFINE WORD - setați un „cuvânt” (un „cuvânt” este doi octeți consecutivi. De obicei, aceasta este o adresă.) DEFM - DEFINE MESSAGE - setați un mesaj (aceștia sunt mai mulți octeți consecutivi). De obicei, programele de asamblare impun o limită a câți octeți pot fi specificați de o directivă DEFM, să spunem nu mai mult de cinci. Dar asta nu ar trebui să te îngrijoreze. Daca vrei sa intrebi mesaj lung, atunci puteți pune câte linii DEFM la rând doriți.

Deci, DEFB specifică un singur octet (0...255), DEFW specifică doi octeți consecutivi (0...65535), iar DEFM specifică un grup de octeți consecutivi - mesaj text, tabel de numere etc.

În exemplul nostru anterior, dacă dorim să stocăm un număr de doi octeți la adresele 60016 și 60017, linia 80 ar trebui scrisă astfel:

80 60016 DEFW 5C92H

90 60018

Să presupunem că doriți să stocați cuvântul „Spectrum” începând de la adresa 60135.

Cod pentru litera "S" Cod pentru litera "p" "e" "c" "t" "r"

"u" "m"

60135

60136

60137

60138

60139

60140

60141

60142

53H 7 0H 65H 63H 7 4H 72H 75H 6DH

DEFB DEFB DEFB DEFB DEFB DEFB DEFB DEFB

îl puteți specifica în perechi de octeți:

Dar este mai ușor și mai corect să îl setați ca mesaj:

60135 DEFM 5370656374 ; "Spect"

60140 DEFM 72756D ; "rom"

Există un caz special la programarea în ASSEMBLY când textul programului trebuie introdus și prin DEFB sau DEFM. Acesta este cazul când scrieți un program pentru un calculator încorporat. La urma urmei, un program de asamblare poate traduce mnemonicii ASSEMBLY în codul mașinii, dar nu știe nimic despre codurile calculatorului și nu-și cunoaște mnemonicii. Codul calculatorului este o chestiune internă „Sinclair”, interpretarea sa

Programele aflate în ROM sunt procesate, iar codul calculatorului nu are nicio legătură cu procesorul și comenzile acestuia. Prin urmare, veți putea introduce comenzi de calculator într-un program de asamblare doar ca o secvență de octeți independenți, adică prin DEFB sau DEFM.

În prima parte a cărții, am folosit notații mnemonice pentru comenzile calculatorului, cum ar fi add, stk_data s_lt etc., și le-am scris cu o literă mică, spre deosebire de comenzile procesorului. Dar am făcut acest lucru înainte și vom continua să facem acest lucru doar de dragul înțelegerii și ușurinței înregistrării. Programul ASSEMBLY nu cunoaște astfel de mnemonici, ele nu sunt în dicționarul său.

Deci, cu ajutorul DEFB, DEFW și DEFM, ei setează valorile inițiale ale variabilelor programului, introduc tabele, mesaje și orice alte secvențe de date în program, chiar și

grafice, precum și secvențe de cod pe care programul de asamblare nu le înțelege ca comenzi ASSEMBLY.

3.5. Directive ORG, END.

Trebuie doar să luăm în considerare cele două directive cele mai banale. Directiva ORG declară adresa de la care va fi asamblat programul. Trebuie să fie prima directivă din codul sursă, deși în principiu pot exista comentarii înaintea acesteia.

Ați observat că în exemplele de mai sus am scris o coloană de adrese în stânga în care vor fi plasate anumite comenzi. Deci, acest lucru nu este necesar să faceți atunci când programați în ASAMBLARE. Este suficient să dai o directivă de la bun început

10 ORG 63000

iar apoi programul de asamblare însuși va calcula în ce celulă de memorie va fi amplasată această sau acea instrucțiune. Acest lucru simplifică foarte mult procesul de programare. Și dacă faci modificări la text gata, ASSEMBLATORUL însuși va corecta toate adresele.

Directiva END marchează sfârșitul unui program. Dacă mai este ceva după el, ASSEMBLEA îl va ignora în timpul compilării.

Acesta este, probabil, tot ceea ce merită să știți despre directivele ASSEMBLEEI pentru început. Acestea nu sunt toate directivele care pot fi întâlnite în viață, iar regulile de utilizare a acestora sunt diferite pentru diferiți asamblatori, dar în funcție de în general acest minim va satisface 90 la sută din nevoile dvs. de informații, iar restul ar trebui să îl obțineți din instrucțiunile pentru asamblatorul cu care lucrați.