使用C语言清除BSS段,我们肯定要获取BSS段的起始地址和结束地址,那么,C语言要怎么实现使用lds文件中的变量abc?
答:需要以下两步,这两步是重点。
在函数中声明该变量为extern类型(类型不重要,因为我们主要是取值,具体原因后面会说);
使用时,要取址,比如, int *p = &abc;//p的值即为lds中abc的值。
比如下图中,使用extern声明代码段的起始地址和bss段的起始地址,然后取值用指针进行复制操作,这样lds中的变量也可以像C语言中的普通变量一样操作。(实际上,它们和C语言中的变量不同。)
在C语言中需要声明,那么在汇编指令中,为什么可以直接使用?(如下图,为重定位和清除bss段的汇编代码)
下面开始解答:
在C函数中,如果我们声明如下变量。这样,该变量为全局变量:
int g_i; //程序中必然有四字节空间来保存这个变量
1
但是,如果我们在lds链接文件中声明了a1,a2,a3…an个变量,那么,.bin文件中是不会保存这些变量的,这是为啥?
答:这是因为C程序中不保存lds文件中的变量(因为一般用不到),而且真正要用到的时候,我们也并不是没办法。
我们编译程序时,有一个symbol table符号表,万一要用这些变量,可以通过这个符号表在链接的时候使用。
以上面为例,除了g_i,我们再声明两个变量:
int g_i, g_j, g_k;
那么在链接的时候,会有一个符号表如下:
画质不好,但是还是能看懂的。这里每个圈表示一个变量,一个变量由名字和地址构成。显然,C语言中的变量,名字即为变量名,地址即为变量的地址。但是,我们前面说过,.bin文件中不会保存lds文件中的变量,所以lds文件中的变量,地址填的是值,名字则还是变量名。 所以,我们在copy2sdram函数中才要使用取址符号来修饰这个lds变量,因为它的地址才是它的值。
另外,我们要明白。
这个符号表只存在于链接时,作用是辅助链接,不存在与.bin文件中。
lds文件中,无论变量还是常量,里面的值都来自于链接脚本,在链接时由编译器决定。
在使用上,他们和C语言中的普通变量是不同的:
对于g_i,它是一个C语言变量,使用&g_i就可以得到它的地址Addr;
对于lds中的a1,他们没有地址,因为.bin文件里面不会保存它们,C语言中使用它们时,使用&a1取它们的值。
综上所述,使用ld中的变量,就是借助symbol table保存lds的变量,使用时加上&得到它们的值。
关键字:C语言
引用地址:
1.4.3重定位_使用C语言清除BSS段
推荐阅读最新更新时间:2024-11-05 15:43
avr单片机编程的c语言问题总结
这两天在用AVR单片机做项目,这次是边做边深入学,尽量将以前忽略的知识用上,比如指针、文件包含、条件编译、变量作用域等一一调研清楚。收获不少,再次体会到学习的过程中没有无用的地方。用的越深入,才发现学时以为没用的东西都是最有用的,因为都被忽略了。幸亏学习时候的最重要的《c程序设计》还在,全能解决,所以遇到问题就问“谭浩强”。如果不能解决,就找编译器的问题。这是这段时间总结的经验。 一、函数指针 1.int (*func)(void)--基本函数指针变量定义方式,变量func是一个指向返回值为int,没有参数的函数指针,这与其他变量定义有点区别,一般是把变量名放最后,如int a,而函数指针比较不直观, 2.typedef
[单片机]
PIC C语言编程_PICC中变量修饰关键词
1) extern — 外部变量声明 如果在一个 C 程序文件中要使用一些变量但其原型定义写在另外的文件中,那么在本文件中必须将这些变量声明成“extern”外部类型。例如程序文件 code1.c 中有如下定义: bank1 unsigned char var1, var2; //定义了 bank1 中的两个变量 在另外一个程序文件 code2.c 中要对上面定义的变量进行操作,则必须在程序的开头定义: extern bank1 unsigned char var1, var2; //声明位于 bank1 的外部变量 2) volatile — 易变型变量声明 PICC 中还有一个变量修饰词在普通
[单片机]
C语言中的变量详解
先说说变量的作用域,比如,在函数中,形参变量只是在被调用期间才分配内存单元,调用结束立即释放。这就说明形参变量只有在函授内才是有效的,离开该函数就不能再使用了。 这种变量有效性的范围称为变量的作用域。当然不仅仅是形参变量,在C中所有的量都有自己的作用域。 C中的变量,按作用域可分为两种,局部变量和全局变量。 局部变量: 也称内部变量。局部变量是在函数内做定义说明的,其作用域仅限于函数内部,离开函数后再使用这种变量是非法的。 如: void delay(unsigned int x) { unsigned char i,j; //i j 的作用域只是在delay函数内 } 关于局部变量的作用域的几点说
[单片机]
单片机C语言C51的输入输出
在C51语言中,它本身不提供输入和输出语句,输入和输出操作是由函数来实现的。在C51的标准函数库中提供了一个名为“stdio.h”的一般I/O函数库,它当中定义了C51中的输入和输出函数。当对输入和输出函数使用时,须先用预处理命令“#include stdio.h ”将该函数库包含到文件中。 在C51的一般I/O函数库中定义的I/O函数都是通过串行接口实现,在使用I/O函数之前,应先对51单片机的串行接口进行初始化。选择串口工作于方式2(8位自动重载方式),波特率由定时器/计数器1溢出率决定。例如,设系统时钟为12MHZ,波特率为2400,则初始化程序如下: SCON=0x52; TMOD=0X20; TH1=0
[单片机]
51单片机C51程序
C51程序 学习C51程序之前需要对C语言有一定的了解和学习;这里只介绍与C语言有区别的地方; 具体的不同如下: 1、C51中增加了几种针对MSC-51单片机的特有数据类型 a、sfr和sfr16:用于定义特殊功能寄存器,如:sfr PSW = 0xd0(一般情况下这些特殊功能寄存器不需要用户自定义,通常包含在 reg51.h 头文件中) b、bit和sbit: 定义位变量,只占用一个二进制位;bit是位寻址区中的变量(20H~2FH,关于位寻址区详见51单片机之存储器篇);sbit指特殊功能寄存器中的可以位寻址的变量 ,如:sbit P1_0 = P1^0 sbit OV = 0xd2 2、C51的存储模式与存储器密
[单片机]
C语言基础 - 结构(struct)
ant发表于 2005-8-6 12:37:00 结构(struct) 结构是由基本数据类型构成的、并用一个标识符来命名的各种变量的组合。 结构中可以使用不同的数据类型。 1. 结构说明和结构变量定义 在Turbo C中, 结构也是一种数据类型, 可以使用结构变量, 因此, 象其它 类型的变量一样, 在使用结构变量时要先对其定义。 定义结构变量的一般格式为: struct 结构名 { 类型 变量名; 类型 变量名; ... } 结构变量; 结构名是结构的标识符不是变量名。 类型为第二节中所讲述的五
[单片机]
12864液晶显示C语言程序设计实例
12864液晶显示程序 #include reg51.h #include intrins.h sbit RS = P2^5; sbit RW = P2^6; sbit E = P2^7; sbit RES = P3^5; #define Lcd_Bus P0 //MCU P1 ------ LCM #define FIRST_ADDR 0 //定义字符/汉字显示起始位置 unsigned char code zk ={ 0x08,0x20,0x1c,0x10,0x1c,0x1c,0xff,0x9e,0x7f,0x1e,0x1c,0x1f,0x3e,0x1f,0x3e,0x1f, 0x77,0x1f,0x41,0x3
[单片机]
STM32 嵌入式学习入门(0)——C语言基础复习
摘要 主要介绍了嵌入式编程中几个常用,但软件编程中用得不是很多的C语言知识。包括位操作、条件编译、结构体和结构体指针、typedef声明类型、以及extern变量声明、static关键字等内容。 本文并没有将相关C语言知识点介绍地很详细,毕竟这么多知识点要想掌握绝对不是看几篇文档就能掌握的。因此博主建议,如果上述的C语言知识掌握得还不是很好的话,找一本C语言的书好好研究研究。尤其是结构体和结构体指针、还有函数的知识(本文没提到),一定要很熟练。 本文除了简要介绍C语言知识,也结合博主自己的感受简单谈了各个知识点用在了嵌入式编程的什么地方,有不详细和描述不准确的地方欢迎大家留言讨论。 要想学习STM32,C语言的基础
[单片机]