在诸如C语言等高级语言中,当一个变量(符号)定义时,会有两件事发生。首先,编译器会在程序内存中留下足够的空间来保存该变量(符号)的值。第二步,编译器在符号表中创建一个入口,这个入口保存着上一步保留下的保存变量的值的地址。例如: int gintl = 1000; 编译器首先申请一块int类型大小的内存块,假设申请的内存块地址是0x00200070。编译器在符号表中创建符号表时,申请的内存块的地址0x00200070就会保存在符号表中。当使用变量时,首先会在符号表是查找名为"gintl"的符号,通过该符号获取保存该变量值的地址,对该地址的内容进行读取或写入操作就可以读取该变量的值或修改该变量的值。值得一提的是关于指针的操作。例如: int *ptr = &gintl; 对于指针变量ptr来说,按照上述步骤申请内存块以及创建符号表入号。对于初始化的值来说,在符号表中查找'gintl',找到后把符号表中的值0x0020070复制到ptr相关的内存块中。在链接脚本中,定义一个变量时,只在符号表中创建符号表入口,并且把值300保存在符号中。 foo = 300; 因此,我们无法在C语言等高级语言中访问foo,因为在链接脚本中定义该变量时并没有为该变量申请内存,该变量只有地址而没有值。我们可以访问它的地址。在链接脚本中,定义的变量就只是用来标识下地址而不是用来修改内存中的数据的。如在链接脚本中定义一个变量和C语言中一样,申请内存块并把值写入内存块中,这样就更改了内存中的数据,并非我们所愿。 用nm命令可查看程序的符号表,可以看出两者的不同。第一列是符号值,第二列是符号类型,第三列是符号名。如下:
001003ac t BOARD_GetRemap 00100430 T BOARD_RemapRam 001001a4 T LowLevelInit 0010046c T _efixed 00200074 D _erelocate 00200074 N _ezero 00100000 T _sfixed 00200000 D _srelocate 00204000 A _sstack 00200074 N _szero 00200010 d dataAbortVector 0010018c T defaultFiqHandler 00100198 T defaultIrqHandler 00100180 T defaultSpuriousHandler 00200074 A end 00100000 T entry 0020001c d fiqHandler 0020001c d fiqVector 00200070 D gintl 00200020 d irqHandler 00200018 d irqVector 001000a0 T main 0020000c d prefetchAbortVector 00200014 d reservedVector 00100000 t resetHandler 00200000 d resetVector 00200008 d swiVector 00200004 d undefVector