background image

Wykład z budowy i programowania układów

mikroprocesorowych

Wykład prowadził profesor Jerzy Jakubiec.

Notowali Rafał Kała i Adam Szojda.

background image
background image

Spis rzeczy

1

Programowanie w j ˛ezyku asembler

1

1.1

Podstawowe wła´sciwo´sci asemblera . . . . . . . . . . . . . . . . . . . . . . .

1

1.1.1

Proces powstawania i tłumaczenia programu

. . . . . . . . . . . . . .

1

1.1.2

Składnia instrukcji asemblera

. . . . . . . . . . . . . . . . . . . . . .

2

1.1.3

Komentowanie programu . . . . . . . . . . . . . . . . . . . . . . . . .

3

1.1.4

Elementarne obiekty j˛ezyka . . . . . . . . . . . . . . . . . . . . . . .

3

1.1.5

Tworzenie nazw i operacje na słowniku . . . . . . . . . . . . . . . . .

5

1.1.6

Dyrektywy rezerwacji pami˛eci . . . . . . . . . . . . . . . . . . . . . .

6

1.1.7

Dyrektywa ko ´ncz ˛

aca program . . . . . . . . . . . . . . . . . . . . . .

7

1.2

Makroasembler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7

1.2.1

Ogólne wła´sciwo´sci makroasemblera . . . . . . . . . . . . . . . . . .

7

1.2.2

Asemblacja warunkowa

. . . . . . . . . . . . . . . . . . . . . . . . .

7

1.2.3

Makrodefinicje . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8

1.3

Tworzenie programów w postaci modułowej

. . . . . . . . . . . . . . . . . .

8

1.3.1

Moduły programowe . . . . . . . . . . . . . . . . . . . . . . . . . . .

8

1.3.2

Absolutne i wzgl˛edne tłumaczenie modułów programowych . . . . . .

10

1.3.3

Atrybuty nazw w programach modułowych . . . . . . . . . . . . . . .

11

1.3.4

Relokowalo´s´c modułów . . . . . . . . . . . . . . . . . . . . . . . . .

12

1.3.5

Współu˙zywanie nazw w modułach . . . . . . . . . . . . . . . . . . . .

13

1.3.6

Doł ˛

aczanie modułu zawieraj ˛

acego kod ´zródłowy programu . . . . . . .

14

1.4

Sekcje . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

14

1.4.1

Typy sekcji . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

14

1.4.2

Składnia dyrektywy .SECTION . . . . . . . . . . . . . . . . . . . . .

15

1.4.3

Sekcje rejestrowe i sekcje bitowe

. . . . . . . . . . . . . . . . . . . .

15

1.5

Lokowanie sekcji w pami˛eci . . . . . . . . . . . . . . . . . . . . . . . . . . .

16

1.5.1

Sposoby lokowania sekcji . . . . . . . . . . . . . . . . . . . . . . . .

16

1.5.2

Zwi ˛

azki mi˛edzy sekcjami

. . . . . . . . . . . . . . . . . . . . . . . .

16

1.5.3

Sterowanie lokowaniem sekcji . . . . . . . . . . . . . . . . . . . . . .

17

1.5.4

Konsolidacja programu o strukturze sekcyjnej . . . . . . . . . . . . . .

18

2

Programowanie w C

µ

K rodziny Intel 8051

21

2.1

Proces uzyskiwania programu wynikowego dla programów w C . . . . . . . .

21

2.2

Program rozruchowy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

22

2.2.1

Rodzaje programu rozruchowego

. . . . . . . . . . . . . . . . . . . .

22

2.2.2

Definiowanie rodzaju mikrokontrolera . . . . . . . . . . . . . . . . . .

23

i

background image

Spis rzeczy

2.2.3

Deklaracja rejestrów roboczych . . . . . . . . . . . . . . . . . . . . .

26

2.2.4

Przesuwanie danych . . . . . . . . . . . . . . . . . . . . . . . . . . .

27

2.2.5

Przygotowanie stosu . . . . . . . . . . . . . . . . . . . . . . . . . . .

28

2.2.6

Wywołanie programu w C . . . . . . . . . . . . . . . . . . . . . . . .

28

2.3

Organizacja danych w C . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

29

2.3.1

Typy danych i ich modyfikatory . . . . . . . . . . . . . . . . . . . . .

29

2.3.2

Organizacja ramki stosu . . . . . . . . . . . . . . . . . . . . . . . . .

30

2.3.3

Przekazywanie argumentów do funkcji

. . . . . . . . . . . . . . . . .

31

2.3.4

Rozmieszczenie zmiennych lokalnych w ramce stosu . . . . . . . . . .

33

2.3.5

Przechowywanie warto´sci zwracanych przez funkcj˛e . . . . . . . . . .

36

2.4

Przekazywanie danych mi˛edzy funkcjami a instrukcjami asemblera . . . . . . .

37

2.4.1

Wprowadzanie instrukcji asemblera do programu w C . . . . . . . . .

37

2.4.2

Dost˛ep do zmiennych lokalnych . . . . . . . . . . . . . . . . . . . . .

38

2.4.3

Dost˛ep do argumentów funkcji j˛ezyka C . . . . . . . . . . . . . . . . .

38

2.4.4

Adresowanie bezpo´srednie i po´srednie w programach w C . . . . . . .

39

Indeks

43

ii

background image

Spis rysunków

1.1

Proces tworzenia programu . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1

1.2

Proces tworzenia programów w postaci modułowej . . . . . . . . . . . . . . .

10

1.3

Zwi ˛

azki mi˛edzy sekcjami . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

17

2.1

Proces uzyskiwania programu wynikowego dla programów w C . . . . . . . .

21

2.2

Struktura wewn˛etrznej pami˛eci RAM po zainicjowaniu stosu . . . . . . . . . .

29

2.3

Ramka stosu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

31

2.4

Kolejno´s´c argumentów funkcji w ramce stosu . . . . . . . . . . . . . . . . . .

32

2.5

Ramka stosu dla przykładu ze strony 33 . . . . . . . . . . . . . . . . . . . . .

34

2.6

Mapa pami˛eci zmiennych lokalnych . . . . . . . . . . . . . . . . . . . . . . .

34

2.7

Mapa ramki stosu funkcji z przykłady ze strony 33

. . . . . . . . . . . . . . .

36

iii

background image

Spis rysunków

iv

background image

1 Programowanie w j ˛ezyku asembler

1.1

Podstawowe wła ´sciwo ´sci asemblera

1.1.1

Proces powstawania i tłumaczenia programu

Program z´ródłowy

Program wynikowy

Tłumaczenie

Rysunek 1.1: Proces tworzenia programu

Proces tworzenia programu u˙zytkowego, niezale˙znie od zastosowanego j˛ezyka programo-

wania, przebiega w sposób przedstawiony ogólnie na rysunku 1.1. Proces ten mo˙zna okre ´sli´c
jako zespół działa ´n słu˙z ˛

acych przetworzeniu programu, tworzonego w sposób dogodny dla pro-

gramisty i specyficzny dla rodzaju oprogramowywanego zadania, na posta ´c dostosowan ˛

a do

potrzeb procesora realizuj ˛

acego program. Ta pierwotna posta ´c programu, nazywana programem

´zródłowym, ma zawsze posta´c symboliczn ˛

a i powstaje przy u˙zyciu edytora tekstu

1

Program

wynikowy ma posta´c binarn ˛

a wyra˙zon ˛

a j˛ezykiem wewn˛etrznym (maszynowym) procesora. Pro-

ces tłumaczenia polega na nadawaniu warto´sci liczbowych nazwom symbolicznym. Elementem
składowym tego procesu jest równie˙z organizacja i zapis pami˛eci danych. Program ´zródłowy
stanowi ci ˛

ag instrukcji uszeregowanych w sposób wła´sciwy dla celów realizacji okre´slonego za-

dania. Posta´c instrukcji narzuca sposób tłumaczenia programu, okre´slaj ˛

ac zarazem podstawowy

podział j˛ezyków programowania. Wyró˙znia si˛e dwa podstawowe rodzaje j˛ezyków:

j˛ezyki maszynowo (sprz˛etowo) zorientowane nazywane asemblerami a w rozwini˛etej wer-
sji makroasemblerami,

j˛ezyki proceduralnie zorientowane, czyli tzw. j˛ezyki wy˙zszego rz˛edu.

Budowa asemblera dostosowana jest do wła´sciwo´sci sprz˛etowych procesora i urz ˛

adze ´n z nim

współpracuj ˛

acych. Wyst˛epuje wi˛ec ´scisły zwi ˛

azek mi˛edzy budow ˛

a mikrokomputera a postaci ˛

a

instrukcji j˛ezyka typu asembler. Zewn˛etrznie ten zwi ˛

azek przejawia si˛e w taki sposób, ˙ze jedna

instrukcja w j˛ezyku asemblerowym koduje jeden rozkaz maszynowy (jest to tzw. własno´s´c jeden
na jeden
). Symbolika j˛ezyka sprowadza si˛e do u˙zywania:

1

Czyli MS Word odpada, na szcz˛e´scie . . . ;-)

1

background image

1

Programowanie w j˛ezyku asembler

symbolicznych (mnemonicznych) kodów rozkazów,

symbolicznych adresów i danych.

Reasumuj ˛

ac mo˙zna powiedzie´c, ˙ze j˛ezyk typu asembler jest j˛ezykiem symbolicznym sprz˛etowo

zorientowanym.

Podstawow ˛

a cech ˛

a j˛ezyka wy˙zszego poziomu jest orientacja proceduralna, tzn. ˙ze j˛ezyki te

s ˛

a budowane pod k ˛

atem optymalizacji okre´slonego rodzaju zada ´n. Dzieli si˛e je na:

j˛ezyki algorytmiczne,

j˛ezyki symulacyjne,

j˛ezyki do tworzenia baz danych, itp. itd.

Programy pisane w tych j˛ezykach maj ˛

a praktycznie tak ˛

a sam ˛

a posta ´c dla ró˙znych typów kom-

puterów. Ró˙zni ˛

a si˛e natomiast programy tłumacz ˛

ace, które musz ˛

a by ´c inne dla ka˙zdego typu

komputera (procesora). Istotn ˛

a zewn˛etrzn ˛

a cech ˛

a j˛ezyków wy˙zszego rz˛edu jest zast˛epowanie

ka˙zdej ich instrukcji wieloma rozkazami maszynowymi.

1.1.2

Składnia instrukcji asemblera

Instrukcja jest elementarnym poleceniem dla programu tłumacz ˛

acego. Inaczej mo˙zna po-

wiedzie´c, ˙ze instrukcja jest podstawowym elementem j˛ezyka. Instrukcja mo˙ze:

kodowa´c rozkaz,

zawiera´c dyrektyw˛e,

by´c pusta (komentarz).

Dyrektywa jest to taki rodzaj instrukcji, która słu˙zy do organizowania programu. Na ogół

dyrektywy nie generuj ˛

a kodu, za wyj ˛

atkiem takich, które wprowadzaj ˛

a liczby do pami˛eci da-

nych.

Instrukcja jest zapisana w oddzielnej linii programu ´zródłowego, zatem linia programu jest

jednostk ˛

a organizacji programu ´zródłowego. W linii programu wyró˙znia si˛e cztery pola (zawar-

to´s´c ka˙zdego z nich mo˙ze by´c pusta):

pole_etykiety: pole_operacji pole_argumentów ;pole komentarza

Dwukropek jest wyró˙znikiem pola etykiety, przed komentarzem zawsze musi wyst˛epowa ´c ´sred-
nik. W polu etykiety umieszczana jest nazwa wprowadzana przez programist˛e. U˙zycie nazwy
w polu etykiety nadaje jej warto´s´c w procesie tłumaczenia programu według okre´slonych reguł.
Nazwa w polu etykiety musi by´c zako ´nczona dwukropkiem. Długo´s´c nazwy w polu etykiety
zale˙zy od dopuszczalnej długo´sci nazw danej wersji asemblera. W przypadku pakietu 2500AD
wynosi ona 32 znaki, przy czym zalecane jest u˙zywanie nie wi˛ecej ni˙z 10 znaków. Zawarto ´s´c

2

background image

1.1

Podstawowe wła´sciwo´sci asemblera

pola operacji okre´sla rozkaz maszynowy lub dyrektyw˛e. Natomiast pole argumentówpodaje
dodatkowe argumenty, których liczba i rodzaj zale˙z ˛

a od zawarto´sci pola operacji. Pole komen-

tarza, poprzedzone ´srednikiem, mo˙ze zawiera´c dowolny ci ˛

ag znaków. Komentarz w procesie

tłumaczenia jest przez asembler pomijany. Przykład:

int0:

ACALL przeslij ;prze´

slij komunikat na P1

RETI

komunikat_1: .db ’komunikat 1’,0Dh,0Ah,0

1.1.3

Komentowanie programu

Standardowo komentarz realizuje si˛e przy u˙zyciu ´srednika. Przykład:

;To jest komentarz

;************************

;* Data: xx-xx-xxxx

*

;* Nazwisko programisty *

;* Wersja programu

*

;************************

U˙zycie dyrektywy

.COMMENT

pozwala na swobodne operowanie komentarzem. Cały tekst mi˛e-

dzy znakami przyj˛etymi przez programist˛e jako ograniczniki stanowi komentarz. Przykład:

.comment #

