gnu鏈接腳本
⑴ cpu運行時程序是在flash中還是在RAM
x86cpu和單片機讀取程序的具體途徑
pc機在運行程序的時候將程序從外存(硬碟)中,調入到RAM中運行,cpu從RAM中讀取程序和數據
而單片機的程序則是固化在flash中,cpu運行時直接從flash中讀取程序,從RAM中讀取數據
造成這種差別的具體原因分析
x86構架的cpu是基於馮毀清.諾依曼體系的
,即數據和程序存儲在一起,而且pc機的RAM資源相當豐富,從幾十M到幾百M甚至是幾個G,客觀上能夠承受大量的程序數據。
單片機的構架大多是哈弗體系的
,即程序和數據分開存儲,而且單片的片內RAM資源是相當有限的,內部的RAM過大會帶來成本的大幅度提高。
通過上面的分析可得知:單片機的程序能存儲於flash中是基於兩點考慮,即體系結構和RAM資源的多少。因此,在技術不但進步片內RAM容量不斷增多的今天,RAM資源已經不再是制約這種差別的主要因素,而對於體系機構我們只要更改cpu讀取程序的方式就可以。
將嵌入式系統的程序存於RAM中的具體做法
「對於很多的嵌入式系統,其代碼很多都存儲在nor flash中,運行也是直接在flash中運行.我最近了解到我新公司的軟體中的一段代碼當時為了提高運行速度被載入到ram中運行.當時他們是花了很多時間來解決這個問題的.
我仔細研究了一下鏈接腳本,用的是gnu的linux的交叉工具鏈.地址分配是寫在一個ld腳本中的.
他們是這樣實現的:
1,將你需要在ram中運行的代碼寫在單獨的一個c文件中,然後在腳本中設置其運行地址與存放地址分開.設置好必要的代碼起始和結束的標志變數.
2,在代碼中將存放地址處的代碼拷貝到運行地址中.
馮.諾依曼體系與哈佛體系的區別
二者的區別就是程序空間和數據空間是否是一體的。 早期的微處理器大多采輪陸用馮諾依曼結構,典型代表是Intel公司的X86微處理器。取指令纖桐前和取操作數都在同一匯流排上,通過分時復用的方式進行的。缺點是在高速運行時,不能達到同時取指令和取操作數,從而形成了傳輸過程的瓶頸。
哈佛匯流排技術應用是以DSP和ARM為代表的。採用哈佛匯流排體系結構的晶元內部程序空間和數據空間是分開的,這就允許同時取指令和取操作數,從而大大提高了運算能力。例如STM320LF240x系列DSP是增強型的哈佛結構通過三組並行的匯流排訪問多個存儲空間。
⑵ c腳本在不同系統中編譯和鏈接依賴的庫文件有何區別
問題1,
區別很大,跨OS編譯的區別就在於OS的本質區別,有一下幾點:
a, 位元組排序,一個int型的數據在windows里是由高地址存到低地址的4個位元組的(假設是32位機器),但是在某些UNIX伺服器,如AIX,它的排序方式就相反的,所以當程序被編譯成低級語言(例如匯編)的時候,內存及CPU的處理就會截然相反
b, 字長,有些unix伺服器是64位的,但大多WINDOWS是32位,那麼定義一個整形的時候就有用8個位元組和4個位元組的區別,字長不一樣,那麼執行起來用對內存的使用也自然就不一樣咯。
c,所謂的庫,也是由編譯器編譯出來的,在不同的OS下,由同一個代碼編譯出來的庫也會不一樣。
d,編譯器也各不相同,也會導致編譯出程序不完全相同。
e,所謂的調用,也就是將程序和庫一起打包,然後在找到庫裡面所定義的函數罷了
綜上,當一個程序或者庫要從其他OS搬到另一個不同規格的OS上的時候,一定要重新編譯一下草能確保程序跑起來不發生錯誤,求其原因也就是因為OS的本質區別,兼容的話,其實就是看OS是否在規格上有沒有本質區別
二,庫文件的編譯是單向的,所以無法取回源碼,
.a庫的打包例: ar r libabc.a a.o b.o c.o
將a.o b.o c.o 合並打包成libabc.a。注意哦(.a一定要以lib開始.a結束哦)
WIN下我不是很在行,你說的lib大包應該沒錯。
三,我不是很清楚
希望對你有幫助,我2年工作的精華
⑶ (ARM + Linux)GNU鏈接腳本中的".ARM.attributes"是什麼意思
所謂gnu鏈接腳本,其實一般都是lds腳本,或者說是elf格式的bin文件組成的腳本文件,主要是告訴你代碼是怎麼排列在elf文件終,至於為啥要燒到arm,其實一般都燒錄在flash中的,然後arm引導程序啟動就需要從flash獲取機器貓,也就是你說的那些段,常見的有data,bss,text,rely等
⑷ llvm 利用g++編譯程序,此程序inclue了llvm的一些頭文件。編譯時出現 undefined reference to錯誤
你是要編譯llvm和你自己在llvm上做的工程?llvm能用gnu工具鏈編譯的,你的配置有問題,編譯,鏈接腳本的順序有問題。這跟是不是第三方庫沒關系
⑸ linux下c語言gcc編譯的時候如果不知道.c文件怎麼鏈接的
有以下步驟:
1.源程序的編譯
在Linux下面,如果要編譯一個C語言源程序,我們要使用GNU的gcc編譯器. 下面
我們以一個實例來說明如何使用gcc編譯器.
假設我們有下面一個非常簡單的源程序(hello.c):
int main(int argc,char **argv)
{
printf("Hello Linux\n");
}
要編譯這個程序,我們只要在命令行下執行:
gcc -o hello hello.c
gcc 編譯器就會為我們生成一個hello的可執行文件.執行./hello就可以看到程
序的輸出結果了.命令行中 gcc表示我們是用gcc來編譯我們的源程序,-o 選項表示
我們要求編譯器給我們輸出的可執行文件名為hello 而hello.c是我們的源程序文件.
gcc編譯器有許多選項,一般來說我們只要知道其中的幾個就夠了. -o選項我們
已經知道了,表示我們要求輸出的可執行文件名. -c選項表示我們只要求編譯器輸出
目標代碼,而不必要輸出可執行文件. -g選項表示我們要求編譯器在編譯的時候提
供我們以後對程序進行調試的信息.
知道了這三個選項,我們就可以編譯我們自己所寫的簡單的源程序了,如果你
想要知道更多的選項,可以查看gcc的幫助文檔,那裡有著許多對其它選項的詳細說
明.
2.Makefile的編寫
假設我們有下面這樣的一個程序,源代碼如下:
#include "mytool1.h"
#include "mytool2.h"
int main(int argc,char **argv)
{
mytool1_print("hello");
mytool2_print("hello");
}
#ifndef _MYTOOL_1_H
#define _MYTOOL_1_H
void mytool1_print(char *print_str);
#endif
#include "mytool1.h"
void mytool1_print(char *print_str)
{
printf("This is mytool1 print %s\n",print_str);
}
#ifndef _MYTOOL_2_H
#define _MYTOOL_2_H
void mytool2_print(char *print_str);
#endif
#include "mytool2.h"
void mytool2_print(char *print_str)
{
printf("This is mytool2 print %s\n",print_str);
}
當然由於這個程序是很短的我們可以這樣來編譯
gcc -c main.c
gcc -c mytool1.c
gcc -c mytool2.c
gcc -o main main.o mytool1.o mytool2.o
這樣的話我們也可以產生main程序,而且也不時很麻煩.但是如果我們考慮一
下如果有一天我們修改了其中的一個文件(比如說mytool1.c)那麼我們難道還要重
新輸入上面的命令?也許你會說,這個很容易解決啊,我寫一個SHELL腳本,讓她幫我
去完成不就可以了.是的對於這個程序來說,是可以起到作用的.但是當我們把事情
想的更復雜一點,如果我們的程序有幾百個源程序的時候,難道也要編譯器重新一
個一個的去編譯?
為此,聰明的程序員們想出了一個很好的工具來做這件事情,這就是make.我們
只要執行以下make,就可以把上面的問題解決掉.在我們執行make之前,我們要先
編寫一個非常重要的文件.--Makefile.對於上面的那個程序來說,可能的一個
Makefile的文件是:
# 這是上面那個程序的Makefile文件
main:main.o mytool1.o mytool2.o
gcc -o main main.o mytool1.o mytool2.o
main.o:main.c mytool1.h mytool2.h
gcc -c main.c
mytool1.o:mytool1.c mytool1.h
gcc -c mytool1.c
mytool2.o:mytool2.c mytool2.h
gcc -c mytool2.c
有了這個Makefile文件,不過我們什麼時候修改了源程序當中的什麼文件,我們
只要執行make命令,我們的編譯器都只會去編譯和我們修改的文件有關的文件,其
它的文件她連理都不想去理的.
下面我們學習Makefile是如何編寫的.
在Makefile中也#開始的行都是注釋行.Makefile中最重要的是描述文件的依賴
關系的說明.一般的格式是:
target: components
TAB rule
第一行表示的是依賴關系.第二行是規則.
比如說我們上面的那個Makefile文件的第二行
main:main.o mytool1.o mytool2.o
表示我們的目標(target)main的依賴對象(components)是main.o mytool1.o
mytool2.o 當倚賴的對象在目標修改後修改的話,就要去執行規則一行所指定的命
令.就象我們的上面那個Makefile第三行所說的一樣要執行 gcc -o main main.o
mytool1.o mytool2.o 注意規則一行中的TAB表示那裡是一個TAB鍵
Makefile有三個非常有用的變數.分別是$@,$^,$<代表的意義分別是:
$@--目標文件,$^--所有的依賴文件,$<--第一個依賴文件.
如果我們使用上面三個變數,那麼我們可以簡化我們的Makefile文件為:
# 這是簡化後的Makefile
main:main.o mytool1.o mytool2.o
gcc -o $@ $^
main.o:main.c mytool1.h mytool2.h
gcc -c $<
mytool1.o:mytool1.c mytool1.h
gcc -c $<
mytool2.o:mytool2.c mytool2.h
gcc -c $<
經過簡化後我們的Makefile是簡單了一點,不過人們有時候還想簡單一點.這里
我們學習一個Makefile的預設規則