一、mem文件和map文件 sdcc提供mem文件和map文件来帮助我们分析一个项目编译完成后,它对各种存储空间的占用情况。
1.1 mem文件 mem文件主要组成是这样的: ——内部ram使用表 ——外部ram和rom使用统计表
打开在前一个实验里生成的test.mem查看的结果如下
Internal RAM layout: 0 1 2 3 4 5 6 7 8 9 A B C D E F 0x00:|0|0|0|0|0|0|0|0|a|I|S|S|S|S|S|S| 0x10:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S| 0x20:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S| 0x30:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S| 0x40:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S| 0x50:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S| 0x60:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S| 0x70:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S| 0x80:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S| 0x90:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S| 0xa0:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S| 0xb0:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S| 0xc0:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S| 0xd0:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S| 0xe0:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S| 0xf0:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0-3:Reg Banks, T:Bit regs, a-z:Data, B:Bits, Q:Overlay, I:iData, S:Stack, A:Absolute
Stack starts at: 0x0a (sp set to 0x09) with 246 bytes available.
可以看到它有一个内部ram的map图,每个字节的指派都很清晰,对于外部ram和rom,也提供了一张总体统计表。
Other memory:
Name
Start
End
Size
Max
PAGED EXT. RAM
0x0000
0x0000
1
256
EXTERNAL RAM
0x0001
0x0001
1
65536
ROM/EPROM/FLASH
0x0000
0x0079
122
65536
1.2 map文件 mem文件提供的是ram和rom的总体使用统计,而map文件,则是ram和rom的详细内存使用表。
map文件的前两段是由链接器创建的符号表,然后再是ram的详细分段。
map文件的主要组成是这样的: ——符号表 ——ram map ———ram segment REG_BANK_0 ———ram segment DSEG ———ram segment ….. ——rom map ———-start up ———-code (代码区) ———-const(常量区) ———-lib&rel列表
在ram map中,除了分段的大小,map文件还会列出所有申明在这个区域的变量名以及该变量实际是在哪个源文件里申明的,比如DSEG段:
Area
Addr
Size
Decimal Bytes
(Attributes)
DSEG
00000000
00000080
128 bytes
(REL,CON)
地址表
Value
Global
Global Defined
In Module
00000008
_data_v
test
变量表
段表的顺序是REG_BANK_0(R0-R7),DSEG(data),ISEG(idata),SSEG(stack),PSEG(pdata),XSEG(xdata),都是之前有提到的存储空间。
在rom map里,一开始是一段汇编函数的地址图,关于sdcc如何初始化单片机及c语言运行环境,之后再做分析。
进入代码区,我写了一个小的实验项目,它的代码区memory map是这样的:
Area
Addr
Size
Decimal Bytes
(Attributes)
CSEG
0000006E
00000282
642. bytes
(REL,CON,CODE)
code区总表
Value
Global
Global Defined In Module
C:
0000006E
_init_timer0
debug
C:
00000075
_count_runtime_start
debug
C:
00000078
_count_runtime_over
debug
C:
0000008D
_init_uart
debug
C:
0000009F
_uart_send_char
debug
C:
000000AD
_delay10ms
debug
C:
000000AE
_delay100cyc
delay
C:
000000B8
_delay10000cyc
delay
C:
000000CA
_HC595_Send_Data
display
C:
000000F5
_HC595_Set_Row
display
C:
0000012C
_Led_Show_Word
display
C:
0000018B
_Delay10ms
key
C:
000001A3
_Scan_key
key
C:
00000239
_Check_Password
key
C:
0000027C
_board_init
main
C:
0000028C
_Beer
main
C:
000002B3
_main
main
C:
000002EC
__sdcc_external_startup
_startup
函数表
然后是常量区的大小和常量表(略),形式同上述data分段。
mem文件会分别列出每个函数在rom中的起始地址以及他们从哪里链接而来。也会给出所有链接的rel和lib
Files Linked [ module(s) ]
build/debug.rel [ ] build/delay.rel [ ] build/display.rel [ ] build/key.rel [ ] build/main.rel [ ]
Libraries Linked [ object file ]
/usr/bin/../share/sdcc/lib/small/mcs51.lib [ crtclear.rel ] /usr/bin/../share/sdcc/lib/small/mcs51.lib [ crtxinit.rel ] /usr/bin/../share/sdcc/lib/small/mcs51.lib [ crtxclear.rel ] /usr/bin/../share/sdcc/lib/small/mcs51.lib [ crtpagesfr.rel ] /usr/bin/../share/sdcc/lib/small/mcs51.lib [ crtstart.rel ] /usr/bin/../share/sdcc/lib/small/libsdcc.lib [ _startup.rel ]
二、指定分段地址 sdcc可以用一些链接选项来修改默认的ram/rom段的起始地址。
2.1 —xram-loc 默认值为0,指定外部内存使用的起始地址,链接选项可以用16进制或者10进制,e.g1 --xram-loc 0x8000 or --xram-loc 32768
2.2 —code-loc 修改code段在rom中的起始地址,默认为0
2.3 —stack-loc 修改堆栈指针,如果要使用这个选项,要一并使用—no-pack-iram来关闭用寄存器优化变量的访问。
2.4 —xstack-loc 默认值为pdata区域之后
2.5 —idata-loc 默认值为0x80