To jest przykład u˙

zycia dyrektywy .comment

Cały tekst zawarty mi˛

edzy hash-ami jest komentarzem

Taki komentarz mo˙

ze mie´

c wiele linii, ale te 3 chyba wystarcz ˛

a...

#

1.1.4

Elementarne obiekty j ˛ezyka

Elementarnymi obiektami j˛ezyka typu asembler, czyli wielko´sciami, na których j˛ezyk wy-

konuje działania, s ˛

a:

stałe,

nazwy,

wyra˙zenia arytmetyczne.

Stałe mog ˛

a by´c zapisane jako:

1. dziesi˛etne: D

2. dwójkowe: B

3. ósemkowe: OQ

3

background image

1

Programowanie w j˛ezyku asembler

4. szesnastkowe: H

5. znakowe

Stałe liczbowe opatrzone s ˛

a odpowiednim symbolem literowym. Pomini˛ecie symbolu oznacza

liczb˛e dziesi˛etn ˛

a. U˙zycie dyrektywy

.RADIX

powoduje zmian˛e standardowej podstawy liczb

u˙zywanych w programie. Argumentem tej dyrektywy jest jeden z wymienionych symboli lub
liczba b˛ed ˛

aca podstaw ˛

a danego kodu

2

. Stałe znakowe ograniczone s ˛

a znakami pojedynczego

lub podwójnego cudzysłowu. Przykład:

127

;stała dziesi˛

etna

101101101b

;stała binarna

0A3h

;stała szestnastkowa. Je˙

zeli pierwsza cyfra stałej

;jest liter ˛

a to nale˙

zy j ˛

a poprzedzi´

c zerem

’napis’

;pi˛

ecio bajtowa stała znakowa

.radix 16

;ustaw standard liczb szesnastkowy

Nazwa jest ci ˛

agiem liter i cyfr zaczynaj ˛

acym si˛e od litery. Liczba znaków w nazwie zale˙zy

od standardu asemblera. W ró˙znych asemblerach zmienia si˛e tak˙ze zbiór dozwolonych znaków
alfanumerycznych, z których mog ˛

a by´c budowane nazwy i inne obiekty j˛ezyka.

Ostatni ˛

a konstrukcj ˛

a składniow ˛

a jest wyra˙zenie arytmetyczne b˛ed ˛

ace ci ˛

agiem nazw i stałych

przedzielonych dwuargumentowymi operatorami arytmetycznymi. Ka˙zda nazwa lub stała mo˙ze
by´c poprzedzona operatorem jednoargumentowym. Dopuszcza si˛e stosowanie nawiasów w celu
ł ˛

aczenia argumentów. Operatory wyra˙ze ´n arytmetycznych:

1. Operatory jednoargumentowe

.NOT.

’, ‘

\

’,

‘!

’ – zaprzeczenie logiczne,

+

’ – opcjonalne oznacza argument dodatni,

-

’ – negacja arytmetyczna (uzupełnienie dwójkowe),

<

’, ‘

.HIGH.

’ – starszy bajt szesnastobitowego słowa,

>

’, ‘

.LOW.

’ – młodszy bajt szesnastobitowego słowa.

2. Operatory dwuargumentowe

**

’ – pot˛egowanie całkowite,

*

’ – mno˙zenie całkowite,

/

’ – dzielenie całkowite,

.SHR.

’ – przesuw w prawo,

.SHL.

’ – przesuw w lewo,

+

’ – suma arytmetyczna,

2

2, 8, 10 lub 16

4

background image

1.1

Podstawowe wła´sciwo´sci asemblera

-

’ – ró˙znica arytmetyczna,

.AND.

’, ‘

&

’ – iloczyn logiczny,

.OR.

’, ‘

^

’ – suma logiczna,

.XOR.

’ – suma modulo 2 (ró˙znica symetryczna)

Warto´sci wyra˙ze ´n arytmetycznych zapisywane s ˛

a w słowie o´smio lub szesnastobitowym w za-

le˙zno´sci od kontekstu wyra˙zenia. Nale˙zy podkre´sli´c, ˙ze w asemblerze wyra˙zenia arytmetyczne
słu˙z ˛

a do obliczania warto´sci nazw, a nie do realizacji oblicze ´n przez program wynikowy. War-

to´sci wyra˙ze ´n arytmetycznych s ˛

a obliczane podczas procesu tłumaczenia, a nie w trakcie jego

realizacji.

W trakcie asemblacji mo˙zliwe jest stosowanie porówna ´n, których wynikiem jest

1

gdy wa-

runek jest spełniony lub

0

gdy nie jest. Operatory porówna ´n:

=

’, ‘

.EQ.

’ – równo´s´c,

>

’, ‘

.GT.

’ – wi˛eksze ni˙z,

<

’, ‘

.LT.

’ – mniejsze ni˙z,

.UGT.

’ – wi˛eksze ni˙z dla liczb bez znaku (ang. unsigned),

.ULT.

’ – mniejsze ni˙z dla liczb bez znaku.

1.1.5

Tworzenie nazw i operacje na słowniku

Asembler w chwili rozpocz˛ecia tłumaczenia zawiera pewien wst˛epnie zdefiniowany słownik

Umieszczone s ˛

a w nim nazwy rozkazów procesora, nazwy dyrektyw, nazwy innych obiektów

j˛ezyka (np. nazwy rejestrów). Nazwy te mog ˛

a by ´c u˙zywane w programie wg. okre´slonych reguł,

zgodnie ze sposobem budowy rozkazów mikroprocesora i konstrukcji asemblera. Podstawowym
sposobem dopisania nowej nazwy do słownika jest umieszczenie jej w polu etykiety. W procesie
tłumaczenia nazwa b˛ed ˛

aca etykiet ˛

a uzyskuje warto´s´c równ ˛

a bie˙z ˛

acemu wska´znikowi umiesz-

czenia

3

. Bie˙z ˛

acy wska´znik umieszczenia jest zmienn ˛

a procesu tłumaczenia przybieraj ˛

ac ˛

a war-

to´sci równe adresom, pod którymi lokowany jest kod wynikowy. Programista powinien ustawi ´c
warto´s´c wska´znika przed napisaniem pierwszej linii programu zawieraj ˛

acej rozkaz. Do tego celu

słu˙zy dyrektywa

.ORG

4

, której argumentem jest warto´s´c adresu nadawana, przy ka˙zdym u˙zyciu

dyrektywy, bie˙z ˛

acemu wska´znikowi umieszczenia. W pakiecie 2500AD pomini˛ecie pocz ˛

atko-

wej dyrektywy

.ORG

powoduje przyj˛ecie domy´slnej warto´sci wska´znika umieszczenia

$=0000

.

Przykład:

;program przykładowy

.org 0

;$=0000h

ajmp start

.org 3

;obsługa przerwania INT0

3

Oznaczanym ‘

$

4

ORIGIN

5

background image

1

Programowanie w j˛ezyku asembler

int0:

acall 100h ;prze´

slij komunikat na port P1

reti

.org 30h

start:

acall 40h

;inicjacja mikrokontrolera

czekaj: nop

ajmp czekaj

;czekaj na przerwanie

Innym sposobem dopisania nazwy do słownika, czyli nadania jej warto ´sci, jest u˙zycie jednej
z dyrektyw

.SET

lub

.EQU

, których argumentem jest wyra˙zenie arytmetyczne. Ró˙znica pomi˛e-

dzy

.SET

a

.EQU

sprowadza si˛e do tego, ˙ze nazwa zdefiniowana przez

.SET

mo˙ze by ´c w tym

samym programie okre´slana wielokrotnie w ró˙znych miejscach – nazwa redefiniowalna. Nato-
miast zdefiniowanie nazwy dyrektyw ˛

a

.EQU

wyklucza jej powtórne okre´slenie. Nazwa taka jest

nieredefiniowajna i nazywana jest cz˛esto absolutn ˛

a.

Program tłumacz ˛

acy musi jednoznacznie przypisa ´c ka˙zdej nowej nazwie odpowiedni ˛

a war-

to´s´c. Proces tłumaczenia przebiega sekwencyjnie linia po linii od pocz ˛

atku programu. Ist-

nieje mo˙zliwo´s´c wielokrotnego definiowania tych samych nazw, a ponadto mo˙ze si˛e zdarzy ´c, ˙ze
w procesie tłumaczenia danej linii nazwa w niej u˙zyta nie została jeszcze zdefiniowana. Z po-
wy˙zszych powodów ka˙zdej tworzonej przez programist˛e nazwie musz ˛

a by ´c przyporz ˛

adkowane

atrybuty maj ˛

ace posta´c jednobitowej informacji towarzysz ˛

acej nazwie. Podstawowe atrybuty to:

1. warto´s´c (

0

– brak warto´sci,

1

– jest warto´s´c) ,

2. logiczne – redefiniowalno´s´c

Atrybut okre´slono´sci mówi o tym, czy w chwili tłumaczenia danej linii nazwa ma ju˙z warto ´s´c.
Warunkiem koniecznym poprawno´sci programu jest to, aby po przetłumaczeniu ostatniej linii
programu wszystkiem nazwy w słowniku były okre´slone.

1.1.6

Dyrektywy rezerwacji pami ˛eci

Słu˙z ˛

a do rezerwowania pami˛eci operacyjnej na pola robocze programu (s ˛

a to elementy pa-

mi˛eci danych) oraz do ustalania pocz ˛

atkowych warto´sci tych pól.

Dyrektywa

.DB

.DB lista_argumentów

Po przetworzeniu tej dyrektywy w kolejnych bajtach kodu wynikowego s ˛

a umieszczane warto ´sci

odpowiednich wyra˙ze ´n arytmetycznych lub warto´sci kodów ASCII znaków tworz ˛

acych stałe

znakowe.

Dyrektywa

.DW

Dyrektywa ta ma analogiczn ˛

a składni˛e jak

.DB

, z tym ˙ze jej argumenty słu˙z ˛

a do okre ´slania

warto´sci szesnastobitowych.

6

background image

1.2

Makroasembler

Dyrektywa

.DS

Słu˙zy do rezerwacji liczby komórek okre´slonej przez parametr b˛ed ˛

acy jej argumentem.

W rezerwowany obszar nie jest wpisywana ˙zadna informacja lub jest on zerowany (na ogół
na ˙z ˛

adanie programisty).

1.1.7

Dyrektywa ko ´

ncz ˛

aca program

Dyrektyw ˛

a ko ´ncz ˛

ac ˛

a program jest dyrektywa

.END

.

1.2

Makroasembler

1.2.1

Ogólne wła ´sciwo ´sci makroasemblera

Makroasembler jest asemblerem rozsze˙zonym o dodatkowe dyrektywy i konstrukcje, któ-

rych u˙zycie pozwala programi´scie na wykonanie pewnych operacji na tek´scie programu ´zródło-
wego. W wyniku tych operacji mo˙zna:

kre´sli´c warunek uwzgl˛ednienia lub zignorowania fragmentu programu ´zródłowego,

zdefiniowa´c pewn ˛

a instrukcj˛e, której u˙zycie jest równoznaczne wstawieniu ci ˛

agu linii pro-

gramu,

spowodowa´c wstawienie w program ´zródłowy ci ˛

agu linii skojarzonych z wcze´sniej okre-

´slon ˛

a instrukcj ˛

a.

W przypadku makroasemblera proces tłumaczenia ró˙zni si˛e w pewnym stopniu od tłumaczenia
w prostym asemblerze. Ka˙zda wczytana linia podlega wst˛epnej analizie i ew. przetworzeniu.
W wyniku tego linia mo˙ze:

zosta´c zignorowana,

by´c przekazana do dalszej asemblacji bez zmian,

doprowadzi´c do wytworzenia ci˛egu linii z jednej linii wczytanej.

Operacje te zawsze poprzedzaj ˛

a wła´sciwe tłumaczenie w sensie prostego asemblera.

1.2.2

Asemblacja warunkowa

Podstawowa konstrukcja programowa słu˙z ˛

aca do warunkowego tłumaczenia programu ma

nast˛epuj ˛

ac ˛

a posta´c:

.if [warunek]

.

;program tłumaczony je´

sli warunek spełniony (1)

.

7

background image

1

Programowanie w j˛ezyku asembler

.else

.

;program tłumaczony je´

sli warunek nie jest spełniony (0)

.

.endif

Dyrektywa

.ELSE

nie jest obligatoryjna. Jej brak oznacza, ˙ze dany fragment programu jest tłu-

maczony, lub nie, bez ˙zadnej alternatywy. Argument dyrektywy

.IF

okre ´sla warto´s´c logiczn ˛

a

w ten sposób, ˙ze warto´s´c wyra˙zenia arytmetycznego u˙zytego jako argument ró˙znej od zera od-
powiada prawda, warto´sci równej zero odpowiada fałsz.

1.2.3

Makrodefinicje

Makrodefinicje definuje si˛e przez umieszczenie fragmentu programu ´zródłowego mi˛edzy

dyrektywami

.MACRO

i

.ENDM

w nast˛epuj ˛

acy sposób:

nazwa: .macro lista,parametrów,formalnych

.

.

;tre´

c makrodefinicji

.

.

.endm

Przykład:

wstaw:

.macro rozkaz, warto´

c

rozkaz

etykieta: .db warto´

c

.endm

Tre´s´c makrodefinicji mo˙ze stanowi´c dowolny ci ˛

