Paměťový model procesorů řady x51 (8051, 8052, ...)

z hexadecimální soustavy do ASCII  Obsah  není násl. kap.
Mikroprocesory řady MCS-51 používají oddělené adresové prostory programu a dat. Oba prostory, jak datový, tak programový je možno dále rozdělit na vnitřní a vnější paměťový prostor. Mezi paměťové prostory je možno zařadit i oblast speciálních funkčních registrů. Jednotlivé paměťové prostory se vzájemně nepřekrývají a používají k přístupu různou sadu instrukcí.

Adresový prostor programu

Nejjednodušší je adresový prostor programu. Řada MCS-51 umí adresovat přímo, bez využití dalších programátorsko/hardwarových fint, 64 kBytů programu. GNU assembler MCS51-AS (který požívá systém Web51) pro paměť programu používá standardní segment .text. Do tohoto segmentu je standardně umisťován kód programu. Pro uložení konstant do tohoto segmentu je možno použít v závislosti na požadovaném formátu konstanty například těchto příkazů:
Příklad 1.1.
   1                 	.text
   2                 	
   3                 	.equ	symbol1, 0x4A
   4                 	
   5 0000 4A          	.byte	74
   6 0001 4A          	.byte	0b01001010
   7 0002 4A          	.byte	0112
   8 0003 4A          	.byte	0x4A
   9 0004 4A          	.byte	0X4a
  10 0005 4A          	.byte	'J
  11 0006 4A          	.byte	'J'
  12 0007 4A          	.byte	'\J
  13 0008 4A          	.byte	symbol1
  14 0009 00          	.byte	neznamysymbol
  15 000a 12 34       	.word	4660
  16 000c 12 34       	.word	0x1234
  17 000e 12 34 56 78 	.int	02215053170
  18 0012 12 34 56 78 	.int	305419896
  19 0016 12 34 56 78 	.int	0x12345678
  20 001a 12 34 56 78 	.long	0x12345678
  21 001e 12 34 56 78 	.quad	0x123456789ABCDEF0
  21      9A BC DE F0 
  22 0026 12 34 56 78 	.octa	0x123456789ABCDEF0123456789abcdef0
  22      9A BC DE F0 
  22      12 34 56 78 
  22      9A BC DE F0 

DEFINED SYMBOLS
         example.asm:3      *ABS*:0000004a symbol1

UNDEFINED SYMBOLS
neznamysymbol

Jak je z ukázky patrné, assembler umí pracovat s konstantami o délce 8/16/32/64/128 bitů, nadefinovanými dle konvencí jazyka "C", a to ať již v dekadickém formátu (v tomto případě číslo začíná číslicí 1 až 9), hexadecimálním (začínajícím sekvencí 0x), binárním (začínajícím sekvencí 0b) či jako ASCII konstantou. Místo hodnoty konstanty je možno uvést i symbolické jméno, jež je později v době překladu či linkování nahrazeno hodnotou.

Assembler umožňuje do adresového prostoru programu vkládat i řetězcové konstanty, např. textová hlášení. Tyto konstanty je možno automaticky ukončovat znakem binární nuly (použijeme-li pro definici .string či .asciz).


Příklad 1.2.
  24 0036 4F 64 72 61 	.ascii	"Odradkovani\12"
  24      64 6B 6F 76 
  24      61 6E 69 0A 
  25 0042 4F 64 72 61 	.ascii	"Odradkovani\012"
  25      64 6B 6F 76 
  25      61 6E 69 0A 
  26 004e 4F 64 72 61 	.ascii	"Odradkovani\x0A"
  26      64 6B 6F 76 
  26      61 6E 69 0A 
  27 005a 4F 64 72 61 	.ascii	"Odradkovani\n"
  27      64 6B 6F 76 
  27      61 6E 69 0A 
  28 0066 4E 75 6C 61 	.string	"Nula nakonec"
  28      20 6E 61 6B 
  28      6F 6E 65 63 
  28      00 
  29 0073 4E 75 6C 61 	.asciz	"Nula nakonec"
  29      20 6E 61 6B 
  29      6F 6E 65 63 
  29      00 
  30 0080 08 0C 0A 0D 	.ascii	"\b\f\n\r\t\\\""
  30      09 5C 22

Textové řetězce mohou obsahovat i speciální znaky, tak jak jsou známy např. z jazyka "C", např. \n pro znak nového řádku. V textových řetězcích mohou být vloženy i další speciální znaky pomocí jejich vyjádření pomocí znaku \ a jejich oktalové hodnoty, popř. sekvence \x a jejich hexadecimální hodnoty. Potřebujeme-li do řetězce vložit znak obráceného lomítka, musíme jej zdvojit. Pro vložení znaku " do řetězce je nutno před něj dát znak \ tak jak je vidět z předchozí ukázky programového kódu.

