回頭重看一下,關於相關的stack資訊
1.對於8051/52 memory map
記憶體種類
tab.1type | SDCC | instruction | size | addressing |
(A) program | __code | MOVC | 64K | index direct |
(B) external | __xdata | MOVX | 64K | indirect |
(C) internal(80~FF) | __idata | MOV | 128 | indirect |
(C) SFR(80~FF) | __sfr | MOV | 128 | direct |
(C) internal(0~7F) | __data | MOV | 128 | direct/indirect |
記憶體定址
tab.2type | read | write | register |
direct | MOV Rn,direct MOV direct,direct | MOV direct,Rn MOV direct,@DPTR MOV direct,#data | R0~R7,A |
indirect | MOV direct,@Ri MOVX A,@DPTR | MOV @Ri,direct MOVX @DPTR,A MOV @Ri,#data | R0,R1,DPTR,A |
index direct | MOV A,#30h MOV DPTR,#300H MOVC A,@A+DPTR | X | A,DPTR |
- Ri=R0,R1,Rn=R0~R7。
- 索引定址法 (index direct) 只能用在程式記憶體,而且不能寫入,只能讀取到 A。
- 外部記憶體只能使用間接定址法 (indirect),而且只能透過 Ri/DPTR/A 三者傳遞數值,如果要寫入數值,只能把值先存入 A,再由 A 寫入 DPTR/Ri。
- 內部記憶體不論間接或直接都可以直接把數值寫入,不需要透過 A,當然要經由 A 也是可以。
pic.1
pic.2
2.關於keil C 管理Stack
因為8051/52的RAM有限.故與一般的C對stack管理方式不同
- 對於keil C中,其對於local variable(區域變數)管理
- 會依不同的設定,會對其local variable有不同的處理,C語言在對local variable會在其scope中對stack中allocated,但同樣地這樣做可能超過51的限制(51的stack是在idata(*1)。所以 compiler會自動作function間的dependency checking(*2,採用共用變數的方式,將local variable放在 _DATA_GROUP_。
- Compiler的選項:Small,Compact,Large的設置就是決定這個segment存放的記憶體位置。
- Small : variable in DATA,會將所有local variable放在 DATA,segment name叫_DATA_GROUP.
- Compact : variable in PDATA,會將所有local variable放在PDATA,segment name叫_PDATA_GROUP_.
- Large : variable in XDATA,會將所有local variable放在XDATA,segment name叫_XDATA_GROUP_.
Optimize Level
- 51 雖然有一般用途的stack和stack pointer,但是Keil C51並沒有真的像標準的C compiler一樣,將function local variable 放在stack中,反而是將local variable都自行allocate在RAM中固定位置,另外利用Compiler作function dependency tree。決定function間共用variable的時機。
- 這要enable optimize : 2 - Data Overlaying,才會啟動。否則Keil C不會check function dependency而共用local variable。
- 所以enable optimize 2以上,對RAM用量影響很大。
- 另 外一個影響RAM用量的optimize的level是 4 : register variable。會在容許的時候,使用register作為local variable。這樣也可以節省ram的使用。但是register 的local variable在debug時無法顯示出來。必須要自己去找出register才行。
上面是keil c對於stack介紹及設定
接下來是對於不同的data,idata,pdata,xdata的介紹
3.
- data,idata,xdata........可參考tab.1
- 其data 為internal register;
- idata也為internal ,但只能indirect access
type
SDCC
instruction
size
addressing
(A) program
__code
MOVC
64K
index direct
(B) external
__xdata
MOVX
64K
indirect
(C) internal(80~FF)
__idata
MOV
128
indirect
(C) SFR(80~FF)
__sfr
MOV
128
direct
(C) internal(0~7F)
__data
MOV
128
direct/indirect
- 而對於pdata---------
- keil c對它的定義為-----Paged (256 bytes) external data memory; accessed by opcode MOVX @Rn.
- 為indirect access ,且只能acess range 256 byte.
- 見pic.2中的external data space上的F800---FFFF(在此有多個pdata
- 256 Bytes On-chip RAM + 2048 Bytes addition XRAM.(PDATA
- 在多數的device中,在存取其XRAM(0x0000~~0x00FF),並不需要額外設定(PPAGEENABLE ) 來對前XRAM 256存取;
- allow PDATA access (MOVX @Rx)---就可以存取其XRAM(0x0000~~0x00FF)
- Some devices have a special SFR that contains the upper address byte to use for PDATA accesses. Devices like the Infineon C517A have an SFR called XPAGE at address 0x91. In the startup code, you must set this SFR to the page number for PDATA. We recommend you use the first available memory page for the PDATA space (0xF8 in the case of the Infineon device).
- 以下以w78516b為例
main.c
include
char xdata kk _at_ 0x0101;
void test(int a)
{
a=a;
}
void main()
{
char a[2];
char b;
test(1);
a[0]='a';
kk='c';
b='b';//test the add
for(;;)
;
}
file : *.list
; SOURCE LINE # 5
0000 7800 R MOV R0,#LOW a
0002 EE MOV A,R6
0003 F2 MOVX @R0,A
0004 08 INC R0
0005 EF MOV A,R7
0006 F2 MOVX @R0,A
; SOURCE LINE # 6
; SOURCE LINE # 7
0007 7800 R MOV R0,#LOW a
0009 E2 MOVX A,@R0
000A FE MOV R6,A
000B 08 INC R0
000C E2 MOVX A,@R0
000D FF MOV R7,A
000E 7800 R MOV R0,#LOW a
0010 EE MOV A,R6
0011 F2 MOVX @R0,A
0012 08 INC R0
0013 EF MOV A,R7
0014 F2 MOVX @R0,A
; SOURCE LINE # 8
0015 22 RET
; FUNCTION _test (END)
; FUNCTION main (BEGIN)
; SOURCE LINE # 10
; SOURCE LINE # 11
; SOURCE LINE # 15
0000 7F01 MOV R7,#01H
0002 7E00 MOV R6,#00H
0004 120000 R LCALL _test
; SOURCE LINE # 16
0007 7800 R MOV R0,#LOW a
0009 7461 MOV A,#061H
000B F2 MOVX @R0,A
; SOURCE LINE # 17
000C 900101 MOV DPTR,#kk
000F 7463 MOV A,#063H
0011 F0 MOVX @DPTR,A
; SOURCE LINE # 18
0012 7800 R MOV R0,#LOW b
0014 7462 MOV A,#062H
0016 F2 MOVX @R0,A
; SOURCE LINE # 19
0017 ?C0002:
0017 80FE SJMP ?C0002
0019 22 RET
; FUNCTION main (END)
LINK MAP OF MODULE: test (TEST)
TYPE BASE LENGTH RELOCATION SEGMENT NAME
-----------------------------------------------------
* * * * * * * D A T A M E M O R Y * * * * * * *
REG 0000H 0008H ABSOLUTE "REG BANK 0"
IDATA 0008H 0014H UNIT ?STACK
* * * * * * * X D A T A M E M O R Y * * * * * * *
XDATA 0000H 0005H INPAGE _PDATA_GROUP_
0005H 00FCH *** GAP ***
XDATA 0101H 0001H ABSOLUTE
* * * * * * * C O D E M E M O R Y * * * * * * *
CODE 0000H 0003H ABSOLUTE
CODE 0003H 0027H UNIT ?C_C51STARTUP
CODE 002AH 001AH UNIT ?PR?MAIN?TEST
CODE 0044H 0016H UNIT ?PR?_TEST?TEST
-------------------------------------------------------
*1.51的stack是在idata----並非一定在idata中,使用者也可宣告在它處
?C_C51STARTUP SEGMENT CODE ?STACK SEGMENT IDATA ;///在此是將?stack放在idata中 RSEG ?STACK DS 1 ;///可以加以決定出其最少空間給stack用 ;DS 20 ;//最少保留10B 而在*.m51中 REG 0000H 0008H ABSOLUTE "REG BANK 0" ;work register DATA 0008H 0005H UNIT _DATA_GROUP_ ;給local variable IDATA 000DH 0014H UNIT ?STACK ;最少保留空間
2.
如何設定其stack addressIn the STARTUP code, change the following:
?STACK SEGMENT IDATA RSEG ?STACK DS 100h-080h
to:
ISEG AT 0xA0 ?STACK: DS 0x100 - ?STACK
This creates an absolute segment for the stack. Then, you can change the 0xA0 to the address where you want the stack to reside. This has the advantage that if your C program variables overlap with the stack, the linker emits a warning.
*2,dependency checking 為根據call-tree來決定其可overlay data 可以從其*.m51中得出.其餘下次再專論
沒有留言:
張貼留言