ag znaków, który nie musi miec składni popraw-

nej instrukcji i mo˙ze si˛e składa´c z praktycznie dowolnej liczby linii. Ogólnie definicja makroin-
strukcji słu˙zy do tego, aby za pomoc ˛

a jednej linii programu wstawi ´c ci ˛

ag linii okre´slony w tej

definicji. Lini˛e zawieraj ˛

ac ˛

a nazw˛e makrodefinicji nazywa si˛e wywołaniem makroinstrukcji. Za-

wiera ona w polu parametrów ci ˛

ag wyra˙ze ´n arytmetycznych w liczbie odpowiadaj ˛

acej liczbie

parametrów formalnych. Argumenty te nazywa si˛e parametrami aktualnymi. Makroasembler
przetwarzaj ˛

ac wywołanie makroinstrukcji (rozwijaj ˛

ac makroinstrukcj˛e) zast˛epuje odpowiednie

parametry formalne ich aktualnymi warto´sciami. Wywołanie mo˙ze by´c powtarzane dowoln ˛

a

ilo´s´c razy.

1.3

Tworzenie programów w postaci modułowej

1.3.1

Moduły programowe

Ko´ncowa posta´c programu wynikowego powstaje z reguły jako wynik scalania wielu jego

ró˙znych fragmentów. Przyczyny tego maj ˛

a ró˙zny charakter. Wynikaj ˛

a one przede wszystkim

8

background image

1.3

Tworzenie programów w postaci modułowej

z konieczno´sci tworzenia programu przez zespół programistów, a zatem podziału na fragmenty
tworzone równolegle. Bardzo cz˛esto korzysta si˛e przy tym z bibliotek programów standar-
dowych (np. mno˙zenia i dzielenia zmiennoprzecinkowego, konwersji liczb. . . ) tworzonych
i przechowywanych w postaci odr˛ebnych modułów. Równie˙z wła´sciwo´sci fizyczne oprogra-
mowywanego procesora zmuszaj ˛

a do wyodr˛ebnienia fragmentów programu. Na przykład dla

mikrokontrolerów z rozdzielon ˛

a pami˛eci ˛

a programu i danych kod wynikowy trzeba rozdzieli ´c

zgodnie z przeznaczeniem do odpowiednich rodzajów pami˛eci. Podział logiczny dokonywany
jest przez programist˛e w celu wyodr˛ebnienia samodzielnych fragmentów nazywanych proce-
durami. Z reguły procedura jest podprogramem komunikuj ˛

acym si˛e z innymi procedurami za

pomoc ˛

a okre´slonych standardów przekazywania danych. Zatem procedury mog ˛

a by ´c budowane

niezale˙znie – zmiany wprowadzone w ich obr˛ebie nie maj ˛

a bezpo´sredniego wpływu na inne

procedury. Taki sposób tworzenia programu nazywany jest modularnym i stanowi jeden z pod-
stawowych standardów dobrego programowania.

Podstawow ˛

a jednostk ˛

a programow ˛

a z punktu widzenia asemblera jest moduł

5

. Jest to taki

ci ˛

ag linii programu, który dla asemblera stanowi jedn ˛

a cało´s´c. Oznacza to, ˙ze dla ka˙zdego

modułu asembler rozpoczyna swoje działanie od pocz ˛

atku (mówi si˛e, ˙ze ma miejsce restart

asemblera). Przede wszystkim modułem jest plik z programem ´zródłowym. Mo˙zna jednak
wyodr˛ebni´c moduły w ramach pojedynczego pliku. Słu˙z ˛

a do tego dyrektywy asemblera

.MOD

i

.ENDMOD

.

Z tego, ˙ze poszczególne moduły tłumaczone s ˛

a niezale˙zne, a nast˛epnie zestawiane w jedn ˛

a

cało´s´c, wynikaj ˛

a dwa istotne fakty:

kod programu uzyskany w wyniku asemblacji musi mie ´c tak ˛

a postac aby mógł by´c umiesz-

czony w dowolnym obszarze pami˛eci – posta ´c taka nazywa si˛e postaci ˛

a relokowaln ˛

a

(przesuwaln ˛

a),

z konieczno´sci tworzenia programów z po´srednich postaci przesuwalnej wynika potrzeba
dwustopniowej realizacji procesu tłumaczenia (rys. 1.2). W pierwszej fazie przy u˙zyciu
asemblera tworzone s ˛

a programy w postaci relokowalnej, w drugiej fazie moduły relo-

kowalne s ˛

a zespalane w procesie konsolidacji

6

w jedn ˛

a cało´s´c lokowan ˛

a w obszarach

pami˛eci o ´sci´sle okre´slonych adresach. T ˛

a drug ˛

a faz˛e realizuje program nazywany konso-

lidatorem lub programem ł ˛

acz ˛

acym

7

.

Techniczne aspekty procesu konsolidacji wymagaj ˛

a podziału modułów na mniejsze cz˛e ´sci, ele-

mentarne z punktu widzenia konsolidatora. Wynika to przedewszystkim z konieczno ´sci podziału
ka˙zdego modułu na cz˛e´sci zawieraj ˛

ace program i dane, a tak˙ze na inne fragmenty zwi ˛

azane ze

specyfik ˛

a konstrukcji procesera. Dla INTEL 8051 wyodr˛ebnianie fragmentów programu zwi ˛

a-

zane jest z podziałem pami˛eci RAM na wewn˛etrzn ˛

a i zewn˛etrzn ˛

a, wydzieleniem rejestrów ro-

boczych i specjalnych oraz pami˛eci adresowanej bitowo.

Definiuje si˛e poj˛ecie sekcji

8

lub segmentu jako takiego, spójnego logicznie, fragmentu pro-

gramu, który jest traktowany przez konsolidator jako jedna elementarna cało ´s´c. Oznacza to, ˙ze

5

ang. module

6

ł ˛

aczenia, linkowania

7

ang. linker

8

ang. section

9

background image

1

Programowanie w j˛ezyku asembler

Asembler

Moduł 1

Moduł n

Asembler

Konsolidator

Program

wynikowy

*.obj

*.asm

*.asm

*.obj

*.exe

Rysunek 1.2: Proces tworzenia programów w postaci modułowej

mo˙zna wskaza´c konsolidatorowi adres, pod którym nale˙zy umie´sci´c dan ˛

a sekcj˛e oraz dodatkowe

parametry okre´slaj ˛

ace typ sekcji (np. sekcja z programem, danymi, sekcja rejestrowa. . . ).

Bior ˛

ac pod uwag˛e, ˙ze w procesie konsolidacji zespalane mo˙ze by ´c wiele modułów w ka˙z-

dym z nich mo˙zna na ogół wyró˙zni´c sekcje tego samego typu. Sekcje takie powinny by ´c ł ˛

aczone

ze sob ˛

a i umieszczane w zwartym obszrze pami˛eci. Zatem cz˛esto wygodzniej jest operowa ´c na

wi˛ekszych cało´sciach nazywanych grupami sekcji lub grupami. Grupa jest to zespół sekcji o ta-
kich samych nazwach w ró˙znych modułach traktowanych przez konsolidator tak jak pojedyncza
sekcja.

1.3.2

Absolutne i wzgl ˛edne tłumaczenie modułów programowych

Budowanie programu w postaci modułowej wymaga uzyskiwania po asemblacji kodu w po-

staci przesuwalnej umo˙zliwiaj ˛

acej ulokowanie modułu w dowolnym obszarze pami˛eci. Powo-

duje to z kolei konieczno´s´c przyporz ˛

adkowania ka˙zdemu modułowi adresu bazowego, który

stanowi adres odniesienia, wzgl˛edem którego okre´slane s ˛

a warto´sci wszystkich przesuwalnych

(relokowalnych) nazw w danym module. Ilustruje to poni˙zszy przykład

9

:

;program wyprowadzania komunikatu przez port P1

;adres pocz ˛

atku komunikatu w DPTR

.org

BAZA

pisz_kom1:

mov

dptr,#komunikat_1 ;ładuj rejestr bazowy

mov

r0,#0

;licznik znaków

dalej:

mov

a,r0

movc

a,@a+dptr

;pobierz znak

cjne

a,#0,nie_koniec ;czy koniec ła´

ncuch znaków?

ret

;tak

nie_koniec:

mov

p1,a

;nie

inc

r0

ajmp

dalej

;komunikat nr 1

kom_end:

.equ 0

;znak ko´

nca

komunikat_1: .db ’komunikat 1’,0ah,0dh,kom_end

9

U˙zyta w nim nazwa

BAZA

symbolizuje jedynie adres bazowy i słu˙zy do uwidocznienia relacji mi˛edzy tym adresem

a warto´sci ˛

a nazw relokowalnych.

10

background image

1.3

Tworzenie programów w postaci modułowej

Program ´zródłowy

Program wynikowy

aders (hex)

kod (hex)

.org BAZA

BAZA

pisz_kom1:

mov

dptr,#komunikat

_

1

BAZA

90 00 10

mov

r0,#0

BAZA+0003

78 00

dalej:

mov

a,r0

BAZA+0005

e8

movc a,@a+dptr

BAZA+0006

93

cjne a,#0,nie_koniec

BAZA+0007

b4 00 01

ret

BAZA+000a

22

nie_koniec:

mov

p1,a

BAZA+000b

f5 90

inc

r0

BAZA+000d

08

ajmp dalej

BAZA+000e

01 05

kom_end:

.equ 0

BAZA+0010

komunikat_1:

.db ’komunikat 1’,0ah,0dh,kom_end

BAZA+0010

6b 6f 6d

75 6e 69

itd. . .

Analizuj ˛

ac uzyskany program wynikowy mo˙zna stwierdzi ´c, ˙ze adres ka˙zdej komórki pami˛eci

daje si˛e wyrazi´c w postaci sumy dwóch składników: adresu bazowego (który tutaj symbolizuje
ogólnie nazwa

BAZA

) oraz cz˛e´sci stałej. Adres bazowy jest jednakowy dla wszystkich komórek

przechowuj ˛

acych kod wynikowy danego modułu programowego, przy czym ulega on zmianie

wraz ze zmian ˛

a poło˙zenia modułu w pami˛eci. Cz˛e´s´c stała adresu komórki nie zmienia si˛e nie-

zale˙znie od lokalizacji modułu bowiem wskazuje ona odległo´s´c od pocz ˛

atku modułu. Z powy˙z-

szego wynika, ˙ze operacje zwi ˛

azane z działaniem na adresach komórek przy zmianie poło˙zenia

modułu w pami˛eci s ˛

a proste – polegaj ˛

a na dodaniu do ka˙zdej warto ´sci stałej, zwi ˛

azanej nie-

rozł ˛

acznie z ka˙zdym kodem rozkazu uzyskanym po asemblacji, adresu bazowego okre ´slaj ˛

acego

aktualne poło˙zenie modułu w pami˛eci. Programista ma do dyspozycji szereg mo˙zliwo ´sci od-
działywania na adres bazowy modułu – zarówno przy u˙zyciu asemblera jak i w trakcie procesu
konsolidacji.

1.3.3

Atrybuty nazw w programach modułowych

W ka˙zdym programie wyst˛epuj ˛

a etykiety, czyli nazwy symblolizuj ˛

ace adresy okre ´slonych

miejsc w pami˛eci. W trakcie zmiany poło˙zenia modułu w pami˛eci musz ˛

a one podlega ´c takim

samym regułom przemieszczania jak inne adresy. Ponadto mo˙zna równie˙z definiowa ´c nazwy,
które zachowuj ˛

a stał ˛

a warto´s´c niezale˙znie od poło˙zenia modułu. Dla powy˙zszego przykładu

mo˙zna zestawi´c nast˛epuj ˛

ac ˛

a tablic˛e nazw:

Nazwa

Warto´s´c

Atrybyt absolutno´sci

pisz_kom1

BAZA+0000

0

dalej

BAZA+0005

0

nie_koniec

BAZA+000b

0

komunikat_1

BAZA+0010

0

kom_end

00

1

11

background image

1

Programowanie w j˛ezyku asembler

Nazwy, których warto´s´c zale˙zy od poło˙zenia modułu w pami˛eci nazywane s ˛

przesuwalnymi

(relokowalnymi), natomiast nazwy o stałych warto´sciach – absolutnymi. Ka˙zdej nazwie mo˙zna
przypisa´c atrybut absolutno´sci, który stanowi dla programu tłumacz ˛

acego wska´znik czy nale˙zy,

lub nie, modyfikowa´c nazw˛e przy zmianie poło˙zenia modułu.

1.3.4

Relokowalo ´s ´c modułów

Mo˙zna nakaza´c tłumaczenie fragmentów programu w sposób absolutny umieszczaj ˛

ac je

mi˛edzy dyrektywami:

.ABSOLUTE

,

.RELATIVE

.

Dyrektywa

.ABSOLUTE

powoduje przej´scie asemblera w tryb tłumaczenia absolutnego, co ozna-

cza, ˙ze wszystkie nazwy w tym trybie maj ˛

a atrybut absolutno´sci równy 1. Dyrektywa

.RELATIVE

przywraca tryb wzgl˛edny działania asemblera. Tryb ten jest zazwyczaj trybem domy ´slnym
asemblera o ile programista nie naka˙ze inaczej.

Tryb absolutny powinien by´c stosowany tylko w szczególnych przypadkach, poniewa˙z po-