Do adresního prostoru programu je možno jednoduše vkládat i konstanty, vyjadřující čísla v pohyblivé řádové čárce. MCS51-AS pracuje s formátem čísel dle IEEE


Příklad 1.3.
  31 0071 40 49 0F D8 	.float	3.141592
  32 0075 40 49 0F D8 	.float	3141592E-6
  33 0079 40 49 0F D8 	.single	3141592E-6
  34 007d 40 09 21 FA 	.double	3141592E-6
  34      FC 8B 00 7A 
  35 0085 40 49 0F D8 	.float	0f3141592E-6
  36 0089 40 49 0F D8 	.float	0d3141592E-6

Adresový prostor dat

Daleko složitější je adresový prostor obsahující data. Procesory řady MCS-51 mají dva datové prostory, Vnitřní datovou paměť o velikosti 128 byte u nejmenších procesorů řady (8031, 8051, ...) až 256 byte u největších procesorů řady (8052, ...). Vnější adresová paměť má maximální velikost 64 kByte. Vnější a vnitřní datová paměť jsou přístupné pomocí rozdílné sady instrukcí a vzájemně se nepřekrývají. Pomocí externích hardwarových fintiček je však možné překrýt vnější datovou paměť a vnější paměť programu.

Vnitřní datová paměť

