当前位置: 首页 > news >正文

如何建设一个网站站财务公司网站开发源码

如何建设一个网站站,财务公司网站开发源码,个人网站名字大全,网页制作一、目的在之前的《GNU LD脚本命令语言(一)》、《GNU LD脚本命令语言(二)》我们介绍了GNU链接脚本的知识点,基本上对链接脚本中的SECTION、REGION、以及加载地址与执行地址的关系等内容有了一定的了解。本篇主要讲解链…

一、目的

在之前的《GNU LD脚本命令语言(一)》、《GNU LD脚本命令语言(二)》我们介绍了GNU链接脚本的知识点,基本上对链接脚本中的SECTION、REGION、以及加载地址与执行地址的关系等内容有了一定的了解。

本篇主要讲解链接脚本的符号如何在C代码中进行访问。

二、介绍

实际问题分析

在使用RT-Thread Studio进行STM32H750的bootloader代码阅读过程,大家肯定看到过此段代码


RT_WEAK void rt_hw_board_init()
{extern void hw_board_init(char *clock_src, int32_t clock_src_freq, int32_t clock_target_freq);/* Heap initialization */
#if defined(RT_USING_HEAP)rt_system_heap_init((void *) HEAP_BEGIN, (void *) HEAP_END);  //①
#endifhw_board_init(BSP_CLOCK_SOURCE, BSP_CLOCK_SOURCE_FREQ_MHZ, BSP_CLOCK_SYSTEM_FREQ_MHZ);/* Set the shell console output device */
#if defined(RT_USING_DEVICE) && defined(RT_USING_CONSOLE)rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
#endif/* Board underlying hardware initialization */
#ifdef RT_USING_COMPONENTS_INITrt_components_board_init();
#endif}

①注意此行代码中的两个宏HEAP_BEGIN和HEAP_END

#define RAM_START              (0x24000000)
#define RAM_SIZE               (512)
#define RAM_END                (RAM_START + RAM_SIZE * 1024)#if defined(__CC_ARM) || defined(__CLANG_ARM)
extern int Image$$RW_IRAM1$$ZI$$Limit;
#define HEAP_BEGIN      ((void *)&Image$$RW_IRAM1$$ZI$$Limit)
#elif __ICCARM__
#pragma section="CSTACK"
#define HEAP_BEGIN      (__segment_end("CSTACK"))
#else
extern int __bss_end;
#define HEAP_BEGIN      ((void *)&__bss_end)  //①
#endif#define HEAP_END                       STM32_SRAM1_END  //②

①HEAP_BEGIN的值是变量__bss_end的地址,注意此处的__bss_end的类型声明是extern的。

②HEAP_END的值是STM32H750的SRAM的地址末尾,即0x24000000 + 512 * 1024,这个很容易理解,从地址映射表上可以查询的到。

我们搜索整个工程没有找到在代码中找到__bss_end的定义。但是我们在链接脚本文件以及最后的map文件中找到__bss_end的符号

链接脚本中的__bss_end符号定义了bss段的末尾地址

通过map文件分析我们可以看到bss段的末尾地址为0x2400205c,也就是说从这个地址开始我们将SRAM中剩余的内存作为系统堆使用。

那么c代码中的&__bss_end和链接脚本中的__bss_end有什么关系呢?


参考文档

Source Code Reference (LD) (sourceware.org)

在链接脚本中我们可以定义变量,在源代码中(C/C++、Fortran )也可以定义变量。

在链接脚本中定义的变量(或者叫符号)只有地址,没有值;

在源码中定义的变量既有地址又有值。

由于C++支持函数重载,所以编译后符号表中的函数名称会改变。

这边为了统一描述我们假设编译器编译后符号名称不变。

假如我们在链接脚本中定义了符号

_foo = 1000

那么就可以在源码中按照下面的代码引用这个符号

 extern int _foo;

注意源码中的符号我们只能对其取地址,因为这个变量只有地址没有值。

(void *)&_foo;

知识点

When a symbol is declared in a high level language such as C, two things happen. The first is that the compiler reserves enough space in the program’s memory to hold the value of the symbol. The second is that the compiler creates an entry in the program’s symbol table which holds the symbol’s address. ie the symbol table contains the address of the block of memory holding the symbol’s valueWhen a program references a symbol the compiler generates code that first accesses the symbol table to find the address of the symbol’s memory block and then code to read the value from that memory block. 

在高级语中(例如C)声明一个符号时,其内部其实做了两个事,第一编译器在系统内存中保留了足够的内存空间来存放这个符号的值;第二编译器在系统符号表中创建了一个新的条目(表项)用来存放符号的地址,也就是说通过符号名可以找到符号占用的内存的地址,通过此地址,可以知道符号里面对应的值。

举例说明

int foo = 1000;  //①
foo = 1;  //②

①定义了一个变量其初值为1000,也就是foo占用的内存(四字节)里面保存的是数字1000;

②将foo占用的内存里面的值修改为1;这边涉及到两个操作,第一通过foo在符号表中找到其代表的地址值,第二通过找到的地址值找到foo占用的内存空间,然后修改为1

Linker scripts symbol declarations, by contrast, create an entry in the symbol table but do not assign any memory to them. Thus they are an address without a value. So for example the linker script definition:foo = 1000;
creates an entry in the symbol table called ‘foo’ which holds the address of memory location 1000, but nothing special is stored at address 1000. This means that you cannot access the value of a linker script defined symbol - it has no value - all you can do is access the address of a linker script defined symbol.

如果在链接脚本中定义了一个符号,只会在符号表中添加一个新的条目,不会为这个符号分配任何内存,也就说这个符号只有地址没有值。

上图中符号A只有地址没有值

因为符号只有地址,所以我们只能通过&取这个符号的地址,而不能取值


假如我们在源码中想将.ROM段的数据拷贝到FLASH段

start_of_ROM   = .ROM;
end_of_ROM     = .ROM + sizeof (.ROM);
start_of_FLASH = .FLASH;
extern char start_of_ROM, end_of_ROM, start_of_FLASH; //①
memcpy (& start_of_FLASH, & start_of_ROM, & end_of_ROM - & start_of_ROM); //②

①②注意extern声明和&取地址符号。

如果符号是数组怎么办?数组的名称(符号)就是代表其地址,所以下面的代码片段与上面的功能一致。

extern char start_of_ROM[], end_of_ROM[], start_of_FLASH[];
memcpy (start_of_FLASH, start_of_ROM, end_of_ROM - start_of_ROM);

那如果在汇编语言中应该怎么操作呢?

/* start address for the initialization values of the .data section. 
defined in linker script */
.word  _sidata
/* start address for the .data section. defined in linker script */  
.word  _sdata
/* end address for the .data section. defined in linker script */
.word  _edata
/* start address for the .bss section. defined in linker script */
.word  _sbss
/* end address for the .bss section. defined in linker script */
.word  _ebss
/* stack used for SystemInit_ExtMemCtl; always internal RAM used *//*** @brief  This is the code that gets called when the processor first*          starts execution following a reset event. Only the absolutely*          necessary set is performed, after which the application*          supplied main() routine is called. * @param  None* @retval : None
*/.section  .text.Reset_Handler.weak  Reset_Handler.type  Reset_Handler, %function
Reset_Handler:  ldr   sp, =_estack      /* set stack pointer *//* Copy the data segment initializers from flash to SRAM */  movs  r1, #0b  LoopCopyDataInitCopyDataInit:ldr  r3, =_sidataldr  r3, [r3, r1]str  r3, [r0, r1]adds  r1, r1, #4LoopCopyDataInit:ldr  r0, =_sdata  ldr  r3, =_edataadds  r2, r0, r1cmp  r2, r3bcc  CopyDataInitldr  r2, =_sbssb  LoopFillZerobss
/* Zero fill the bss segment. */  
FillZerobss:movs  r3, #0str  r3, [r2], #4LoopFillZerobss:ldr  r3, = _ebsscmp  r2, r3bcc  FillZerobss/* Call the clock system intitialization function.*/bl  SystemInit   
/* Call static constructors */
/* bl __libc_init_array */
/* Call the application's entry point.*/bl  entrybx  lr    
.size  Reset_Handler, .-Reset_Handler

注意观察_sidata、_sdata、_edata等等这些都是在链接脚本中定义的

至此,本篇的内容介绍完毕,点赞+收藏,永远不迷路。

http://www.yayakq.cn/news/605620/

相关文章:

  • ios开发网站app怎么做阿里国际网站的数据分析
  • 网站建设方案 pdf电话销售的10个小技巧
  • 网站建设的素材处理方式宝塔建站详细教程
  • 微信网站开发制作公司wordpress标题代码调用
  • 做网站有免费的服务器吗杭州旅游团购网站建设
  • 上海青浦房地产网站建设iis7发布php网站
  • 做物流网站找哪家好网页qq空间在线登录
  • 联科网站建设手机能制作软件吗
  • 河北唐山网站建设wap网页编写
  • 南京做信息登记公司网站产品设计创意图片
  • 网站站点的建立广安北京网站建设
  • 门户网站开发投标文件.doc熊掌号 wordpress插件
  • 网站开发计入会计 什么科目博客seo优化技术
  • 免费网站建设翻译深圳高端家装公司
  • 山东临沂网站建设北京企业网站建设方案
  • php网站建设与管理网址导航怎么卸载不掉
  • 网站建站是 什么手机企业网站如何建设
  • 沈阳建设企业网站网页制作基础入门教程
  • 学习网站开发培训wordpress点击量设置
  • 辽宁市场网站建设销售视频网站建站费用
  • 做外贸网站俄罗斯外贸公司名录
  • 殡仪馆做网站的好处赤峰网站开发公司
  • 互联网公司网站建设ppt北京成立公司
  • 做网站在线支付系统多少钱电子商务网站建设论文结论
  • 上海html5网站制作北京建设工程继续教育网站
  • 农产品的网站建设方案书范文黑龙江新闻法治频道节目回放
  • dw建设网站教案wordpress可以自己做主题
  • 做网站推广公司网站页面布局优化
  • 怎么利用云盘建设网站泉州制作网站软件
  • 商务网站建设怎样收费电子商务学网站建设好吗