ł ˛

aczenie modułów absolutnych z relokowalnymi mo˙ze prowadzi ´c do utworzenia niepoprawnych

sekwencji programowych. Poniewa˙z cz˛esto przyjmuje si˛e zasad˛e, ˙ze nie wyró˙znia si˛e w spe-
cjalny sposób modułów absolutnych, w zwi ˛

azku z czym s ˛

a one ł ˛

aczone z innymi modułami na

takich samych zasadach. Oznacza to, ˙ze w module absolutnym mog ˛

a ulega ´c przesuni˛eciu adresy

komórek pami˛eci natomiast nazwy definiowane w tym module pozostaj ˛

a stałe. Przykład:

adres

kod

.absolute

.org 20

petla:

nop

0020

00

ajmp petla

0021

01 20

Nazwa

PETLA

w tym przykładzie uzyskuje warto´s´c absolutn ˛

a

0020h

. Załó˙zmy, ˙ze ł ˛

aczy si˛e po-

wy˙zszy program z innymi, w efekcie czego program ten zostaje umieszczony od adresu

1000h

:

adres

kod

petla:

nop

1020

00

ajmp petla

1021

01 20

Zatem posta´c ko ´ncowa (wynikowa) tego fragmentu programu jest niepoprawna. Wynika st ˛

ad

wniosek, ˙ze za wyj ˛

atkiem szczególnych przypadków moduły programowe nale˙zy tłumaczy ´c

w sposób wzgl˛edny, a ich wła´sciw ˛

a lokalizacj˛e w pami˛eci okre´sla´c dopiero w trakcie konsolida-

cji.

Przykład ten ilustruje równie˙z specyfik˛e stosowania dyrektywy

.ORG

w modułach przesu-

walnych – wskazuje ona odległo´s´c miejsca w module programowym od pocz ˛

atku modułu wska-

zywanego przez adres bazowy. Standardowo przyjmuje si˛e w procesie asemblacji, ˙ze adres
bazowy ka˙zdego z modułów równa si˛e zera. W trakcie konsolidacji do tego adresu dodawany

12

background image

1.3

Tworzenie programów w postaci modułowej

jest adres przesuni˛ecia modułu (ang. offset), który jest dodawany do wszystkich adresów wska-
zywanych przez dyrektyw˛e

.ORG

. Powoduje to, ˙ze argument tej dyrektywy i przesuni˛ecie dodaj ˛

a

si˛e.

1.3.5

Współu˙zywanie nazw w modułach

Budowanie programu w postaci modułowej, a nast˛epnie ł ˛

aczenie modułów w jeden wspólny

program wymaga definiowania nazw wspólnych dla wielu modułów. Równie˙z w przypadku
doł ˛

aczania modułów bibliotecznych niezb˛edne jest u˙zycie nazw definiowanych przez moduły.

To wszystko powoduje, ˙ze w trakcie asemblacji w pewnych modułach pojawiaj ˛

a si˛e nazwy,

których warto´sci nie s ˛

a okre´slone w danym module.

Nazwa, która jest definowana w danym module i jest udost˛epniana równie˙z na zewn ˛

atrz

modułu, co oznacza ˙ze jest wa˙zna w całym programie, nazywana jest nazw ˛

a globaln ˛

a. Wskazy-

wanie nazw globalnych odbywa si˛e przy u˙zyciu dyrektywy:

.GLOBAL ci ˛

ag,nazw

Dyrektywa ta nadaje nazw ˛

atrybut globalno´sci.

Nazwy, które s ˛

a u˙zywane w danym module, przy zało˙zeniu, ˙ze s ˛

a definiowane w innym, na-

zywane s ˛

zewn˛etrznymi z punktu widzenia tego modułu. Nazwy takie wskazuje si˛e dyrektyw ˛

a:

.EXTERNAL ci ˛

ag,nazw

U˙zycie tej dyrektywy powoduje nadanie wskazanym nazw ˛

atrybutu zewn˛etrzno´sci.

Z powy˙zszych uwag wynika, ˙ze modułowe tworzenie programów wymaga wyposa˙zenia

nazw w trzy dodatkowe atrybuty: absolutno´sciglobalno´sci i zewn˛etrzno´sci. Atrybuty te s ˛

a

niezb˛edne w procesie konsolidacji do uzyskania kodu programu wynikowego i stwierdzenia
poprawno´sci wszystkich działa ´n składaj ˛

acych si˛e na ten proces.

Przykład ilustruj ˛

acy sposób posługiwania si˛e nazwami współu˙zywanymi w ró˙znych mody-

łach:

.module ;moduł 1

.global start

.external init

start: acall init

.endmod

.module ;moduł 2

.global init

init:

mov a,#10h

.

.

.

ret

.endmod

13

background image

1

Programowanie w j˛ezyku asembler

1.3.6

Doł ˛

aczanie modułu zawieraj ˛

acego kod ´zródłowy programu

Podstawowy moduł programowy ma posta´c pliku. Wyró˙znikiem pliku jest jego nazwa

(w przykadku modułów asemblerowych wymagane jest rozszerzenie

*.asm

). Ka˙zdy moduł jest

tłumaczony oddzielnie, w wyniku czego uzyskiwany jest plik z kodem przesuwalnym (

*.obj

)

nosz ˛

acy na ogół tak ˛

a sam ˛

a nazw˛e jak plik ´zródłowy. Pliki z kodem przesuwalnym poddawane s ˛

a

konsolidacji polegaj ˛

acej na zespoleniu odpowiednich fragmentów programu (sekcji) z ró˙znych

modułów i lokowanie ich w wybranych obszarach pami˛eci.

Istnieje sposób bardzo prosty cho´c znacznie mniej elestyczny od wy˙zej wymienionego słu-

˙z ˛

acy do ł ˛

aczenia modułów. Jest ono wówczas wykonywane na poziomie tekstu programu ´zró-

dłowego za pomoc ˛

a dyrektywy:

.INCLUDE nazwa_pliku.asm

1.4

Sekcje

1.4.1

Typy sekcji

Sekcja – wyró˙zniony fragment programu stanowi ˛

acy elementarn ˛

a cało ´s´c z punktu widze-

nia konsolidatora. Nadaje on sekcji jedno stałe przesuni˛ecie (ang. offset). Cz˛esto takie same
konstrukcje programowe jak sekcje nazywane s ˛

a w innych asemblerach segmantami, przy czym

na ogół sposób definiowania segmentów nie pozwala na tak du˙z ˛

a eleastyczno ´s´c struktury pro-

gramu jak to ma miejsce w przypadku sekcji. Opisany sposób definiowania sekcji zwi ˛

azany jest

ze specyficznymi cechami budowy mikrokontrolerów rodziny INTEL 8051. Mo˙zna wskaza ´c
dwa sposoby definiowania sekcji: przy u˙zyciu standardowych dyrektyw tybów sekcji oraz jako
sekcji u˙zytkowanika.

U˙zycie standardowych typów sekcji powoduje, ˙ze w trakcie konsolidacji s ˛

a one traktowane

priorytetowo w stosunku do sekcji definiowanych przez u˙zytkownika. Oznacza to, ˙ze s ˛

a one lo-

kowane jako pierwsze, przy czym priorytet lokowania samych sekcji standardowych jest zgodny
z zestawieniem.

.CODE

– sekcja z programem,

.DATA

– sekcja z danymi,

.RSECT

– sekcja rejestrowa,

.BSECT

– sekcja w pami˛eci bitowej.

Typ

.CODE

ma najwy˙zszy priorytet, a ponadto jest standardowym (domy´slnym) typem sekcji

– ka˙zdemu fragmentowi programu ´zródłowego o nieokre´slonym typie sekcji nadawany jest ten
typ.

14

background image

1.4

Sekcje

1.4.2

Składnia dyrektywy .SECTION

U˙zytkownik definiuje sekcje za pomoc ˛

a dyrektywy:

nazwa_sekcji: .SECTION argumenty_opcjonalne

Argumenty dyrektywy wskazuj ˛

a sposób lokowania sekcji w pami˛eci. Nazwa zdefiniowana przy

u˙zyciu dyrektywy

.SECTION

sama mo˙ze by´c u˙zywana jak dyrektywa, a konkretnie jako prze-

ł ˛

acznik sekcji. Przykład:

nop

;sekcja CODE

.DATA

;przeł ˛

acz na sekcj˛

e DATA

.ds 1

;bajt w sekcji DATA

SEKCJA_1 .SECTION

;definiuje i aktywizuje sekcj˛

e u˙

zytkownika

nop

;rozkaz w sekcji SEKCJA_1

.CODE

nop

;a ten w sekcji CODE

.SEKCJA_1 ;przeł ˛

acza na sekcje u˙

zytkownika

nop

;sekcja u˙

zytkownika mo˙

ze zawiera´

c rozkazy

.ds 1

;i dane

Powy˙zszy przykład pokazuje, ˙ze poszczególne fragmenty programu mo˙zna zestawia ´c w sekcje
w sposób praktycznie dowolny. Bior ˛

ac pod uwag˛e, ˙ze sekcje tego samego typu (w przypadku

sekcji u˙zytkownika oznacza to sekcje o tej samej nazwie) z ró˙znych modułów s ˛

a zespalane

w jedn ˛

a cało´s´c przez konsolidator daje to programi´scie elastyczne narz˛edzie tworzenia struk-

tur programowych dostasowanych zarówno do specyfiki budowy pami˛eci mikrokontrolera jak
i konstrukcji programu.

1.4.3

Sekcje rejestrowe i sekcje bitowe

Sekcje rejestrowe – konstrukcje obejmuj ˛

ace pojedyncze rejestry lub ich grupy. Definiowane

s ˛

a za pomoc ˛

a dyrektywy

.RSECT

lub przy u˙zyciu modyfikatora

REG

po dyrektywie

.SECTION

.

Jedyn ˛

a dyrektyw ˛

a, która mo˙ze wyst˛epowa ´c wewn ˛

atrz sekcji rejestrowej jest dyrektywa

.DS

.

Sposób tworzenia sekcji ilustruje przykład:

.RSECT

;przeł ˛

acza na sekcj˛

e rejestrow ˛

a

reg1:

.ds 1

sekcja_rej: .section reg ;definiuje rejestrow ˛

a sekcj˛

e u˙

zytkownika

reg2:

.ds 1

reg3:

.ds 1

Sekcje bitowe – umo˙zliwiaj ˛

a indywidualne adresowanie bitów. Mo˙zna utworzy ´c j ˛

a za po-

moc ˛

a standardowej dyrektywy

.BSECT

lub za pomoc ˛

a modyfikatora

BIT

. Wewn ˛

atrz sekcji bito-

wej mo˙zna u˙zywa´c jedynie dyrektywy

.DS

.

15

background image

1

Programowanie w j˛ezyku asembler

1.5

Lokowanie sekcji w pami ˛eci

1.5.1

Sposoby lokowania sekcji

Umieszczenie sekcji w okre´slonym miejscu pami˛eci polega na podaniu adresu sekcji, tj.

adresu pierwszej komórki pami˛eci zadeklarowanej jako pocz˛etek sekcji oraz ew. adresu ko ´nca
sekcji (chocia˙zby w celu unikni˛ecia braku pamieci – przepełnienia). Adres sekcji mo˙ze by ´c
wskazany w programie ´zródłowym jako argument dyrektywy

.SECTION

lub w trakcie konsoli-

dacji. Zalecany jest drugi sposób bo zapewnia znacznie wi˛eksz ˛

a elastyczno ´s´c procesu lokowa-

nia.

Mo˙zna wyró˙zni´c kilka rodzajów sekcji ze wzgl˛edu na ich sposób lokowania w pami˛eci.

Bior ˛

ac pod uwag˛e sposób wykorzystania celowe jest wyodr˛ebnienie trzech rodzajów sekcji:

sekcje bezpo´srednio lokowane w pami˛eci (ang. direct),

sekcje po´srednio lokowane w pami˛eci (ang. indirect),

sekcje referencyjne (ang. reference only).

Sekcja bezpo´srednia charakteryzuje si˛e tym, ˙ze jest u˙zywana w tym obszarze pami˛eci, w którym
została ulokowana w trakcie konsolidacji. Oznacza to, ˙ze kod wynikowy i wszystkie nazwy
zdefiniowane dla danej sekcji nie podlegaj ˛

a ˙zadnym zmianom w trakcie realizacji programu

u˙zytkowego.

Po´srednie lokowanie sekcji polega na tym, ˙ze sekcja po konsolidacji jest umieszczona w jed-

nym miejscu, a nast˛epnie po rozpocz˛eciu pracy programu zostaje przeniesiona w inne niejsce
gdzie jest u˙zytkowana. Oznacza to, ˙ze warto´sci wszystkich nazw definiowanych w danej sek-
cji s ˛

a wyznaczane nie dla miejsca umieszczenia jej po konsolidacji lecz zgodnie z lokalizacj ˛

a

sekcji w trakcie jej u˙zytkowania przez program (np. dla sekcji z danymi przemieszczenie jej
z pami˛eci programu ROM do pami˛eci danych RAM mo˙ze mie ´c na celu umo˙zliwienie jej aktu-
alizacji w trakcie realizacji programu).

Sekcja refernecyjna jest sekcj ˛

a pust ˛

tzn. w trakcie konsolidacji nie jest w niej lokowany