Vnitřní datová paměť je částečně překryta speciálními funkčními registry. První procesory řady MCS-51 měly pouze 128 byte interní datové paměti a proto do zbývajících 128 byte paměti, adresovatelných osmibitovou adresou, umístili konstruktéři speciální funkční registry. Na adrese 0x80 najdeme například datový registr portu 0 procesoru. Jediné čím se speciální funkční registry liší od interní datové paměti je, že jsou pouze přímo adresovatelné. Není do nich možno přistupovat pomocí nepřímé adresace, to znamená pomocí určení adresy interní datové paměti pomocí registru R0 (mov a,@r0)(mov @r0,a) či R1 (mov a,@r1)(mov @r1,a), ale pouze pomocí přímé adresace (např. mov a,0x80)(mov a,p0)(anl p0,#0b10101010). Celý rozsah interní datové paměti je přístupný pouze pomocí nepřímé adresace. Hledání chyb, způsobených přímou adresací interní datové paměti, tam kde je paměť přístupná pouze nepřímo, patří k nočním můrám mnoha programátorů. Assembler nemá příliš možností jak na tyto chyby upozornit.

A aby to nebylo tak jednoduché, jsou v prostoru interní datové paměti další dvě oblasti, umožňující ještě další "kouzla". První z nich je oblast 0x00...0x1F obsahující čtyři banky registrů. Druhou je oblast 0x20...0x2F umožňující bitový přístup.

Procesory z rodiny MCS-51 používají pro svoji činnost osm univerzálních registrů označených R0 až R7. Aby je nebylo nutno např. při obsluze přerušení odkládat na zásobník, využívají procesory z rodiny MCS-51 metodu bankování. Procesory mají celkem 4 banky registrů, přepínané pomocí dvou bitů (RS0, RS1)ve stavovém registru PSW. Jednotlivé banky mají počátek od adresy 0x00, 0x08, 0x10 a 0x18. Vzhledem k tomu, že některé instrukce neumožňují použít k adresaci registr ale pouze absolutní adresou (např. PUSH, POP, ...), usnadňují snad všechny assemblery takovouto adresaci zavedením absolutních pseudoregistrů AR0 až AR7. Tyto registry však nesledují stav bitů RS0 a RS1, ale počáteční adresu celé banky odvozují od speciální pseudoinstrukce .using 0 až 3. Pseudoinstrukce .using zároveň ovlivňuje rezervaci místa sestavovacím programem (linkerem) pro registry. Jak ovlivní tato pseudoinstrukce vygenerovaný kód je vidět z následující ukázky


Příklad 1.4.
  38                 	.using	0
  39 008d C0 00       	push	ar0
  40 008f C0 07       	push	ar7
  41                 	.using	1
  42 0091 C0 08       	push	ar0
  43 0093 C0 0F       	push	ar7
  44                 	.using	2
  45 0095 C0 10       	push	ar0
  46 0097 C0 17       	push	ar7
  47                 	.using	3
  48 0099 C0 18       	push	ar0
  49 009b C0 1F       	push	ar7

Na oblast registrů navazuje oblast interní paměti, která je bitově adresovatelná. Adresace jednotlivých bitů je pouze přímá, adresa bitu je součástí instrukce. Stejně jako v případě paměti dat, se pro bitovou adresaci používá pouze prvních 128 bitů, zbývajících 128 bitů bitově adresovatelného prostoru je použito k adresaci bitů ve speciálních funkčních registrech. Bitově je tedy adresovatelná oblast v rozsahu 0x20 až 0x2F. Potřebujeme-li používat zároveň pro přístup do této oblasti na úrovni bytů i bitů, budeme potřebovat na úrovni assembleru funkci, umožňující adresaci např. 3 bitu z daného bytu. MCS51-AS používá k tomu to účelu zabudovanou funkci B2B(byte, bitový_offset_v_rámci_byte). Bitový offset nemusí být v rozsahu 0 až 7, B2B umožňuje adresovat i vícebytové proměnné, lze si proto nadefinovat např. 4bytovou proměnnou a adresovat pomocí B2B všech jejích 32 bitů.

Příklad 1.5.
  51                 	    .equ	test1,0x20	;zacatek bitove adresovatelne datove oblasti
  52                 	    .equ	test2,0x24	;4 byte bitove adresovatelne datove oblasti
  53                 	
  54 009d A2 00       	    mov C,B2B(test1, 0)         ;presun do Carry bit 0 promenne test0
  55 009f A2 0D       	    mov C,B2B(test1, 13)
  56 00a1 A2 1F       	    mov C,B2B(test1, 31)
  57 00a3 A2 20       	    mov C,B2B(test2, 0)
  58 00a5 A2 2D       	    mov C,B2B(test2, 13)
  59 00a7 A2 3F       	    mov C,B2B(test2, 31)

Absolutně zadané začátky bitově adresovatelné paměti zde byly zvoleny jen pro demonstraci, vlastní přidělování paměti, zajišťuje obvykle sestavovací program (linker). [1].[2]

Zadávat adresy proměnných pomocí .equ by bylo velmi nepraktické. Assembler spolu se sestavovacím programem umožňuje celkem komfortní přidělování paměti. Pro přidělení paměti lze použít dva postupy. První spočívá v přepnutí do příslušného datového segmentu některou z pseudoinstrukcí .data a následném klasickém vymezení místa pomocí některé z pseudoinstrukcí .ds. Druhou možností je použít definici proměnné pomocí jedinné pseudoinstrukce, definující zároveň datový segment, jméno proměnné a její velikost. Touto pseudoinstrukcí je některá z pseudoinstrukcí .comm či .common. Jednotlivé datové segmenty, respektivě části interního datového prostoru jsou odlišeny svými předdefinovanými jmény segmentů a modifikacemi pseudoinstrukce .comm. Umístění jednotlivých segmentů v interní paměti dat je určeno skripty řídicími sestavovací program. standardní umístění je definováno v následující tabulce.


Tabulka 1.1.

Od adresy Do adresy Segment   Poznámka
0x08(.using 0), 0x10(using 1), 0x18(using 2), 0x20(.using 3) max. 0xFF, obvykle však max. 0x1F .rdata .rcomm/.rcommon Nevyžitá část pro umístění registrů, přímo adresovatelná
od konce .rdata, min. 0x20 max. 0xFF, obvykle však max. 0x2F .bdata .bcomm/.bcommon Bitově adresovatelná oblast (0x20...0x2F), adresovaná po bytech
od konce (.bdata - 0x20)*8 bitově max. 0x7F bitově, max. 0x2F bytově .bitdata .bitcomm/.bitcommon Bitově adresovatelná oblast (0x00...0x7F), adresovaná po bitech
od konce (.bdata + velikost .bitdata přepočtená na byty) tj. min 0x20 max. 0xFF, obvykle však 0x7F .data .comm/.common Přímo adresovatelná oblast (<0x80)
od konce .data tj. min 0x20 max. 0xFF .idata .icomm/.icommon Nepřímo adresovatelná oblast


Příklad 1.6.
  61                 	    .rdata
  62 0000 00          	var1:	.ds.b	1
  63                 	    .bdata
  64 0000 00          	var2:	.ds.b	1
  65                 	    .data
  66 0000 00          	var3:	.ds.b	1	;1 byte promenna
  67 0001 00 00       	var4:	.ds.w	1	;2 byte promenna
  68 0003 00 00 00 00 	var5:	.ds.s	1	;4 byte promenna
  69 0007 00 00 00 00 	var6:	.ds.d	1	;8 byte promenna
  69      00 00 00 00 
  70 000f 00 00       	var7:	.ds	1	;2 byte promenna
  71                 	    .idata
  72 0000 00          	var8:	.ds.b	1
  73                 	
  74                 	.rcomm	var9, 1		;1 byte promenna
  75                 	.bcomm	var10, 1
  76                 	.comm	var11, 1
  77                 	.icomm	var12, 1

DEFINED SYMBOLS
         example.asm:62     .rdata:00000000 var1
         example.asm:64     .bdata:00000000 var2
         example.asm:66     .data:00000000 var3
         example.asm:67     .data:00000001 var4
         example.asm:68     .data:00000003 var5
         example.asm:69     .data:00000007 var6
         example.asm:70     .data:0000000f var7
         example.asm:72     .idata:00000000 var8
                            .rbss:00000001 var9
                            .bbss:00000001 var10
                            *COM*:00000001 var11
                            .ibss:00000001 var12
[3]

Vnější datová paměť

Vnější datová paměť je v dnešní době často součástí procesoru, a to ať již jako paměť RAM, či jako paměť EEPROM. Jednotlivé části takovéto zabudované paměti jsou pak přístupné po jejich zapnutí pomocí specialních konfiguračních bitů v procesoru, kdy poté překryjí klasickou, vnější datovou paměť. Na to je potřeba pamatovat při návrhu podprogramů obsluhujících přerušení. Assembler MCS51-AS spolu s linkerem umožňuje použití vlastních, uživatelsky nadefinovaných paměťových segmentů, nicméně i základní, zabudovaná podpora vnější datové paměti počítá s více paměťovými prostory. standardní paměťový prostor .xdata je rozšířen o další dva, a to o .edata a .eeprom. V těchto prostorech je možno nezávisle na sobě, stejně jako v sekci .data alokovat proměnné. Mimo alokaci proměnných, pomocí .ds lze použít i alokaci pomocí definice common proměnné, pomocí příkazů .xcomm, .xcommon, .ecomm, .ecommon. V segmentu .eeprom není ekvivalent .common příkazu implementován, využití tohoto segmentu, vzhledem k omezenému počtu zápisů a rychlosti zápisu se předpokládá především pro uložení konstant. Do všech datových segmentů lze uložit i konstanty (pomocí příkazů uvedených pro sekci .text), jak překladač, tak linker s nimi umí pracovat.

Použití .common příkazů je velmi lákavé, proměnnou je možno definovat až v místě jejího použití, a ne jak je obvyklé ve zvláštní sekci obvykle na začátku či konci programu. Tyto proměnné jsou však, jak již vyplývá z názvu příkazu common - společné. Nadefinujeme-li si ve dvou částech programu shodou okolností proměnnou stejného jména, sestavovací program obě proměnné považuje za jedinou. Deklarujeme-li proměnné pomocí .ds v příslušné sekci, k tomuto prolnutí nedojde, jak je vidět i z následující ukázky.


Příklad 1.7.
file www8051.lst
  12                 	    .data
  13 0000 00 00       	test1:	.ds	1
  14                 	.global test1

file testLED.lst
  11                 	    .data
  12 0000 00 00       	test1:	.ds	1
  13                 	.global test1

testLED.obj: In function `test1':
testLED.obj(.data+0x0): multiple definition of `test1'
www8051.obj(.data+0x0): first defined here
make: *** [www8051.o2] Error 1

[1] Ani sestavovací program, ani assembler však nekontroluje záměnu bitové proměnné za bytovou. Např. mov a,B2B(test1, 0) projde bez chyby, přestože jde o chybné použití, bytové proměnné (osmibitovému registru) se snažíme přiřadit bitovou proměnnou. Ve skutečnosti se přiřadí místo bitové proměnné do akumulátoru obsah příslušné bytové proměnné na adrese shodné s bitovou proměnnou

[2] Převod bytů na bity odpovídá mechanismu MCS-51, to znamená očíslujeme-li bity v čtyřbytové proměnné z výše uvedeného příkladu dostáváme pro číslování bitů 7 6 5 4 3 2 1 0 15 14 13 12 11 10 9 8 23 22 21 20 19 18 17 16 31 30 29 28 27 26 25 24. MCS-51 používá pro uložení čísel větších jak byte způsob uložení významnějšího byte (MSB) na nižší adresu.

[3] Pro proměnné, definované pomocí .comm, jsou použity jako jména segmentů jména odvozená od .bss, sestavovací program umisťuje do příslušných částí paměti vždy nejprve odpovídající segment .data a za něj .bss.





Sponzored by LPhard Ltd. Graphics by GIMP Created by EasyPad

(c)Copyright 2000, 2001, HW server & Radek Benedikt
Web51@HW.cz, Web51.HW.cz

Final applications of the Web51 : www.HWgroup.cz
z hexadecimální soustavy do ASCII  Obsah  není násl. kap.