˙zaden kod wynikowy. Jest kreowana jedynie dla celów wyznaczania warto ´sci adresów niezb˛ed-

nych dla programu u˙zytkowego. (np. mo˙ze to by ´c tablica w pami˛eci danych, której adresy
s ˛

a wyznaczane w trakcie kosolidacji i przekazywane pod postaci ˛

a odpowiednich nazw do pro-

gramu u˙zytkowego w celu umo˙zliwienia działania na elementach tej tablicy.)

1.5.2

Zwi ˛

azki mi ˛edzy sekcjami

Sekcje po przeprowadzeniu konsolidacji mog ˛

a by ´c:

odseparowane tzn. lokowane w oddzielnych obszarach pami˛eci np. jako sekcje z danymi
i programem,

sklejone (ang. stacked),

nało˙zone na siebie (ang. common).

16

background image

1.5

Lokowanie sekcji w pami˛eci





















































Pamie˛c´

Sekcja 1

Sekcja 2

















































Pamie˛c´

Adres kon´ca sekcji 2

Adres pocz. sekcji 1

Sekcja 1

Sekcja 2

Adres kon´ca sekcji1 =
Adres pocz. sekcji 2

         

         

         

         

         

         

         

         

         

         

         

         

         

         

         

         

         

         

         

         

         

         

         

         

Pamie˛c´

Sekcja 1

Sekcja 2

Adres kon´ca sekcji 1

Adres kon´ca sekcji 2

Adres pocz. sekcji 1 =
Adres pocz. sekcji 2

odseparowane

sklejone

nało˙zone na siebie

Rysunek 1.3: Zwi ˛

azki mi˛edzy sekcjami

1.5.3

Sterowanie lokowaniem sekcji

Rozmieszczenie sekcji w pami˛eci mo˙ze by ´c sterowane z poziomu asemblera za pomoc ˛

a

argumentów dyretywy

.SECTION

:

OFFSET

Argument

OFFSET adres

powoduje bezpo´srednie umieszczenie sekcji pod wskaza-

nym adresem przy zało˙zeniu, ˙ze adres pocz ˛

atku sekcji wynosi zero. U˙zycie dyrek-

tywy:

sekcja1:

.section offset 100h

powoduje utworzenie sekcji o nazwie “

sekcja1

” i nakazuje ulokowanie jej w pa-

mi˛eci programu z przesuni˛eciem

100h

w stosunku do pocz ˛

atku sekcji okre ´slonego

dyrektyw ˛

a

.ORG

.

INDIRECT

Po´srednie lokowanie sekcji umo˙zliwia argument

INDIRECT addres

, gdzie

adres

wskazuje miejsce, do którego sekcja zostanie przeniesiona po rozpocz˛eciu pracy
programu. U˙zycie dyrektywy:

sekcja1:

.section offset 100h, indirect 200h

spowoduje fizyczne umieszcznie sekcji w pami˛eci programu ROM pocz ˛

awszy od

adresu

100h

, przy czym etykiety definiowane w tej sekcji uzyskuj ˛

a warto ´sci, jak

gdyby sekcja była lokowana od adresu

200h

. Po inicjacji program u˙zytkowy w pierw-

szej fazie działania przemieszcza sekcje z pami˛eci ROM do pami˛eci RAM pod adres

200h

i dysponuj ˛

ac warto´sciami adresów wła´sciwymi dla tego obszaru mo˙ze od tego

momentu u˙zywa´c przemieszczonej sekcji.

STACKED

Argument

STACKED

powoduje lokoawnie sekcji tu˙z nad sekcj ˛

a poprzedni ˛

a. Nazywa

si˛e to sklejaniem sekcji. Sekcja poprzednia musi by ´c zdefiniowana jako bezpo´sred-
nia. Np. zdefiniowanie sekcji w sposób jak ni˙zej:

sekcja1:

.section offset 100h

;sekcja bezpo´

srednia

a nast˛epnie:

sekcja2:

.section stacked

powoduje, ˙ze

sekcja2

jest lokowana tu˙z nad

sekcja1

.

17

background image

1

Programowanie w j˛ezyku asembler

AUTO_STACK

W praktyce cz˛esto jest stosowana technika polegaj ˛

aca na sklejaniu sekcji z frag-

mentów umieszczonych w ró˙znych plikach (modułach). Sklejanie takich fragmen-
tów umo˙zliwia argument

AUTO_STACK

. Nazwy sklejanych fragmentów definiowa-

nych równie˙z jako sekcje musz ˛

a by´c we wszystkich plikach jednakowe.

REF_ONLY

Wskazanie sekcji referencyjnej nast˛epuje za pomoc ˛

a argumentu

REF_ONLY

. U˙zycie

dyrektywy:

sekcja1:

.

section offset 100h, ref_only

spowoduje jedynie takie wyznaczenie adresów i nazw zwi ˛

azanych z

sekcja1

ja-

kie s ˛

a wła´sciwe w przypadku umieszczenia jej z przesuni˛eciem

100h

. Jednak bez

fizycznego umieszczania sekcji w tym obszarze.

RANGE

Ka˙zdej sekcji mo˙zna przypisa´c obszar umieszczenia za pomoc ˛

a parametrów:

RANGE adres1 adres2

COMMON

Sekcje o tej samej nazwie w ró˙znych plikach mog ˛

a by´c nakładane na siebie przy

u˙zyciu arguemntu

COMMON

. Jednak w trakcie deklaracji sekcji tego rodzaju w pierw-

szym pliku nie mo˙zna u˙zy´c argumentu

COMMON

. Sekcja w pozostałych plikach mu-

sz ˛

a by´c natomiast deklarowane z tym argumentem oraz musz ˛

a by´c typu referencyj-

nego, gdy˙z inaczej w pliku wynikowym pojawiłoby si˛e wiele rekordów z kodem
odnosz ˛

acym si˛e do tego obszaru adresowego.

1.5.4

Konsolidacja programu o strukturze sekcyjnej

Wskazywanie miejsca, gdzie wstawi´c sekcj˛e realizowane z poziomu asemblera ma ograni-

czone zastosowanie. Nie wszystkie działania mog ˛

a by ´c wykonane (np. te z doł ˛

aczaniem modu-

łów bibliotecznych), a ponadto ich elastyczno´s´c jest znacznie mniejsza od działa ´n realizowanych
przez konsolidator. A tak˙ze ka˙zda zmiana sposobu i miejsca lokowania sekcji zmusza do zmiany
programu ´zródłowego, który tym samym musi by ´c znów tłumaczony. Wła´snie dlatego zalecane
jest
, aby wszystkich manipulacji na sekcjach dokonywa ´c z poziomu konsolidatora (w trakcie
konsolidacji). Cz˛esto konsolidatory wyposa˙zone s ˛

a w ´srodki przeznaczone do tego celu.

Konsolidator pakietu 2500AD dysponuje specjalnym j˛ezykiem przeznaczonym do przekazy-

wania polece ´n konsolidacji w postaci pliku wsadowego. Nazwy polece ´n stanowi ˛

a słowa angiel-

skie dobrane tak, ˙ze ich zestawienia stanowi ˛

a pełny komentarz do działa ´n zleconych konsoli-

datorowi. Zatem analiza pliku wsadowego steruj ˛

acego procesem konsolidacji w takim trybie,

nazywanym rozszerzonym (ang. enhanced) pozwala na uzyskanie pełnego obrazu konsolidacji.
Zmiany tego procesu wymagaj ˛

a tylko poprawek w pliku wsadowym, co realizuje si˛e za pomoc ˛

a

prostego edytora tekstu.

Przykład 1:

Załó˙zmy, ˙ze konsolidowany jest pojedynczy plik ´zródłowy stanowi ˛

acy jedn ˛

a sek-

cj˛e. Zawiera dyrektyw˛e

ORIGIN

wskazuj ˛

ac ˛

a adres pocz ˛

atku programu. Plik wsadowy steruj ˛

acy

konsolidacj ˛

a program w trybie rozszerzonym ma posta ´c:

version v0.1.1

option: executable

18

background image

1.5

Lokowanie sekcji w pami˛eci

input: nazwa_pliku_wej´

sciowego

output: nazwa_pliku_wyj´

sciowego

locate: CODE at 0h

Poszczególne linie w tym przykładzie zawieraj ˛

a polecenia konsolidacji, przy czym

‘:

’ stanowi

separator oddzielaj ˛

acy nazw˛e polecenia od jego argumentu. Znaczenie poszczególnych linii:

1. Słowo kluczowe

version

wskazuje, ˙ze dany plik zawiera polecenia w trybie rozszerzo-

nym. Jest to niezb˛edne, bo stosowany jest tak˙ze standardowy tryb wsadowy, w którym
polecenia maj ˛

a inn ˛

a posta´c.

2. Słowo

option

wskazuje rodzaj pliku wyj´sciowego:

executable

– plik z kodem binarnym,

intel hex

– plik z kodem w standardzie HEX Intela,

high level

– nakazuje utworzenie dodatkowego pliku wyj´sciowego z danymi nie-

zb˛ednymi w trakcie uruchamiania programu przy u˙zyciu symulatora,

load map

.

3. Argumentem polecenia

input

jest nazwa pliku wej´sciowego poddawanego konsolidacji.

4. Polecenie

output

zawiera nazw˛e pliku wyj´sciowego, którego rodzaj okre´slaj ˛

a argumenty

polecenia

option

5. Polecenie

locate

wskazuje adres umieszczenia poszczególnych sekcji. Interpretowane

jest jako dodatkowe przesuni˛ecie w stosunku do adresu pocz ˛

atku programu okre ´slonego

dyrektyw ˛

a

ORIGIN.

Przykład 2:

Dla zało˙ze ´n jak w poprzednim przykładzie nale˙zy zbudowa ´c plik wsadowy taki,

aby mo˙zna było przył ˛

aczy´c moduły biblioteczne, a plik wyj´sciowy był w standardzie

intel

hex

, a zarazem aby został utworzony plik uruchomieniowy za pomoc ˛

a symulatora. Plik konso-

lidacji ma wówczas posta´c:

version

option: loca map, intel hex

input: nazwa_pliku_wej´

sciowego

output: nazwa_pliku_wyj´

sciowego

library: nazwa_pliku bibliotecznego

locate: CODE at 0h

19

background image

1

Programowanie w j˛ezyku asembler

20

background image

2 Programowanie w C

µ

K rodziny Intel 8051

2.1

Proces uzyskiwania programu wynikowego dla programów w C

Pliki doła˛czene przez

uz˙ytkownika

w C

Plik z´ródłowy

Standardowe pliki nagłówkowe doła˛czane

na poziomie je˛zyka C (*.h)

Pliki doła˛czene przez

uz˙ytkownika

uz˙ytkownika

biblioteczne

Programy

Standardowe

programy

biblioteczne

Kompilator

asemblerowy

Plik z´ródłowy

programu rozruch.

Asembler

s´rodowisko (*.def)

Pliki definiuja˛ce 

Pliki

relokowalne

rozruchowy

Konsolidator

Plik

Program

Bibliotekarz

Raport z kompilacji

(*.lst)

Pliki z kodem wynikowym

(*.hex, *.exe, *.sym, *.def)

programu (*.map)

Plik z mapa˛ pamie˛ci

Rysunek 2.1: Proces uzyskiwania programu wynikowego dla programów w C

Doprowadzenie programu napisanego w C do realizacji przez mikrokontroler (lub jego sy-

mulator) jest procesem wieloetapowym. Mo˙zna wyró˙zni ´c w nim conajmniej pi˛e´c niezb˛ednych
kroków:

napisanie w j˛ezyku asembler programu rozruchowego,

przetłumaczenie programu rozruchowego,

21

background image

2

Programowanie w C µK rodziny Intel 8051

kompilacja programu w C do postaci asemblerowej, a nast˛epnie przetłumaczenie go do
postaci relokowalnej,

wskazanie standardowych plików bibliotecznych doł ˛

aczanych w trakcie konsolidacji,

konsolidacja programu rozruchowego, programu w C oraz programów bibliotecznych
w wymienionej kolejno´sci.

Programy w j˛ezyku C wymagaj ˛

a przygotowania ´srodowiska, w którym s ˛

a realizowane. Polega

to ogólnie na zarezerwowaniu miejsca w pami˛eci dla okre´slonego rodzaju danych, zainicjowa-
nia układów wej´scia-wyj´scia do komunikacji z otoczeniem, przygotowania stosu a nast˛epnie na
oddaniu sterowania do programu w C, który standardowo rozpoczyna si˛e od funkcji

main()

.

Powy˙zsze działania realizuje program rozruchowy (ang. runtime start up program), który jest
napisany w j˛ezyku asembler. Jest on zwykle dostarczany przez producenta kompilatora, mo˙ze
by´c równie˙z zbudowany przez u˙zytkownika. Jest on dostosowywany do ró˙znych typów mi-
krokontrolerów rodziny 8051 za pomoc ˛

a plików definiuj ˛

acych struktur˛e rejestrów. Maj ˛

a one

rozszerzenie

*.def

i doł ˛

aczane s ˛

a za pomoc ˛

a dyrektywy

include

. U˙zytkownik mo˙ze modyfi-

kowa´c te pliki, mo˙ze równie˙z tworzy´c własne pliki definicyjne.

Programy w C równie˙z wymagaj ˛

a doł ˛

aczenia plików definicyjnych, które maj ˛

a jednak nieco

inny charakter. S ˛

a to tzw. pliki nagłówkowe

1

słu˙z ˛

ace do tworzenia prototypów funkcji biblio-

tecznych. Ich brak uniemo˙zliwia działanie tych funkcji. U˙zytkownik mo˙ze doł ˛

acza ´c równie˙z

własne pliki nagłówkowe.

Tłumaczenie programu w C odbywa si˛e dwuetapowo. Najpierw program w C tłumaczony

jest na program w asemblerze, a nast˛epnie program asemblerowy tłumaczony jest do postaci
relokowalnej. U˙zywaj ˛

ac odpowiedniego przeł ˛

acznika kompilatora powy˙zsze etapy mo˙zna zre-

alizowa´c jako jedn ˛

a cało´s´c.

Postacie relokowalne programu w C i programu rozruchowego s ˛

a poddane nast˛epnie kon-

solidacji ł ˛

acznie z programami bibliotecznymi. Tego rodzaju programy s ˛

a dostarczane przez

producenta. Mo˙zna równie˙z tworzy´c własne programy biblioteczne. U˙zytkownik mo˙ze doł ˛

a-

cza´c własne programy relokowalne do standardowej biblioteki za pomoc ˛

a programu o nazwie

librarian

2

. Wynikiem konsolidacji jest plik wykonywalny

*.exe

lub cz˛e´sciej jego posta´c he-

xadecymalna

*.hex

. Mo˙zna równie˙z uzyska´c pliki

*.sym

i

*.def

niezb˛edne gdy u˙zywa si˛e

symulatora. Ponadto programista mo˙ze za˙zyczy ´c sobie utworzenia raportu z kompilacji

*.lst

oraz pliku z map ˛

a programu

*.map

zawieraj ˛

acego dane na temat obszarów pami˛eci zajmowa-

nych przez sekcje oraz warto´sci nazw globalnych.

2.2

Program rozruchowy

2.2.1

Rodzaje programu rozruchowego

Program ten napisany jest w asemblerze i spełnia nast˛epuj ˛

ace zadania:

przygotowanie stosu i wywołanie pocz ˛

atkowej funkcji C (

main()

),

1

ang. header files

2

bibliotekarz

22

background image

2.2

Program rozruchowy

zapewnienie komunikacji mi˛edzy fizycznym urz ˛

adzeniem wej´scia-wyj´scia (lub systemem

operacyjnym) a programem w C,

zarezerwowanie obszarów na dane,

przeniesienie danych z pami˛eci programu do pami˛eci danych.

Pakiet 2500AD dostarcza trzy rodzaje programów rozruchowych:

przeznaczonych do zastosowanie w sytuacji gdy do przechowywania danych u˙zywa si˛e
wył ˛

acznie wewn˛etrznej pami˛eci RAM. Jest to tzw. tryb wewn˛etrzny kompilatora (ang.

internal memory mode). Program rozruchowy nosi nazw˛e

c8051ir.src

. W przypadku

gdy u˙zywa si˛e symulatora nale˙zy zastosowa ´c wersj˛e

c851sir.src

.

przeznaczonych do u˙zytku wył ˛

acznie z zewn˛etrzn ˛

a pami˛eci ˛

a RAM jako miejsca przecho-

wywania danych programu w C, co nazywane jest trybem zewn˛etrznym (ang. external
memory mode
). Stosowane s ˛

a wtedy odpowiednio programy rozruchowe:

c8051er.src

i

c8051ser.src

.

przeznaczonych do ł ˛

acznego wykorzystania obu rodzajów pami˛eci RAM. Jest to tzw. tryb

mieszany (ang. mixed memory mode):

c8051mr.src

i

c8051smr.src

.

Podj˛ecie decyzji co do rodzaju pami˛eci RAM, a wi˛ec i trybu kompilacji programu, wi ˛

a˙ze si˛e nie

tylko z wyborem rodzaju programu rozruchowego, ale równie˙z mi˛edzy innymi z wykorzysta-
niem odpowiednich programów bibliotecznych, sposobem definiowania zmiennych globalnych
itd. . . .

2.2.2

Definiowanie rodzaju mikrokontrolera

Rodzina 8051 obejmuje kilkadziesi ˛

at typów mikrokontrolerów. Program jest natomiast pi-

sany dla konkretnego typu, co oznacza, ˙ze u˙zywa on nazw rejestrów specjalnych odpowiednich
dla danego typu. Nazwy te s ˛

a u˙zywane zarówno na poziomie asemblera jak i j˛ezyka C. Nazwy

rejestrów specjalnych u˙zywane na tych poziomach s ˛

a ró˙zne. Oznacza to konieczno ´s´c realizacji

nast˛epuj ˛

acych działa ´n:

Na pocz ˛

atku programu rozruchowego nale˙zy u˙zy ´c dyrektywy

.CHIP

z argumentem okre-

´slaj ˛

acym typ mikrokontrolera (np.

.chip 8052

). Powoduje to doł ˛

aczenie do słownika

nazw asemblera całej grupy nazw rejestrów specjalnych i nazw bitów specyficznych dla
wskazanego typu mikrokontrolera. Od tego momentu nazwom tym zostaj ˛

a przypisane

warto´sci odpowiadaj ˛

ace adresom rejestrów i bitów, które nie mog ˛

a by ´c redefiniowane.

Umo˙zliwia to wskazanie tych nazw przez programist˛e bez konieczno ´sci odwoływanie si˛e
do adresów zwi ˛

azanych z tymi nazwami.

Na pocz ˛

atku sekcji

program

programu rozruchowego nale˙zy doł ˛

aczy ´c plik

c????sr.def

zawieraj ˛

acy globalne definicje nazw rejestrów specjalnych.

23

background image

2

Programowanie w C µK rodziny Intel 8051

Tak zdefiniowane nazwy poprzedzone doln ˛

a kresk ˛

a

3

(

_

) mog ˛

a by´c u˙zywane we wszystkich mo-

dułach pod warunkiem zdefiniowania ich jako zewn˛etrzne dla tych modułów. Dla programu
w C realizowane jest to za pomoc ˛

a makropolecenia doł ˛

aczaj ˛

acego plik nagłówkowy:

#include "c8052sr.h"

Zawarto ´s ´c plików definicyjnych

Plik

c8052sr.def

ma posta´c:

***********************************************************

* 8052 C compiler special functions registers definitions *

***********************************************************

spec_func_regs: .section reg,offset 0,ref_only

.globals on

_P0;

.reg 80h

_PCON:

.reg 77h

.

.

.

_SFB:

.reg 80h

.globals off

.ends

Plik nagłówkowy programu w C o nazwie

c8052sr.h

ma posta ´c:

/************************************************************/

/* 8052 C compiler special functions registers declarations */

/************************************************************/

.asm

.chip 8052

.endasm

extern near char P0; /* port 0 */

.

.

.

extern near char PCON; /* power control */

.

.

.

extern near char IE; /* interrupt enable control */

/*******************************************************/

/* 8052 C compiler special functions bits declarations */

/*******************************************************/

near struct special_finction bits

{

/* Bit name

Bit value */

3

normalnie nazywn ˛

a podkre´sleniem

24

background image

2.2

Program rozruchowy

/* P0 (Port 0) */

unsigned int P0_0:1 ; /* port 0, bit 0

80h*/

.

.

.

unsigned int P0_0:1;

/* port 0, bit 7

87h*/

/* TCON (Timer Control) */

unsigned int IT0:1; /*input INT0/transition activated 88h */

.

.

.

}

Doł ˛

aczenie tego pliku nagłówkowego umo˙zliwia w programach w C u˙zywanie nazw zdefinio-

wanych rejestrów i bitów jako zmiennych. Ilustruj ˛

a to przykłady:

#include “c8052sr.h”

near char c1;

main()

{

char c2;

c1=P0;

c2=P1;

P2=c2;

.local c2

.asm

mov .low. _c1,p0

mov _c2,p1

.endasm

}

Powy˙zszy program po kompilacji b˛edzie wygl ˛

adał tak:

;.asm

.chip 8052

;.endams

;char c1;

.internal_uninit_data

_c1: .ds 1

;

.program

_main: .equal $

;

?ASC0: .equal 0

?TSC0: .equal 0

?LSC0: .equal 1

inc sp

;c1=P0

mov a,.low. _P0

mov .low. _c1, a

25

background image

2

Programowanie w C µK rodziny Intel 8051

;c1=P1

mov a,.low. _P1

xch a,r0

mov a,sp

add a,#0-?LSC0-1

xch a,r0

mov @r0,a

;P2=c2

mov .low. _P2,a

;local c2

c2: .var+0-?LSC0+1

;asm

mov .low. _c1,p0

mov _c2,p1

;endasm

Komunikacje z bitami rejestrów specjalnych w programie w C. Program ten deklaruje rejestry
adresowane bitowo jako struktur˛e bitow ˛

a. Program w C:

#include “c8052sr.h”

extern struct special_functions_bits _SFB;

char c1;

main()

{

_SFB.EA=1;

}

po kompilacji:

;_SFB.EA=1

setb .low. __SFB+47

;

2.2.3

Deklaracja rejestrów roboczych

Kompilator C wykorzystuje wszystkie rejestry robocze r0 . . . r7 mikrokontrolera, niezb˛edne

jest wi˛ec ich zdefiniowanie w programie rozruchowym w sposób wła´sciwy dla kompilatora.
Najlepiej zrobi´c to w postaci sekcji rejestrowej. Jej parametry mo˙zna zadeklarowa ´c na poziomie
asemblera, bo nie ulegaj ˛

a one zmianie w trakcie konsolidacji. Realizowane to jest nast˛epuj ˛

aco:

registers:

.section reg, offset 0, ref_only

.global __reg0

.global __reg1

.

.

.

.global __reg7

26

background image

2.2

Program rozruchowy

__reg0:

.ds 1

.

.

.

__reg7:

.ds 1

__oper1_lsb: .equal __reg0

__oper1_msb: .equal __reg2 ;adres operandu 1

.

.

.

__stack_msb: .equal __reg7

2.2.4

Przesuwanie danych

Kompilator u˙zywa czterech rodzajów sekcji wraz z trzema odpowiadaj ˛

acymi im sekcjami

bibliotecznymi. Sekcje te nosz ˛

a ró˙zne nazwy dla trybu wewn˛etrznego i zewn˛etrznego kompila-

tora.

Rodzaj sekcji

Sekcje biblioteczna

Tryb zewn˛etrzny

program

lib_program

const_data

lib_const_data

init_data

lib_init_data

uninit_data

-

Tryb wewn˛etrzny

program

lib_program

internal_const_data

lib_internal_const_data

internal_init_data

lib_internal_init_data

internal_uninit_data

-

Pierwszy rodzaj sekcji zawiera programy u˙zytkownika i programy biblioteczne. Pozostałe

trzy rodzaje sekcji u˙zywane przez kompilator słu˙z ˛

a do lokowanie danych podzielonych na 3 klasy:

dane nieinicjowane, dla których w wyniku deklaracji typu musi by ´c zarezerwowane miej-
sce w pami˛eci, jednak w rezerwowany obszar nie s ˛

a wpisywane ˙zadne warto ´sci

dane inicjowane, którym prócz zadeklarowania typu przypisywana jest warto ´s´c. Obydwa
powy˙zsze typy zwi ˛

azane s ˛

z deklaracjami zmiennych.

trzeci typ danych zwi ˛

azany jest ze stałymi u˙zywanymi w programie. Stałe nie zmieniaj ˛

a

warto´sci przez cały czas działania programu. Okre´slony symbol mo˙zna zadeklarowa´c jako
stał ˛

a u˙zywaj ˛

ac do tego celu słowa kluczowego

const

.

Przykład:

char c1;

char c2=0;

const char c3=3;

main(){}

27

background image

2

Programowanie w C µK rodziny Intel 8051

po kompilacji:

;char c1

.internal_uninit_data

_c1: ds 1

;char c2=0;

.internal_init_data

_c2: .byte 0

;const char c3=3;

.internal_const_data

_c3: .byte 3

Utworzenie w/w klas sekcji pozwala na umieszczenie modułów bibliotecznych w okre ´slonych
obszarach pami˛eci. S ˛

a one lokowane zgodnie z parametrami podanymi w pliku konsolidacji

(

*.lnk

). Program rozruchowy musi zdefiniowa´c wszystkie niezb˛edne sekcje, nawet je´sli s ˛

a

puste. Przyj˛ecie okre´slonego porz ˛

adku pozwala konsolidatorowi na wyznaczanie rozmiarów

sekcji, co jest niezb˛edne do przemieszczania odpowiednich sekcji przez program rozruchowy
oraz ewentualne zerowanie odpowiednich sekcji.

W funkcjach j˛ezyka C mog ˛

a wyst˛epowa´c dane tymczasowe, które spełniaj ˛

a wewn ˛

atrz funk-

cji zadania pomocnicze. Moduły biblioteczne przechowuj ˛

a ich warto ´sci na stosie. Lokalizacja

ka˙zdej zmiennej wskazywana jest jako przesuni˛ecie w stosunku do zawarto ´sci wska´znika chwi-
lowych zmiennych bibliotecznych
:

__ilib_temp_ptr

(dla trybu wewn˛etrznego). Wyznaczanie

lokalizacji dokonywane jest w trakcie kompilacji i wymaga zdefiniowania odpowiednich sek-
cji. Te sekcje nie mog ˛

a by przemieszczane wi˛ec ich parametry s ˛

a definiowane na poziomie

asemblera.

2.2.5

Przygotowanie stosu

Stos wewn˛etrzny umieszczany jest ponad obszarem wewn˛etrznych danych nieinicjowanych.

Niezb˛ednym elementem zwi ˛

azanym z tym obszarem jest wska´znik

__ilib_temp_ptr

słu˙z ˛

acy

do poruszania si˛e po zarezerwowanym obszarze pami˛eci, który programy biblioteczne u˙zywaj ˛

a

do przechowywania wyników. Mo˙zliwe jest wielokrotne wywoływanie podprogramów biblio-
tecznych realizowane w trzech krokach:

1. Lokalizacja kolejnego bloku danych w obszarze stosu o rozmiarze

__lib_temp_constants_size

.

2. Przechowanie warto´sci bie˙z ˛

acego wska´znika w

__ilib_temp_ptr

.

3. Wprowadzenie nowej warto´sci wska´znika i wywołanie programu bibliotecznego.

2.2.6

Wywołanie programu w C

Wywołanie programu w C z poziomu programu rozruchowego realizowane jest rozkazem

LCALL_MAIN

. Mo˙zna te˙z stosowa´c rozkaz skoku gdy nie przewiduje si˛e powrotu po zrealizo-

waniu programu w C. Gdy taki powrót ma miejsce (np. gdy wywołanie nast ˛

apiło z programu

28

background image

2.3

Organizacja danych w C

internal_init_data

internal_lib_init_data

__ilib_temp_ptr

internal_uninit_data

internal_lib_temp_constants

Bank 3

Bank 2

Bank 1

Bank 0

Bity stanu

30h

7Fh

00h

Rysunek 2.2: Struktura wewn˛etrznej pami˛eci RAM po zainicjowaniu stosu

monitora lub systemu operacyjnego) nale˙zy zapewni ´c przywrócenie warto´sci wska´znika stosu
jaka była przed wywołaniem programu w C.

2.3

Organizacja danych w C

2.3.1

Typy danych i ich modyfikatory

Kompilator 2500AD operuje na nast˛epuj ˛

acych typach danych:

Nazwa

Typ

Rozmiar

znakowy

char

8 bitów

całkowity

int

16 bitów

całkowity krótki

short

8 bitów

całkowity długi

long

32 bity

zmiennoprzecinkowy

float

32 bity (IEEE)

zmiennoprzecinkowy podwójnej precyzji

double

64 bity (IEEE)

Stosowane s ˛

a nast˛epuj ˛

ace kwalifikatory:

Kwalifikator

Stosowany do typu

unsigned

char, int, long

const

do wszystkich wł ˛

aczaj ˛

ac struktury

volatile

do wszystkich wł ˛

aczaj ˛

ac struktury

Znaczenie kwalifikatorów:

unsigned

liczba całkowita nieujemna. W stosunku do takich liczb obowi ˛

azuj ˛

a reguły arytme-

29

background image

2

Programowanie w C µK rodziny Intel 8051

tyki binarnej.

const

słu˙zy do wskazywania stałych, które nie podlegaj ˛

a zmianom w czasie realizacji

całego programu. Kompilator generuje kod pozwalaj ˛

acy na przekazywanie tych

danych do procesora. Zmienne wska´znikowe o warto´sciach b˛ed ˛

acych adresami do

tych stałych maj ˛

a długo´s´c 16 bitów.

volatile

wskazuje, ˙ze okre´slone dane musz ˛

a by´c ponownie ładowane przy ka˙zdym ich u˙zy-

ciu poniewa˙z s ˛

a modyfikowane w trakcie realizacji programu. Tego typu kwalifika-

tor jest u˙zyteczny przy obsłudze układów I/O adresowanych jednolicie z pami˛eci ˛

a.

Uwaga:

Standard j˛ezyka C wymaga oby argumenty operacji 2-argumentowej typy char były

najpierw przetworzone na posta´c int. Opisywany kompilator nie przestrzega tego wychodz ˛

ac

z zało˙zenia, ˙ze mikrokontorlery rodziny 8051 znacznie cz˛e´sciej wykonuj ˛

a operacje na liczbach

8-bitowych typu char ni˙z na 16bitowych typu int. Dlatego trzeba kontrolowa ´c efekty stosowa-
nych operacji. Ilustruje to przykład:

char c1,c2;

int i;

i=c1<<8; /* przesu´

n w lewo 8 pozycji */

Rezultat tej operacji wynosi 0 poniewa˙z wszystkie bity zostały przesuni˛ete przed przechowa-
niem wyniku w postaci zmiennej

i

. Aby uzyska ´c poprawny wynik przed przesuni˛eciem nale˙zy

dokona´c konwersji zmiennej

c1

na typ int:

i=(int)c1<<8;

2.3.2

Organizacja ramki stosu

Ka˙zdej funkcji kompilowanej w trybie wewn˛etrznym przydzielany jest fragment pami˛eci

zorganizowany w stos nazywany ramk ˛

(rys. 2.3). Składa si˛e ona z trzech obszarów:

1. pami˛eci argumentów funkcji,

2. pami˛eci danych tymczasowych,

3. pami˛eci zmiennych lokalnych.

Kompilator dla ka˙zdej funkcji generuje trzy stałe procesu kompilacji, które stanowi ˛

a rozmiary

danych w ramce stosu:

?LSC

rozmiar danych lokalnych

?TSC

rozmiar danych tymczasowych

?ASC

rozmiar argumentów przekazywanych bezpo´srednio na stos

30

background image

2.3

Organizacja danych w C





Dane tymczasowe

Argumenty

Argumenty

Zmienne lokalne

SP po wywołaniu

funkcji

SP przed wywołaniem

funkcji

?ASC - rozmiar obszaru argumentow przekazy-

wanych bezpos´rednio przez stos

SP-?LSC

SP-?LSC+1-TSC

Argumenty przekazywane przez rejestry

?TSC - rozmiar danych tymczasowych

?LSC - rozmiar zmiennych lokalnych

Adres powrotu z funkcji (2 bajty)

Rysunek 2.3: Ramka stosu

Rozmiary te maj ˛

a warto´sci równe liczbie bajtów zarezerwowanych w ramce na dany rodzaj wiel-

ko´sci. Słu˙z ˛

a one do okre´slania wzgl˛ednych adresów bazowych obszarów ramki, które z kolei

stanowi ˛

a podstaw˛e wyznaczania poło˙zenia danych w ramce. Okre´slone s ˛

a nast˛epuj ˛

ace adresy

bazowe:

adres wzgl˛edny pocz ˛

atku obszaru zmiennych lokalnych (

-?LSC+1

) wskazuj ˛

acy poło˙zenie

najstarszego bajtu pierwszej zmiennej lokalnej wzgl˛edem aktualnej zawarto ´sci wska´znika
stosu

adres wzgl˛edny pocz ˛

atku obszaru danych tymczasowych (

-?LSC

)

adres wzgl˛edny ko ´nca obszaru danych tymczasowych (

-?LSC-?TSC

), który słu˙zy jako

adres bazowy obszaru argumentów funkcji

Powy˙zsze adresy bazowe umo˙zliwiaj ˛

a lokalizacj˛e danych w ramce na podstawie ich adresów

wzgl˛ednych b˛ed ˛

acych liczbami wskazuj ˛

acymi odległo´s´c w bajtach najstarszego bajtu danych

od adresu bazowego.

2.3.3

Przekazywanie argumentów do funkcji

Tłumacz ˛

ac funkcj˛e j˛ezyka C kompilator standardowo lokuje ich argumenty typu char i int

w rejestrach roboczych. W momencie gdy kompilator przetłumaczy wywołanie funkcji rozpo-
czyna poszukiwanie miejsca dla przechowania pierwszego argumentu. Je ´sli jest on typu char/int
i jest miejsce w rejestrach to jest on tam umieszczany. W przeciwnym przypadku argument jest
lokowany na stosie. Czynno´s´c ta powtarzana jest do wyczerpania listy argumentów. Kompilator

31

background image

2

Programowanie w C µK rodziny Intel 8051

u˙zywa rejestrów A, R1, R2, R3

4

do przechowywania argumentów typu char, oraz par R2+R0,

R3+R1 dla typu int. Przykłady:

funkcja1(char arg1, char arg2)

– pierwszy argument umieszczony jest w A, drugi w R2

funkcja2(char arg1, int arg2)

– pierwszy argument w A, drugi w R3+R1

funkcja3(int arg1, char arg2)

– pierwszy argument w parze R2+R0, drugi w R1

funkcja4(int arg1, int arg2)

– pierwszy w R2+R0, drugi R3+R1

Po przej´sciu do realizacji funkcji w pierwszym kroku wysyłane s ˛

a na stos argumenty przekazy-

wane w rejestrach. Po ich wysłaniu obszar ramki stosu przeznaczony na argumenty zawiera je
kolejno´sci odwrotnej do kolejno´sci ich deklaracji. Pokazano to na rys. 2.4 dla przykładowej
funkcji:

f_przykl_1 (char, int, float)

Pamie˛c´ danych
tymczasowych

char

int

int

float

float

float

float

bity 0..7

bity 0..7

bity 8..15

bity 0..7

bity 8..15

bity 16..23

bity 24..31

Ostatni argument

Pierwszy argument

Rysunek 2.4: Kolejno´s´c argumentów funkcji w ramce stosu

Przekazanie argumentów na stos odbywa si˛e dwuetapowo:

1. Przed wywołaniem funkcji – pocz ˛

atkowe argumenty s ˛

a ładowane do rejestrów roboczych,

reszta na stos.

2. Po wywołaniu funkcji – argumenty z rejestrów przenoszone s ˛

a na stos.

Mi˛edzy tymi działaniami ma miejsce operacja zwi ˛

azana z wywołaniem podprogramu realizuj ˛

a-

cego dan ˛

a funkcj˛e. Dlatego obszar stosu wewn˛etrznego przeznaczonego na argumenty zostaje

przedzielony na dwie cz˛e´sci dwubajtowym adresem powrotu z podprogramu.

4

W tej kolejco´sci.

32

background image

2.3

Organizacja danych w C

Przykład:

main()

{

f_przykl_2(1,2,3);

}

f_przykl_2(int x, int y, int z)

{

int a,b,s;

a=4;

b=5;

s=0;

s=s+z;

s=s+y;

return(s);

}

Odwołanie si˛e do funkcji

f_przykl_2

wymaga przekazania do niej trzech argumentów. Argu-

menty pierwszy i drugi lokowane s ˛

a w parach rejestrów R2 i R0 oraz R3 i R1, trzeci argument

lokowany jest na stosie. Po kompilacji odpowiednie instrukcje asemblera maj ˛

a posta ´c:

;f_przykl_2(1,2,3)

mov

r0,#.low. 3

mov

r2,#.high. 3

push

_oper1_msb

push

_oper2_lsb

mov

r1,#.low. 2

mov

r3,#.high. 2

mov

r0,#.low. 1

mov

r0,#.high. 1

lcall _f_przykl_2

dec

sp

dec

sp

?BOF0:

.equal $

ret

_f_przykl_2: .equal $

push

_oper2_msb

push

_oper2_lsb

push

_oper1_msb

push

_oper1_lsb

Po wywołaniu podprogramu funkcji argumenty z rejestrów przenoszone s ˛

a na stos. Po zako ´n-

czeniu tej operacji ramka stosu ma posta´c przedstawian ˛

a na rys. 2.5.

2.3.4

Rozmieszczenie zmiennych lokalnych w ramce stosu

Zmienne lokalne umieszczane s ˛

a na stosie w kolejno´sci ich definiowania zaczynaj ˛

ac od naj-

starszego bajtu. Dla funkcji z przykładu ze strony 33 map˛e pami˛eci zmiennych lokalnych przed-
stawia rysunek 2.6.

33

background image

2

Programowanie w C µK rodziny Intel 8051

.low. 1

.low. 2

tymczasowych

Pamie˛c´ danych

Zmienne lokalne

.high. 1

.high. 2

adres

powrotu

.low. 3

.high. 3

Rysunek 2.5: Ramka stosu dla przykładu ze strony 33

.low. 0

Pamie˛c´ danych

tymczasowych

.high. 4

.high. 5

.low. 4

.low. 5

.high. 0

Rysunek 2.6: Mapa pami˛eci zmiennych lokalnych

34

background image

2.3

Organizacja danych w C

Rozmieszczenie zmiennych lokalnych musi by ´c poprzedzone zarezerwowaniem obszaru

stosu na dane tymczasowe i zmienne lokale. Odpowiedni fragment programu po kompilacji
ma posta´c:

?ASC1: .equal 2

?TSC1: .equal 0

?LSC1: .equal 6

mov a,sp

add a,#?TSC1+?LSC1

mov sp,a

;po tej operacji wska´

znik stosu wskazuje koniec ramki stosu

Mechanizm lokowanie zmiennych ilustruje poni˙zszy kod:

;a=4

mov a,sp

add a#0-?LSC1+1

mov r0,a

mov @r0,#.high. 4

inc r0

mov @r0,#.low. 4

;b=5

mov a,sp

add a,#2-?LSC1+1

mov r0,a

.

.

.

;s=0

.

.

.

Po zako ´nczeniu lokowania zmiennych lokalnych ramka stosu dla przykładu ze strony 33 przed-
stawion ˛

a na rysunku 2.7. W tej formie jest ona wykorzystywana przez cały czas realizacji pod-

programu funkcji.

Obszar zmiennych tymczasowych jest wykorzystywany w taki sam sposób jak obszar zmien-

nych lokalnych w miar˛e pojawiania si˛e danych wykorzystywanych chwilowo dla celów przecho-
wania wyników po´srednich.

Powrót z podprogramu funkcji wymaga ustawienia wska´znika stosu SP. Realizuj ˛

a to instruk-

cje:

;return(s)

?BOF1: .equal $

mov a,sp

add a,#-?LSC1-?TSC1-4

mov sp,a

ret

35

background image

2

Programowanie w C µK rodziny Intel 8051

.low. 0

Pamie˛c´ danych

tymczasowych

.high. 4

.high. 5

.low. 4

.low. 5

.high. 0

.low. 1

.high. 1

.low. 2

.high. 2

adres

powrotu

.low. 3

.high. 3

Rysunek 2.7: Mapa ramki stosu funkcji z przykłady ze strony 33

2.3.5

Przechowywanie warto ´sci zwracanych przez funkcj ˛e

Zmienna zwracana przez funkcj˛e okre´slona jest jako argument instrukcji

return

. Typ zwra-

canej warto´sci musi by´c wskazany przez podanie typu funkcji przed jej nazw ˛

a. Pomini˛ecie tej

deklaracji oznacza funkcj˛e etapu int (czyli zwracaj ˛

ac ˛

a warto´s´c całkowit ˛

a). Sposób zwracania

warto´sci funkcji okre´sla tablica:

Typ zwracanej warto´sci

Zwracana w:

wszystkie funkcje:

char

A

int

R2,R0

funkcje zewn˛etrzne (korzystaj ˛

ace z zewn˛etrznej pami˛eci RAM):

long, float, double

lokacja w pami˛eci tymczasowej:

__FUNCTION_RET_ADDR

wska´znik do lokacji w R2 i R0

funkcje wewn˛etrzne:

long, float, double

lokacja w pami˛eci tymczasowej:

__IFUNCTION_RET_ADDR

wska´znik do lokacji w A

Sposób zwracania warto´sci przez funkcj˛e z przykładu ze strony 33 pokazuje fragment pro-

gramu:

mov a,sp

mov a,#4-?LSC1+1

mov r1,a

mov @r1,__oper1_msb

inc r1

mov @r1,__oper1_lsb

36

background image

2.4

Przekazywanie danych mi˛edzy funkcjami a instrukcjami asemblera

;return(s)

.

.

.

Modyfikacja funkcji z tego przykładu powoduje, ˙ze zwracana jest warto ´s´c 4-bajtowa. Program
w C ma wówczas posta´c:

main()

{

long f_przykl_3(1,2,3);

}

long f_przykl_3(int x, int y, int z)

{

int a,b;

long s;

a=4;

b=5;

s=(long)z;

return(s);

}

Po przetłumaczeniu funkcji return:

;return(s)

mov r1,a

mov a,__ilib_temp_ptr

add a,#-__IFUNCTION_RET_ADDR

lcall __istore_long

2.4

Przekazywanie danych mi ˛edzy funkcjami a instrukcjami

asemblera

2.4.1

Wprowadzanie instrukcji asemblera do programu w C

Współprac˛e fragmentów programów w C i w asemblerze umo˙zliwiaj ˛

a odpowiednie dyrek-

tywy kompilatora. Podstawow ˛

a konstrukcj ˛

a składniow ˛

a umo˙zliwiaj ˛

ac ˛

a wprowadzenie instrukcji

asemblera jest para dyrektyw:

.asm

.

;program w asemblerze

.

.endasm

Tekst mi˛edzy nimi jest przenoszony przez kompilator bezpo´srednio do tłumaczenia przez asem-
bler.

37

background image

2

Programowanie w C µK rodziny Intel 8051

Uwaga:

Kompilator dzieli etykiety na lokalne i globalne:

nazwy lokalne generowane s ˛

a przez kompilator wewn ˛

atrz funkcji i s ˛

a wa˙zne tylko w ob-

r˛ebie danej funkcji,

nazwy globalne musz ˛

a by´c definiowane na zewn ˛

atrz funkcji.

Nazwy lokalne definiowane wewn ˛

atrz funkcji wyró˙zniane s ˛

a przez kompilator znakiem

?

na

pocz ˛

atku lub ko ´ncu nazwy. Poniewa˙z stosowana jest zasada, ˙ze u˙zycie nazwy globalnej ko ´nczy

blok nazw lokalnych we wstawkach asemblerowych nale˙zy u˙zywa ´c nazw z

‘?’

na pocz ˛

atku lub

na ko ´ncu.

2.4.2

Dost ˛ep do zmiennych lokalnych

Zmienne lokalne umieszczane s ˛

a na stosie wewn˛etrznym lub zewn˛etrznym w zale˙zno ´sci od

trybu pracy kompilatora. Kompilator lokalizuje je w sposób wzgl˛edny w odniesieniu do war-
to´sci wska´znika ramki. Dyrektywa

.local

powoduje wygenerowanie na poziomie asemblera

dyrektywy

.var

przyporz ˛

adkowuj ˛

acej zmiennej warto´s´c b˛ed ˛

acej przesuni˛eciem w stosunku do

aktualnej zawarto´sci wska´znika ramki. W trybie wewn˛etrznym rol˛e wska´znika ramki spełnia
SP. Poni˙zszy przykład ilustruje wykorzystanie dyrektywy

.local

do wskazywania z poziomu

asemblera zmiennej lokalnej przez nazw˛e:

main()

{

char c2;

int int2;

.local c2; /* tworzy przesuni˛

ecie w stosunku do zawarto´

sci SP */

.local int2;

/* teraz asembler mo˙

ze odwoływa´

c si˛

e do obu zmiennych przez nazw˛

e */

.asm

;wstawka asmeblerowa

mov a,sp

add a,#c2

mov r0,a

mov @r0,#0

;wyzeruj zmienn ˛

a c2

mov a,sp

add a,#int2

mov r0,a

mov @r0,#.high. 0

;wyzeruj zmienn ˛

a int2

inc r0

mov @r1,#.low. 0

.endasm

}

2.4.3

Dost ˛ep do argumentów funkcji j ˛ezyka C

Dost˛ep do argumentów funkcji j˛ezyka C z poziomu asemblera umo˙zliwia dyrektywa kom-

pilatora

.arg

. Działa ona tak samo jak dyrektywa

.local

z tym, ˙ze argumentem generowanej

38

background image

2.4

Przekazywanie danych mi˛edzy funkcjami a instrukcjami asemblera

dyrektywy asemblera

.var

jest przesuni˛ecie wskazuj ˛

ace zmienn ˛

a w obszarze argumentów funk-

cji. Przykład:

main(char c1, int int1)

{

.arg c1;

.arg int1;

/* dalej ja w przykładzie powy˙

zej */

}

2.4.4

Adresowanie bezpo ´srednie i po ´srednie w programach w C

Adresowanie bezpo´srednie – za nazw ˛

a u˙zywan ˛

a w programie kryje si˛e adres, tzn. u˙zycie

danej nazwy powoduje odwołanie si˛e do komórki pami˛eci (lub rejestru) opatrzonej nazw ˛

a. Do-

tyczy to wszystkich nazw globalnych takich jak:

nazwy zmiennych globalnych

nazwy funkcji

nazwy rejestrów specjalnych (s ˛

a definiowane z zasady jako nazwy globalne)

a tak˙ze (z zało˙zenia) struktur zło˙zony takich jak:

tablice

unie

Przykład:

const char tab[]=”komunikat 1”;

main ()

{

extern const char tab[];

char c1;

c1=tab[0];

}

fragment odpowiedniego programu asemblerowego:

.internal_const_data

_tab:

.byte

”komunikat 1”

.program

_main:

.equal $

?ASC0:

.equal 0

?TSC0:

.equal 0

?LSC0:

.equal 1

39

background image

2

Programowanie w C µK rodziny Intel 8051

;c1=tab[0]

mov

dptr,#_tab+0

clr

a

movc a,@a+dprt

xch

a,r0

mov

a,sp

add

a,#0-?LSC0+1

xch

a,r0

mov

@r0,a

?BOFO:

.equal $

dec

sp

ret

.global _tab

.global _main

.extern _tab

.end

U˙zywaj ˛

ac nazw operuje si˛e na zawarto´sciach komórek lub rejestrów traktowanych jako argu-

menty o danej nazwie. Mo˙zliwe jest te˙z uzyskanie adresu danej nazwy i odwołanie si˛e do
argumentu po´sredniego przez ten adres. Mo˙zliwe s ˛

a równie˙z stosowne operacje na adresach

jako zmiennych całkowitych. Przykład:

char c1=1;

main()

{

extern char c1;

int adr_main;

adr_main=&main;

c1++;

}

po kompilacji:

;char c1=1

.internal_init_data

_c1:

.byte 1

.program

_main: .equal $

?ASC0:

.equal 0

?TSC0:

.equal 0

?LSC0:

.equal 4

mov a,sp

mov a,#?TSC0+?LSC0

mov sp,a

40

background image

2.4

Przekazywanie danych mi˛edzy funkcjami a instrukcjami asemblera

;adr_main=&main

mov r0,#.low. _main

mov r2,#.high. _main

mov a,sp

add a,#2-?LSC0+1

mov r1,a

mov @r1,__oper1_msb

inc r1

mov @r1,__oper1_lsb

;c1++

inc .low. _c1

Adresowanie po´srednie – polega na operowaniu adresem zmiennej zamiast jej nazw ˛

a. Tego ro-

dzaju działanie jest niezb˛edne je´sli chce si˛e mie´c dost˛ep do zmiennej jednej funkcji z poziomu
innej funkcji. Przekazywanie argumentu z pierwszej funkcji do drugiej odbywa si˛e poprzez war-
to´s´c, tzn. przy u˙zyciu stosu przekazywane s ˛

kopie argumentów funkcji wywołuj ˛

acej. Funkcja

wywołana operuje tylko na tych kopiach. Aby mo˙zna było zmieni ´c oryginały argumentów funk-
cja wywołuj ˛

aca musi przekaza´c ich adresy. Umo˙zliwia to operator

&

, który u˙zyty dla zmiennej

o nazwie ”

a

” w sposób ”

&a

” nakazuje pobranie adresu zmiennej

a

. Chc ˛

ac teraz operowa ´c na

tym adresie mo˙zna utworzy´c now ˛

a zmienn ˛

a, np. ”

prt=&a;

” nazywan ˛

wska´znikiem (zmienn ˛

a

wska´znikow ˛

a), której warto´s´c stanowi adres zmiennej

a

. Chc ˛

ac zmieni´c warto´s´c zmiennej

a

mo˙zna zastosowa´c ten wska´znik z operatorem ”

*

” nakazuj ˛

acym traktowa ´c swój argument jako

adres, np. ”

*ptr=5;

” powoduje, ˙ze zmienna

a

przyjmuje warto´s´c 5.

41

background image

2

Programowanie w C µK rodziny Intel 8051

42

background image

Indeks

adres bazowy, 10
asembler, 1

biblioteki, 9
bie˙z ˛

acy wska´znik umieszczenia, 5

dyrektywa, 2

.ABSOLUTE, 12
.BSECT, 14
.CODE, 14
.COMMENT, 3
.DATA, 14
.DB, 6
.DS, 7
.DW, 6
.ELSE, 8
.END, 7
.ENDIF, 8
.ENDM, 8
.ENDMOD, 9
.EQU, 6
.EXTERNAL, 13
.GLOBAL, 13
.IF, 8
.INCLUDE, 14
.MACRO, 8
.MOD, 9
.ORG, 5, 12
.RADIX, 4
.RELATIVE, 12
.RSECT, 14
.SECTION, 15
.SET, 6

grupy sekcji, 10

instrukcja, 2

kompilacja, 22

makroasembler, 7
makrodefinicja, 8

parametry

aktualne, 8
formalne, 8

wywołanie, 8

moduł, 9

konsolidacja, 9
posta´c relokowalna, 9

nazwy, 3, 4

absolutna, 12
absolutne, 6
atrybuty, 6, 13

absolutno´sci, 12
globalno´sci, 13
okre´slono´sci, 6
zewn˛etrzno´sci, 13

globalne, 13
relokowalna, 12
wspólne, 13
zewn˛etrzne, 13

pole

argumentów, 3
etykiety, 2
komentarza, 3
operacji, 3

procedura, 9
program

´zródłowy, 1

wynikowy, 1

program rozruchowy, 22
przeł ˛

acznik sekcji, 15

słownik, 5

dopisywanie nazw, 5

segment, 9, 14

43

background image

Indeks

sekcja, 9, 14

bezpo´srednia, 16
bitowa, 15
definiowanie, 15
domy´slna, 14
lokowanie, 16
po´srednia, 16
pusta, 16
refernecyjna, 16
rejestrowa, 15
standardowa, 14

.BSECT, 14
.CODE, 14
.DATA, 14
.RSECT, 14

u˙zytkownika, 14

stałe, 3

liczbowe, 4
znakowe, 4

wyra˙zenia arytmetyczne, 3

operacje porówna ´n, 5
operatory, 4

44