tcc源碼編譯
可以裝,不過需要安卓手機。
安裝步驟如下:
1、我們打開谷歌應用商店。在搜索框里輸入mobile c查找應用程序。下載並安裝好
6、可以看到這里正確的輸出了Hello World字元串。
『貳』 關於C語言
一、C語言的起源
C 語言是1972年由美國的Dennis Ritchie設計發明的, 並首次在UNIX操作系統
的 DEC PDP-11 計算機上使用。 它由早期的編程語言 BCPL( Basic Combind
Programming Language) 發展演變而來。在1970年, AT&T 貝爾實驗室的 Ken
Thompson根據BCPL語言設計出較先進的並取名為 B的語言, 最後導了C 語言的問世。
隨著微型計算機的日益普及, 出現了許多C 語言版本。由於沒有統一的標准,
使得這些C 語言之間出現了一些不一致的地方。為了改變這種情況, 美國國家標准
研究所(ANSI)為C 語言制定了一套ANSI標准, 成為現行的C語言標准。
二、C 語言的特點
C 語言發展如此迅速, 而且成為最受歡迎的語言之一, 主要因為它具有強大的
功能。許多著名的系統軟體, 如DBASE Ⅲ PLUS、DBASE Ⅳ 都是由C 語言編寫的。
用C 語言加上一些匯編語言子程序, 就更能顯示C 語言的優勢了, 象PC- DOS 、
WORDSTAR等就是用這種方法編寫的。歸納起來C 語言具有下列特點:
1. C是中級語言
它把高級語言的基本結構和語句與低級語言的實用性結合起來。C 語言可以象
匯編語言一樣對位、位元組和地址進行操作, 而這三者是計算機最基本的工作單元。
2. C是結構式語言
結構式語言的顯著特點是代碼及數據的分隔化, 即程序的各個部分除了必要的
信息交流外彼此獨立。這種結構化方式可使程序層次清晰, 便於使用、維護以及調
試。C 語言是以函數形式提供給用戶的, 這些函數可方便的調用, 並具有多種循
環、條件語句控製程序流向, 從而使程序完全結構化。
3. C語言功能齊全
C 語言具有各種各樣的數據類型, 並引入了指針概念, 可使程序效率更高。另
外C 語言也具有強大的圖形功能, 支持多種顯示器和驅動器。而且計算功能、邏輯
判斷功能也比較強大, 可以實現決策目的。
4. C語言適用范圍大
C 語言還有一個突出的優點就是適合於多種操作系統, 如DOS、UNIX,也適用於
多種機型。
三、 Turbo C 概述
1 Turbo C 的產生與發展
Turbo C 是美國Borland 公司的產品,Borland公司是一家專門從事軟體開發、
研製的大公司。該公司相繼推出了一套 Turbo系列軟體, 如Turbo BASIC, Turbo
Pascal, Turbo Prolog, 這些軟體很受用戶歡迎。該公司在1987年首次推出Turbo
C 1.0 產品, 其中使用了全然一新的集成開發環境, 即使用了一系列下拉式菜單,
將文本編輯、程序編譯、連接以及程序運行一體化, 大大方便了程序的開發。1988
年, Borland 公司又推出Turbo C1.5版本, 增加了圖形庫和文本窗口函數庫等, 而
Turbo C 2.0 則是該公司1989年出版的。Turbo C2.0在原來集成開發環境的基礎上
增加了查錯功能, 並可以在Tiny模式下直接生成.COM (數據、代碼、堆棧處在同一
64K 內存中) 文件。還可對數學協處理器 (支持8087/80287/80387等)進行模擬。
Borland 公司後來又推出了面向對象的程序軟體包Turbo C+ + , 它繼承發展
Turbo C 2.0 的集成開發環境, 並包含了面向對象的基本思想和設計方法。
1991年為了適用Microsoft 公司的Windows 3.0 版本, Borland 公司又將Turbo
C++ 作了更新, 即Turbo C 的新一代產品Borlandc C++也已經問世了。
2 Turbo C 2.0基本配置要求
Turbo C 2.0可運行於IBM-PC系列微機, 包括XT, AT及IBM 兼容機。 此時要求
DOS 2.0或更高版本支持, 並至少需要448K的RAM, 可在任何彩、單色80列監視器上
運行。支持數學協處理器晶元, 也可進行浮點模擬, 這將加快程序的執行。
3 Turbo C 2.0內容簡介
Turbo C 2.0有六張低密軟盤(或兩張高密軟盤)。下面對Turbo C 2.0的主要文
件作一簡單介紹:
INSTALL.EXE 安裝程序文件
TC.EXE 集成編譯
TCINST.EXE 集成開發環境的配置設置程序
TCHELP.TCH 幫助文件
THELP.COM 讀取TCHELP.TCH的駐留程序
README 關於Turbo C的信息文件
TCCONFIG.EXE 配置文件轉換程序
MAKE.EXE 項目管理工具
TCC.EXE 命令行編譯
TLINK.EXE Turbo C系列連接器
TLIB.EXE Turbo C系列庫管理工具
C0?.OBJ 不同模式啟動代碼
C?.LIB 不同模式運行庫
GRAPHICS.LIB 圖形庫
EMU.LIB 8087模擬庫
FP87.LIB 8087庫
*.H Turbo C頭文件
*.BGI 不同顯示器圖形驅動程序
*.C Turbo C例行程序(源文件)
其中: 上面的?分別為:
T Tiny(微型模式)
S Small(小模式)
C Compact(緊湊模式)
M Medium(中型模式)
L Large(大模式)
H Huge(巨大模式)
四、 Turbo C 2.0的安裝和啟動
Turbo C 2.0的安裝非常簡單, 只要將1#盤插入A驅動器中, 在DOS的"A>" 下鍵
入:
A>INSTALL
即可, 此時屏幕上顯示三種選擇:
1. 在硬碟上創造一個新目錄來安裝整個Turbo C 2.0系統。
2. 對Turbo C 1.5更新版本。
這樣的安裝將保留原來對選擇項、顏色和編輯功能鍵的設置。
3. 為只有兩個軟盤而無硬碟的系統安裝Turbo C 2.0。
這里假定按第一種選擇進行安裝, 只要在安裝過程中按對盤號的提示, 順序插
入各個軟盤, 就可以順利地進行安裝, 安裝完畢將在C盤根目錄下建立一個TC 子目
錄, TC下還建立了兩個了目錄LIB和INCLUDE, LIB子目錄中存放庫文件, INCLUDE
子目錄中存放所有頭文件。
運行Turbo C 2.0時, 只要在TC 子目錄下鍵入TC並回車即可進入Turbo C 2. 0
集成開發環境。
五、 Turbo C 2.0集成開發環境的使用
進入Turbo C 2.0集成開發環境中後, 屏幕上顯示:
——————————————————————————————
File Edit Run Compile Project Options Debug Break/watch
┌————————————Edit——————————————┐
│ Line 1 Col 1 Insert Indent Tab File Unindent c:NONAME.C│
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│—————————Message——————————————— │
│ │
│ │
└————————————————————————————┘
F1-Help F5-Zoom F6-Switch F7-Trace F8-Step F9-Make F10-Menu
———————————————————————————————
其中頂上一行為Turbo C 2.0 主菜單, 中間窗口為編輯區, 接下來是信息窗
口, 最底下一行為參考行。這四個窗口構成了Turbo C 2.0的主屏幕, 以後的編程、
編譯、調試以及運行都將在這個主屏幕中進行。下面詳細介紹主菜單的內容。
1 主菜單
主菜單 在Turbo C 2.0主屏幕頂上一行, 顯示下列內容:
File Edit Run Compile Project Options Debug Break/watch
除Edit外, 其它各項均有子菜單, 只要用Alt加上某項中第一個字母(即大寫字
母), 就可進入該項的子菜單中。
(1)、File(文件)菜單
按Alt+F可進入File菜單, 該菜單包括以下內容:
.Load(載入)
裝入一個文件, 可用類似DOS的通配符(如*.C)來進行列表選擇。也可裝入其它
擴展名的文件, 只要給出文件名(或只給路徑)即可。該項的熱鍵為F3, 即只要在主
菜單中按F3即可進入該項, 而不需要先進入File菜單再選此項。
.Pick(選擇)
將最近裝入編輯窗口的8個文件列成一個表讓用戶選擇, 選擇後將該程序裝入
編輯區, 並將游標置在上次修改過的地方。其熱健為Alt-F3。
.New(新文件)
說明文件是新的, 預設文件名為NONAME.C, 存檔時可改名。
.Save(存檔)
將編輯區中的文件存檔, 若文件名是NONAME.C時, 將詢問是否更改文件名, 其
熱鍵為F2。
.Write to(存檔)
可由用戶給出文件名將編輯區中的文件存檔, 若該文件已存在, 則詢問要不要
覆蓋。
.Directory(目錄)
顯示目錄及目錄中的文件, 並可由用戶選擇。
.Change dir(改變目錄)
顯示當前目錄, 用戶可以改變顯示的目錄。
.Os shell(暫時退出)
暫時退出Turbo C 2.0到DOS提示符下, 此時可以運行DOS 命令, 若想回到
Turbo C 2.0中, 只要在DOS狀態下鍵入EXIT即可。
.Quit(退出)
退出Turbo C 2.0, 返回到DOS操作系統中, 其熱鍵為Alt+X。
說明:
以上各項可用游標鍵移動色棒進行選擇, 回車則執行。也可用每一項的第一個
大寫字母直接選擇。若要退到主菜單或從它的下一級菜單列表框退回均可用Esc鍵,
Turbo C 2.0所有菜單均採用這種方法進行操作, 以下不再說明。
(2)、Edit(編輯)菜單
按Alt+E可進入編輯菜單, 若再回車, 則游標出現在編輯窗口, 此時用戶可以
進行文本編輯。
編輯方法基本與wordstar相同, 可用F1鍵獲得有關編輯方法的幫助信息。
與編輯有關的功能鍵如下:
F1 獲得Turbo C 2.0編輯命令的幫助信息
F5 擴大編輯窗口到整個屏幕
F6 在編輯窗口與信息窗口之間進行切換
F10 從編輯窗口轉到主菜單
編輯命令簡介:
PageUp 向前翻頁
PageDn 向後翻頁
Home 將游標移到所在行的開始
End 將游標移到所在行的結尾
Ctrl+Y 刪除游標所在的一行
Ctrl+T 刪除游標所在處的一個詞
Ctrl+KB 設置塊開始
Ctrl+KK 設置塊結尾
Ctrl+KV 塊移動
Ctrl+KC 塊拷貝
Ctrl+KY 塊刪除
Ctrl+KR 讀文件
Ctrl+KW 存文件
Ctrl+KP 塊文件列印
Ctrl+F1 如果游標所在處為Turbo C 2.0庫函數, 則獲得有關該函數的幫助
信息
Ctrl+Q[ 查找Turbo C 2.0雙界符的後匹配符
Ctrl+Q] 查找Turbo C 2.0雙界符的前匹配符
說明:
a. Turbo C 2.0的雙界符包括以下幾種符號:
花括符 {和}
尖括符 <和>
圓括符 (和)
方括符 [和]
注釋符 /*和*/
雙引號 "
單引號 '
b. Turbo C 2.0在編輯文件時還有一種功能, 就是能夠自動縮進, 即游標定位
和上一個非空字元對齊。在編輯窗口中, Ctrl+OL為自動縮進開關的控制鍵。
(3)Run(運行)菜單
按Alt+R可進入Run菜單, 該菜單有以下各項:
.Run(運行程序)
運行由Project/Project name項指定的文件名或當前編輯區的文件。如果對上
次編譯後的源代碼未做過修改, 則直接運行到下一個斷點(沒有斷點則運行到結束)。
否則先進行編譯、連接後才運行, 其熱鍵為Ctrl+F9。
.Program reset(程序重啟)
中止當前的調試, 釋放分給程序的空間, 其熱鍵為Ctrl+F2。
.Go to cursor(運行到游標處)
調試程序時使用, 選擇該項可使程序運行到游標所在行。游標所在行必須為一
條可執行語句, 否則提示錯誤。其熱鍵為F4。
.Trace into(跟蹤進入)
在執行一條調用其它用戶定義的子函數時, 若用Trace into項, 則執行長條將
跟蹤到該子函數內部去執行, 其熱鍵為F7。
.Step over(單步執行)
執行當前函數的下一條語句, 即使用戶函數調用, 執行長條也不會跟蹤進函數
內部, 其熱鍵為F8。
.User screen(用戶屏幕)
顯示程序運行時在屏幕上顯示的結果。其熱鍵為Alt+F5。
(4)、Compile(編譯)菜單
按Alt+C可進入Compile菜單, 該菜單有以下幾個內容:
.Compile to OBJ(編譯生成目標碼)
將一個C源文件編譯生成.OBJ目標文件, 同時顯示生成的文件名。其熱鍵為
Alt+F9。
.Make EXE file(生成執行文件)
此命令生成一個.EXE的文件, 並顯示生成的.EXE文件名。其中.EXE文件名是下
面幾項之一。
a. 由Project/Project name說明的項目文件名。
b. 若沒有項目文件名, 則由Primary C file說明的源文件。
c. 若以上兩項都沒有文件名, 則為當前窗口的文件名。
.Link EXE file(連接生成執行文件)
把當前.OBJ文件及庫文件連接在一起生成.EXE文件。
.Build all(建立所有文件)
重新編譯項目里的所有文件, 並進行裝配生成.EXE文件。該命令不作過時檢查
(上面的幾條命令要作過時檢查, 即如果目前項目里源文件的日期和時間與目標文
件相同或更早, 則拒絕對源文件進行編譯)。
.Primary C file(主C文件)
當在該項中指定了主文件後, 在以後的編譯中, 如沒有項目文件名則編譯此項
中規定的主C文件, 如果編譯中有錯誤, 則將此文件調入編輯窗口, 不管目前窗口
中是不是主C文件。
.Get info(獲得有關當前路徑、源文件名、源文件位元組大小、編譯中的錯誤數
目、可用空間等信息。
(5)、Project(項目)菜單
按Alt+P可進入Project菜單, 該菜單包括以下內容:
.Project name(項目名)
項目名具有.PRJ的擴展名, 其中包括將要編譯、連接的文件名。例如有一個程
序由file1.c, file2.c, file3.c組成, 要將這3個文件編譯裝配成一個file.exe的
執行文件, 可以先建立一個file.prj的項目文件, 其內容如下:
file1.c
file2.c
file3.c
此時將file.prj放入Project name項中, 以後進行編譯時將自動對項目文件中
規定的三個源文件分別進行編譯。然後連接成file.exe文件。
如果其中有些文件已經編譯成.OBJ文件, 而又沒有修改過, 可直接寫上.OBJ擴
展名。此時將不再編譯而只進行連接。
例如: file1.obj
file2.c
file3.c
將不對file1.c進行編譯, 而直接連接。
說明:
當項目文件中的每個文件無擴展名時, 均按源文件對待, 另外, 其中的文件也
可以是庫文件, 但必須寫上擴展名.LIB。
.Break make on(中止編譯)
由用戶選擇是否在有Warining(警告)、Errors(錯誤)、Fatal Errors( 致命錯
誤)時或Link(連接)之前退出Make編譯。
.Auto dependencies(自動依賴)
當開關置為on, 編譯時將檢查源文件與對應的.OBJ文件日期和時間, 否則不進
行檢查。
.Clear project(清除項目文件)
清除Project/Project name中的項目文件名。
.Remove messages(刪除信息)
把錯誤信息從信息窗口中清除掉。
(6)、Options(選擇菜單)
按Alt+O可進入Options菜單, 該菜單對初學者來說要謹慎使用。
.Compiler(編譯器)
本項選擇又有許多子菜單, 可以讓用戶選擇硬體配置、存儲模型、調試技術、
代碼優化、對話信息控制和宏定義。這些子菜單如下:
Model
共有Tiny, small, medium, compact, large, huge 六種不同模式可由同戶選
擇。
Define
打開一個宏定義框, 同戶可輸入宏定義。多重定義可同分號, 賦值可用等號。
Code generation
它又有許多任選項, 這些任選項告訴編譯器產生什麼樣的目標代碼。
Calling convention 可選擇C或Pascal方式傳遞參數。
Instruction set 可選擇8088/8086或80186/80286指令系列。
Floating point 可選擇模擬浮點、數學協處理器浮點或無浮點運算。
Default char type 規定char的類型。
Alignonent 規定地址對准原則。
Merge plicate strings 作優化用, 將重復的字元串合並在一起。
Standard stack frame 產生一個標準的棧結構。
Test stack overflow 產生一段程序運行時檢測堆棧溢出的代碼。
Line number 在.OBJ文件中放進行號以供調試時用。
OBJ debug information 在.OBJ文件中產生調試信息。
Optimization
Optimize for 選擇是對程序小型化還是對程序速度進行優
化處理。
Use register variable 用來選擇是否允許使用寄存器變數。
Register optimization 盡可能使用寄存器變數以減少過多的取數操
作。
Jump optimization 通過去除多餘的跳轉和調整循環與開關語句
的辦法, 壓縮代碼。
Source
Indentifier length 說明標識符有效字元的個數, 默認為32個。
Nested comments 是否允許嵌套注釋。
ANSI keywords only 是只允許ANSI關鍵字還是也允許Turbo C
2.0關鍵字
Error
Error stop after 多少個錯誤時停止編譯, 默認為25個。
Warning stop after 多少個警告錯誤時停止編譯, 默認為100個。
Display warning
Portability warning 移植性警告錯誤。
ANSI Violations 侵犯了ANSI關鍵字的警告錯誤。
Common error 常見的警告錯誤。
Less common error 少見的警告錯誤。
Names 用於改變段(segment)、 組( group) 和類
(class)的名字, 默認值為CODE,DATA,BSS。
.Linker(連接器)
本菜單設置有關連接的選擇項, 它有以下內容:
Map file menu 選擇是否產生.MAP文件。
Initialize segments 是否在連接時初始化沒有初始化的段。
Devault libraries 是否在連接其它編譯程序產生的目標文件時去尋
找其預設庫。
Graphics library 是否連接graphics庫中的函數。
Warn plicate symbols 當有重復符號時產生警告信息。
Stack warinig 是否讓連接程序產生No stack的警告信息。
Case-sensitive link 是否區分大、小寫字。
.Environment(環境)
本菜單規定是否對某些文件自動存檔及製表鍵和屏幕大小的設置
Message tracking
Current file 跟蹤在編輯窗口中的文件錯誤。
All files 跟蹤所有文件錯誤。
Off 不跟蹤。
Keep message 編譯前是否清除Message窗口中的信息。
Config auto save 選on時, 在Run, Shell或退出集成開發環境之前,
如果Turbo C 2.0的配置被改過, 則所做的改動
將存入配置文件中。選off時不存。
Edit auto save 是否在Run或Shell之前, 自動存儲編輯的源文件。
Backup file 是否在源文件存檔時產生後備文件(.BAK文件)。
Tab size 設置製表鍵大小, 默認為8。
Zoomed windows 將現行活動窗口放大到整個屏幕, 其熱鍵為F5。
Screen size 設置屏幕文本大小。
.Directories(路徑)
規定編譯、連接所需文件的路徑, 有下列各項:
Include directories 包含文件的路徑, 多個子目錄用";"分開。
Library directories 庫文件路徑, 多個子目錄用";"分開。
Output directoried 輸出文件(.OBJ, .EXE, .MAP文件)的目錄。
Turbo C directoried Turbo C 所在的目錄。
Pick file name 定義載入的pick文件名, 如不定義則從current
pick file中取。
.Arguments(命令行參數)
允許用戶使用命令行參數。
.Save options(存儲配置)
保存所有選擇的編譯、連接、調試和項目到配置文件中, 預設的配置文件為
TCCONFIG.TC。
.Retrive options
裝入一個配置文件到TC中, TC將使用該文件的選擇項。
(7)、Debug(調試)菜單
按Alt+D可選擇Debug菜單, 該菜單主要用於查錯, 它包括以下內容:
Evaluate
Expression 要計算結果的表達式。
Result 顯示表達式的計算結果。
New value 賦給新值。
Call stack 該項不可接觸。而在Turbo C debuger 時用於檢
查堆棧情況。
Find function 在運行Turbo C debugger時用於顯示規定的函數。
Refresh display 如果編輯窗口偶然被用戶窗口重寫了可用此恢復
編輯窗口的內容。
(8)、Break/watch(斷點及監視表達式)
按Alt+B可進入Break/watch菜單, 該菜單有以下內容:
Add watch 向監視窗口插入一監視表達式。
Delete watch 從監視窗口中刪除當前的監視表達式。
Edit watch 在監視窗口中編輯一個監視表達式。
Remove all watches 從監視窗口中刪除所有的監視表達式。
Toggle breakpoint 對游標所在的行設置或清除斷點。
Clear all breakpoints 清除所有斷點。
View next breakpoint 將游標移動到下一個斷點處。
六 Turbo C 2.0的配置文件
所謂配置文件是包含Turbo C 2.0有關信息的文件, 其中存有編譯、連接的選
擇和路徑等信息。
可以用下述方法建立Turbo C 2.0的配置:
1. 建立用戶自命名的配置文件
可以從Options菜單中選擇Options/Save options命令, 將當前集成開發環境
的所有配置存入一個由用戶命名的配置文件中。下次啟動TC時只要在DOS下鍵入:
tc/c<用戶命名的配置文件名>
就會按這個配置文件中的內容作為Turbo C 2.0的選擇。
2. 若設置Options/Environment/Config auto save 為on, 則退出集成開發環
境時, 當前的設置會自動存放到Turbo C 2.0配置文件TCCONFIG.TC中。Turbo C 在
啟動時會自動尋找這個配置文件。
3. 用TCINST設置Turbo C的有關配置, 並將結果存入TC.EXE中。Turbo C 在啟
動時, 若沒有找到配置文件, 則取TC.EXE中的預設值。
『叄』 如何打包安卓手機Zip升級包如何簽名不換Recovery,用官方Recovery
通過分析update.zip包在具體Android系統升級的過程,來理解Android系統中Recovery模式服務的工作原理。
我們先從update.zip包的製作開始,然後是Android系統的啟動模式分析,Recovery工作原理,如何從我們上層開始選擇system update到重啟到Recovery服務,以及在Recovery服務中具體怎樣處理update.zip包升級的,我們的安裝腳本updater-script怎樣被解析並執行的等一系列問題。分析過程中所用的Android源碼是gingerbread0919(tcc88xx開發板標配的),測試開發板是tcc88xx。
一、 update.zip包的目錄結構
|----boot.img
|----system/
|----recovery/
`|----recovery-from-boot.p
`|----etc/
`|----install-recovery.sh
|---META-INF/
`|CERT.RSA
`|CERT.SF
`|MANIFEST.MF
`|----com/
`|----google/
`|----android/
`|----update-binary
`|----updater-script
`|----android/
`|----metadata
二、 update.zip包目錄結構詳解
以上是我們用命令make otapackage 製作的update.zip包的標准目錄結構。
1、boot.img是更新boot分區所需要的文件。這個boot.img主要包括kernel+ramdisk。
2、system/目錄的內容在升級後會放在系統的system分區。主要用來更新系統的一些應用或則應用會用到的一些庫等等。可以將Android源碼編譯out/target/proct/tcc8800/system/中的所有文件拷貝到這個目錄來代替。
3、recovery/目錄中的recovery-from-boot.p是boot.img和recovery.img的補丁(patch),主要用來更新recovery分區,其中etc/目錄下的install-recovery.sh是更新腳本。
4、update-binary是一個二進制文件,相當於一個腳本解釋器,能夠識別updater-script中描述的操作。該文件在Android源碼編譯後out/target/proct/tcc8800/system bin/updater生成,可將updater重命名為update-binary得到。
該文件在具體的更新包中的名字由源碼中bootable/recovery/install.c中的宏ASSUMED_UPDATE_BINARY_NAME的值而定。
5、updater-script:此文件是一個腳本文件,具體描述了更新過程。我們可以根據具體情況編寫該腳本來適應我們的具體需求。該文件的命名由源碼中bootable/recovery/updater/updater.c文件中的宏SCRIPT_NAME的值而定。
6、 metadata文件是描述設備信息及環境變數的元數據。主要包括一些編譯選項,簽名公鑰,時間戳以及設備型號等。
7、我們還可以在包中添加userdata目錄,來更新系統中的用戶數據部分。這部分內容在更新後會存放在系統的/data目錄下。
8、update.zip包的簽名:update.zip更新包在製作完成後需要對其簽名,否則在升級時會出現認證失敗的錯誤提示。而且簽名要使用和目標板一致的加密公鑰。加密公鑰及加密需要的三個文件在Android源碼編譯後生成的具體路徑為:
out/host/linux-x86/framework/signapk.jar
build/target/proct/security/testkey.x509.pem
build/target/proct/security/testkey.pk8 。
我們用命令make otapackage製作生成的update.zip包是已簽過名的,如果自己做update.zip包時必須手動對其簽名。
具體的加密方法:$ java –jar gingerbread/out/host/linux/framework/signapk.jar –w gingerbread/build/target/proct/security/testkey.x509.pem gingerbread/build/target/proct/security/testkey.pk8 update.zip update_signed.zip
以上命令在update.zip包所在的路徑下執行,其中signapk.jar testkey.x509.pem以及testkey.pk8文件的引用使用絕對路徑。update.zip 是我們已經打好的包,update_signed.zip包是命令執行完生成的已經簽過名的包。
9、MANIFEST.MF:這個manifest文件定義了與包的組成結構相關的數據。類似Android應用的mainfest.xml文件。
10、CERT.RSA:與簽名文件相關聯的簽名程序塊文件,它存儲了用於簽名JAR文件的公共簽名。
11、CERT.SF:這是JAR文件的簽名文件,其中前綴CERT代表簽名者。
另外,在具體升級時,對update.zip包檢查時大致會分三步:①檢驗SF文件與RSA文件是否匹配。②檢驗MANIFEST.MF與簽名文件中的digest是否一致。③檢驗包中的文件與MANIFEST中所描述的是否一致。
三、 Android升級包update.zip的生成過程分析
1) 對於update.zip包的製作有兩種方式,即手動製作和命令生成。
第一種手動製作:即按照update.zip的目錄結構手動創建我們需要的目錄。然後將對應的文件拷貝到相應的目錄下,比如我們向系統中新加一個應用程序。可以將新增的應用拷貝到我們新建的update/system/app/下(system目錄是事先拷貝編譯源碼後生成的system目錄),打包並簽名後,拷貝到SD卡就可以使用了。這種方式在實際的tcc8800開發板中未測試成功。簽名部分未通過,可能與具體的開發板相關。
第二種製作方式:命令製作。Android源碼系統中為我們提供了製作update.zip刷機包的命令,即make otapackage。該命令在編譯源碼完成後並在源碼根目錄下執行。 具體操作方式:在源碼根目錄下執行
①$ . build/envsetup.sh。
②$ lunch 然後選擇你需要的配置(如17)。
③$ make otapackage。
在編譯完源碼後最好再執行一遍上面的①、②步防止執行③時出現未找到對應規則的錯誤提示。命令執行完成後生成的升級包所在位置在out/target/proct/full_tcc8800_evm_target_files-eng.mumu.20120309.111059.zip將這個包重新命名為update.zip,並拷貝到SD卡中即可使用。
這種方式(即完全升級)在tcc8800開發板中已測試成功。
2) 使用make otapackage命令生成update.zip的過程分析。
在源碼根目錄下執行make otapackage命令生成update.zip包主要分為兩步,第一步是根據Makefile執行編譯生成一個update原包(zip格式)。第二步是運行一個python腳本,並以上一步准備的zip包作為輸入,最終生成我們需要的升級包。下面進一步分析這兩個過程。
第一步:編譯Makefile。對應的Makefile文件所在位置:build/core/Makefile。從該文件的884行(tcc8800,gingerbread0919)開始會生成一個zip包,這個包最後會用來製作OTA package 或者filesystem image。先將這部分的對應的Makefile貼出來如下:
[python] view plainprint?
# -----------------------------------------------------------------
# A zip of the directories that map to the target filesystem.
# This zip can be used to create an OTA package or filesystem image
# as a post-build step.
#
根據上面的Makefile可以分析這個包的生成過程:
首先創建一個root_zip根目錄,並依次在此目錄下創建所需要的如下其他目錄
①創建RECOVERY目錄,並填充該目錄的內容,包括kernel的鏡像和recovery根文件系統的鏡像。此目錄最終用於生成recovery.img。
②創建並填充BOOT目錄。包含kernel和cmdline以及pagesize大小等,該目錄最終用來生成boot.img。
③向SYSTEM目錄填充system image。
④向DATA填充data image。
⑤用於生成OTA package包所需要的額外的內容。主要包括一些bin命令。
⑥創建META目錄並向該目錄下添加一些文本文件,如apkcerts.txt(描述apk文件用到的認證證書),misc_info.txt(描述Flash內存的塊大小以及boot、recovery、system、userdata等分區的大小信息)。
⑦使用保留連接選項壓縮我們在上面獲得的root_zip目錄。
⑧使用fs_config(build/tools/fs_config)配置上面的zip包內所有的系統文件(system/下各目錄、文件)的許可權屬主等信息。fs_config包含了一個頭文件#include「private/android_filesystem_config.h」。在這個頭文件中以硬編碼的方式設定了system目錄下各文件的許可權、屬主。執行完配置後會將配置後的信息以文本方式輸出 到META/filesystem_config.txt中。並再一次zip壓縮成我們最終需要的原始包。
第二步:上面的zip包只是一個編譯過程中生成的原始包。這個原始zip包在實際的編譯過程中有兩個作用,一是用來生成OTA update升級包,二是用來生成系統鏡像。在編譯過程中若生成OTA update升級包時會調用(具體位置在Makefile的1037行到1058行)一個名為ota_from_target_files的python腳本,位置在/build/tools/releasetools/ota_from_target_files。這個腳本的作用是以第一步生成的zip原始包作為輸入,最終生成可用的OTA升級zip包。
二 下面我們分析ota_from_target_files這個python腳本是怎樣生成最終zip包的。先講這個腳本的代碼貼出來如下:
[python] view plainprint?
import sys
if sys.hexversion < 0x02040000:
print >> sys.stderr, "Python 2.4 or newer is required."
sys.exit(1)
主函數main是python的入口函數,我們從main函數開始看,大概看一下main函數(腳本最後)里的流程就能知道腳本的執行過程了。
① 在main函數的開頭,首先將用戶設定的option選項存入OPTIONS變數中,它是一個python中的類。緊接著判斷有沒有額外的腳本,如果有就讀入到OPTIONS變數中。
② 解壓縮輸入的zip包,即我們在上文生成的原始zip包。然後判斷是否用到device-specific extensions(設備擴展)如果用到,隨即讀入到OPTIONS變數中。
③ 判斷是否簽名,然後判斷是否有新內容的增量源,有的話就解壓該增量源包放入一個臨時變數中(source_zip)。自此,所有的准備工作已完畢,隨即會調用該 腳本中最主要的函數WriteFullOTAPackage(input_zip,output_zip)
④ WriteFullOTAPackage函數的處理過程是先獲得腳本的生成器。默認格式是edify。然後獲得metadata元數據,此數據來至於Android的一些環境變數。然後獲得設備配置參數比如api函數的版本。然後判斷是否忽略時間戳。
⑤ WriteFullOTAPackage函數做完准備工作後就開始生成升級用的腳本文件(updater-script)了。生成腳本文件後將上一步獲得的metadata元數據寫入到輸出包out_zip。
⑥至此一個完整的update.zip升級包就生成了。生成位置在:out/target/proct/tcc8800/full_tcc8800_evm-ota-eng.mumu.20120315.155326.zip。將升級包拷貝到SD卡中就可以用來升級了。
四、 Android OTA增量包update.zip的生成
在上面的過程中生成的update.zip升級包是全部系統的升級包。大小有80M多。這對手機用戶來說,用來升級的流量是很大的。而且在實際升級中,我們只希望能夠升級我們改變的那部分內容。這就需要使用增量包來升級。生成增量包的過程也需要上文中提到的ota_from_target_files.py的參與。
下面是製作update.zip增量包的過程。
① 在源碼根目錄下依次執行下列命令
$ . build/envsetup.sh
$ lunch 選擇17
$ make
$ make otapackage
執行上面的命令後會在out/target/proct/tcc8800/下生成我們第一個系統升級包。我們先將其命名為A.zip
② 在源碼中修改我們需要改變的部分,比如修改內核配置,增加新的驅動等等。修改後再一次執行上面的命令。就會生成第二個我們修改後生成的update.zip升級包。將 其命名為B.zip。
③ 在上文中我們看了ota_from_target_files.py腳本的使用幫助,其中選項-i就是用來生成差分增量包的。使用方法是以上面的A.zip 和B.zip包作為輸入,以update.zip包作 為輸出。生成的update.zip就是我們最後需要的增量包。
具體使用方式是:將上述兩個包拷貝到源碼根目錄下,然後執行下面的命令。
$ ./build/tools/releasetools/ota_from_target_files -i A.zip B.zip update.zip。
在執行上述命令時會出現未找到recovery_api_version的錯誤。原因是在執行上面的腳本時如果使用選項i則會調用WriteIncrementalOTAPackage會從A包和B包中的META目錄下搜索misc_info.txt來讀取recovery_api_version的值。但是在執行make otapackage命令時生成的update.zip包中沒有這個目錄更沒有這個文檔。
此時我們就需要使用執行make otapackage生成的原始的zip包。這個包的位置在out/target/proct/tcc8800/obj/PACKAGING/target_files_intermediates/目錄下,它是在用命令make otapackage之後的中間生產物,是最原始的升級包。我們將兩次編譯的生成的包分別重命名為A.zip和B.zip,並拷貝到SD卡根目錄下重復執行上面的命令:
$ ./build/tools/releasetools/ota_form_target_files -i A.zip B.zip update.zip。
在上述命令即將執行完畢時,在device/telechips/common/releasetools.py會調用IncrementalOTA_InstallEnd,在這個函數中讀取包中的RADIO/bootloader.img。
而包中是沒有這個目錄和bootloader.img的。所以執行失敗,未能生成對應的update.zip。可能與我們未修改bootloader(升級firmware)有關。此問題在下一篇博客已經解決。
製作增量包失敗的原因,以及解決方案。
Android系統Recovery工作原理之使用update.zip升級過程分析(二)---update.zip差分包問題的解決
在上一篇末尾提到的生成差分包時出現的問題,現已解決,由於最近比較忙,相隔的時間也比較長,所以單列一個篇幅提示大家。這個問題居然是源碼中的問題,可能你已經製作成功了,不過我的這個問題確實是源碼中的一個問題,不知道是不是一個bug,下文會具體分析!
一、生成OTA增量包失敗的解決方案
在上一篇中末尾使用ota_from_target_files腳本製作update.zip增量包時失敗,我們先將出現的錯誤貼出來。
在執行這個腳本的最後讀取input_zip中RADIO/bootloader.img時出現錯誤,顯示DeviceSpecifiParams這個對象中沒有input_zip屬性。
我們先從腳本中出現錯誤的調用函數中開始查找。出現錯誤的調用地方是在函WriteIncrementalOTAPackage(443行)中的device_specific.IncrementalOTA_InstallEnd(),其位於WriteIncrementalOTAPackage()中的末尾。進一步跟蹤源碼發現,這是一個回調函數,他的具體執行方法位於源碼中/device/telechips/common/releasetools.py腳本中的IncrementalOTA_InstallEnd()函數。下面就分析這個函數的作用。
releasetools.py腳本中的兩個函數FullOTA_InstallEnd()和IncrementalOTA_InstallEnd()的作用都是從輸入包中讀取RADIO/下的bootloader.img文件寫到輸出包中,同時生成安裝bootloader.img時執行腳本的那部分命令。只不過一個是直接將輸入包中的bootloader.img鏡像寫到輸出包中,一個是先比較target_zip和source_zip中的bootloader.img是否不同(使用選項-i生成差分包時),然後將新的鏡像寫入輸出包中。下面先將這個函數(位於/device/telechips/common/releasetools.py)的具體實現貼出來:
我們的實際情況是,在用命令make otapackage時生成的包中是沒有這個RADIO目錄下的bootloader.img鏡像文件(因為這部分更新已被屏蔽掉了)。但是這個函數中對於從包中未讀取到bootloader.img文件的情況是有錯誤處理的,即返回。所以我們要從 出現的實際錯誤中尋找問題的原由。
真正出現錯誤的地方是:
target_bootloader=info.input_zip.read(「RADIO/bootloader.img」)。
出現錯誤的原因是:AttributeError:『DeviceSpecificParams』object has no attribute 『input_zip』,提示我們DeviceSpecificParams對象沒有input_zip這個屬性。
二、updater-script腳本執行流程分析:
先看一下在測試過程中用命令make otapackage生成的升級腳本如下:
[python] view plainprint?
assert(!less_than_int(1331176658, getprop("ro.build.date.utc")));
assert(getprop("ro.proct.device") == "tcc8800" ||
下面分析下這個腳本的執行過程:
①比較時間戳:如果升級包較舊則終止腳本的執行。
②匹配設備信息:如果和當前的設備信息不一致,則停止腳本的執行。
③顯示進度條:如果以上兩步匹配則開始顯示升級進度條。
④格式化system分區並掛載。
⑤提取包中的recovery以及system目錄下的內容到系統的/system下。
⑥為/system/bin/下的命令文件建立符號連接。
⑦設置/system/下目錄以及文件的屬性。
⑧將包中的boot.img提取到/tmp/boot.img。
⑨將/tmp/boot.img鏡像文件寫入到boot分區。
⑩完成後卸載/system。
三、總結
以上的九篇著重分析了Android系統中Recovery模式中的一種,即我們做好的update.zip包在系統更新時所走過的流程。其核心部分就是Recovery服務的工作原理。其他兩種FACTORY RESET、ENCRYPTED FILE SYSTEM ENABLE/DISABLE與OTA INSTALL是相通的。重點是要理解Recovery服務的工作原理。另外詳細分析其升級過程,對於我們在實際升級時,可以根據我們的需要做出相應的修改。
『肆』 如何C語言與匯編混編
c語言可以嵌套匯編:
按照TC2.0的幫助系統所以說的,在TC2.0下是可以用匯編的,方法是使用asm關鍵字:其格式是:
asm opcode <operands> <;newline>,如同別的注釋一樣,<>之間的表示可選的;例如:
main()
{
char *c="hello,world/n/r$";
asm mov ah,9;asm mov dx,c;asm int 33;
printf("You sucessed!/n");
}
或者是:
main()
{
char *c="hello,world/n/r$";
asm mov ah,9
asm mov dx,c
asm int 33
printf("You sucessed!");
}
兩種格式其實是一種.如果你用的是第一種的樣式,記住:
每一句匯編語句都要以asm開頭,如果一行內有多個句子,
那麼千萬不要忘記在兩個句子之間的這個semicolon(分號),
但是最後一句匯編後面(如果後面沒有其它的語句)的分號可有可無,象第一個例子中的
asm int 33;後面的分號就可以不要,因為它的後面沒有其它
的語句了.但如果是這樣:
asm mov ah,9; asm mov dx,c;asm int 33; printf("You sucessed!");
那麼asm int 33;後面的分號便還是留下好,以免出現編譯錯誤!
在這一點上頗象C語言.
還有一種格式是
asm{ assembly language statement},這種格式應該被普遍的歡迎.
它們的例子如下(其中的語句排列格式與上面兩種相同):
asm{
mov ax,var1
add ax,var2
......
}
但是要注意這種格式TC2.0是不支持的!
只有後來的TC++3.0及後來的IDE支持!
工具的使用:
一旦你的C源文件里包括了這些好東西,則必須用TCC.EXE的COMMAND-LINE來編譯,具體的命令參數TCC.EXE已經提供,這里不復闡述了.最簡單的是:TCC C源文件名(使用這個方法,TCC會自動調用TASM.EXE和TLINK.EXE,並且能夠使TLINK.EXE正確的找到需要的.obj和.lib文件,如果你單步編譯的話,可能會碰到很多的問題,主要是TLINK.EXE它自己並不會去找.obj和.lib文件,你自己可以建一個.bat文件,如果要指定.lib文件的目錄的話可以用/L參數,在文章的後面有一個例子).但大家要注意了,看一下你的TC目錄下面到底是否有TASM.EXE文件,並在TURBOC.CFG(這個文件包括TCC.EXE運行期參數,這裡面所有參數在運很期都將被自動TCC.EXE使用,例如:-IH:/TC/INCLUDE/
-LH:/TC/LIB/)文件中設置好一些參數,並確認TASM.EXE的版本號要2.0以上,以及是否能夠向下兼容.但是在大多數的情況下TC的目錄是沒有TASM.EXE的,或是版本不正常.
如果你有TASM.EXE文件並且TURBOC.CFG文件也已經寫好了,但是還要注意一個
問題:運行TCC.EXE時要在獨立的DOS SHELL下面(不要害怕,這不是一個新東西,我的意思
是,不在諸如TC下的DOS SHELL下面運行,我曾經敗在這個問題下,當我發現時直想揍電腦
一頓,還好沒有,不然就沒有這篇文件了.)
還有一句重要的話:TC2.0支持大部分8086指令(當然用法有一些約定,不過現在我並不打算
進行詳細說明,因為那是一件很繁雜的事,以後有時間或許會寫出來----如果大家需要的話).
如果說上面我所說的那些約定很繁雜的話,那麼下面的方法該是多麼簡單啊!
讓我們使用Borland為TC2.0內建的變數來進行偽匯編.
或許你還不知道在TC2.0中還有一些內建的pseudo寄存器(可以看作是register 型的變數,但是它們比register型的變數好用的多)
_AX,_AH,_AL,
_BX,_BH,_BL,
_CX,_CH,_CL,
_DX,_DH,_DL,
_DI,_SI,_SP,
_CS,_DS,_ES,_SS
注意這些寄存器的size,_AX,_BX,_CX,_DX,_CS,_DS,_ES,_SS,_SI,_DI,_SP等都是16位的寄存器相當於C語言的unsigned int類型,其餘的都是8位的寄存器(相當於unsigned char)(TC怎麼可能支持32位的寄存呢,所以EAX等是不能用的,FS,GS和IP寄存器都是無效的),還有就是在傳遞參數的時候千萬不要忘記使用強制類型轉換.
中斷調用指令是:__int__(interrupt_#)(注意int的前輟和後輟都是兩個underscores)
For example:
#include<dos.h>
unsigned int _stklen=0x200;
unsigned int _heaplen=0;
main()
{
_DX=(unsigned int)"Hello,world./r/n$";
_AX=0x900;
__int__(0x21);
}
dos.h它是包含__int__()內建中斷調用語句的頭文件,因此是不可
缺少的._stklen和_heaplen是定義運行期堆棧和堆大小的兩個內部
引用變數(這是個我自己想的名詞,意指如果這兩個變數在源文件中
顯式的聲明了,那麼編譯程序會自會引用來構造編譯時期的信息以產生
用戶希望的目標文件,如果不顯式的聲明則編譯程序自動確定).
這兩個變數也有一些約定,如果_stklen不顯式聲明,_heaplen賦值為零
都表示棧和堆都是defult的.
最後在TC2.0中還有一個沒有說明的標志位寄存器flags,它也是內建
pseudo寄存器是:_FLAGS,是一個16位寄存器.這些內建的寄存器都可以進行
運算,但是要注意它們所代表的類型(必要時進行類型轉換);
看起來這是不是一種好的辦法啊(而且使用這種方法只要用個一個dos.h頭文件就好,
不需要用TCC編譯,可以直接在TC20的IDE下編譯).
TC2.0中也提供了一些簡單好用的函數來實現對DOS功能的調用如:
int86(...),int86x(...)(但是這些方法實際仍然要調用函數,所以不如使用
偽寄存器,又因為要牽涉到union REGS結構的內存分配所以系統的開銷是增大了,
而使用偽寄存器是最簡潔的),埠通信函數如:inportb(...),inport(...),
outportb(...),outport(...),指針轉換函數:FP_OFF,FP_SEG,MK_FP,這些函數在
幫助系統中都有,有用時大家可以查閱.
tlinkbat.bat的例子:
rem The lib environment variable is the directory of the .obj and .lib file
set lib=h:/tc/lib/
rem 這下面的句子中的c0s(C 零S)是一個.OBJ文件,是一個C程序的STARTUP文件
tlink %lib%c0s %1,%1,%1,/L%lib%emu.lib %lib%maths.lib %lib%cs.lib
set lib=
(使用時可將以rem開頭的句子刪除)
___________________________________________________
一些約定:
我們先說一下在TC20下寫匯編(內聯匯編--自己起的名字,大家可以想叫什麼叫什麼)時的編譯器的編譯原則:
1.所有在main()函數外的的匯編語言的語句都作為數據聲明語句處理,也即在編譯器編譯時會將它放在數據段中,如:
asm string1 db "Hello",,,'world!',0ah,0xd,"$"
main()
{
asm mov dx,offset string1
asm mov ah,9
asm int 33
asm mov dx,offset string2
asm int 33
}
asm string2 db "the string can be declared after the main() function!$"
象這些樣子在main()外面的匯編語言的數據定義語句(事實上不管是什麼匯編語句,
只要是在main()之外,包括這個句子:asm mov ax,0x4c00),在編譯後都放在數據段中,而C語言的數據聲明語句仍按C的規則!
2.所有在main()函內的匯編語言的語句在編譯後都放在代碼段中,包括這個句子:
asm string2 db "the string can be declared after the main() function!$"
3.不要在以asm 開頭的語句中使用C語言的關鍵字,這會導致編譯階段的錯誤
那麼,根據這三條大家會得到什麼樣的結論呢?(先閉上眼想一想,你可能會由此變的
很贊賞自己,是的你應該這樣相信自己是對的!)
讓我們一起看一下這個結論:
1.根據編譯原則1得到:不可以在main()外面寫匯編命令語句(不要笑,正是與C語言相同才值得注意!),在任何地方都不要進行任何的段定義和宏定義(這是因為編譯後的形式決定的,也即:在TC20下所有的匯編格式的語句只能是,直接性的數據定義和語句指令)!
2根據編譯原則2得到:不可以在main()之內使用匯編的語句進行數據定義(同樣不要笑,
大多數人在第一次在TC20下寫匯編都會有這樣的錯誤的)
3.如同類強制類型這樣的事是不可以在以asm開頭的匯編語句中使用的
好了,天即朗,氣瞬清!這樣一說,一個大體的框架就出來了!只要遵守這個原則寫,就可避免很多莫名其妙的錯誤出現!
通俗的說:
匯編語句的數據定義放在main()外面,指令放在main()裡面.
如果你沒有更好的文檔,那麼記住我的這些話!
一些細節的問題:
在以asm開頭的內聯匯編語句中是不支持C的轉義字元的,但是用C語言聲明一個字元數組(含有轉義字元的),然後用int 33 ah=9這功能時輸出這個字元串時,其中的轉義字元是有效的(這主要是因為編譯後其內部表示形式不同造成的,自己想想會有答案的).
內聯匯編支持C的一些如數值表示,字元串聲明格式等,
如:一個十六進制的數據可以用兩種方式表示:0xa 和0ah,字元串可以是這樣:
"Hello,world!$"(如同C)也可以這樣'Hello,world!$'(用匯編自己的方式).
象C一樣你同樣要注意賦值的類型,而且要比C更嚴格(匯編從來不自己動手做
如同類型轉換啊這樣事),所以一切的事完全要你自己做好!而且你不要企圖以C的形式
做這件事,如這樣的格式 asm mov dx,(unsigned)a(a是一個這樣的東西,
char a[ ]="hello,world!";),而且這樣句子也會導致錯誤:asm mov dx,word ptr a(邏輯錯誤),不過這不是在編譯時的錯誤,而是運行期的錯誤(具體的原因自己想一想,象word label這樣的東西的運算作用和會導致的後果),你可以這樣用一個句子做"中間人"如int i=(unsigned)a;asm mov dx,i(也千萬不要用asm mov dx,(unsigned)a 這樣的句子.但是,告訴大家一個好消息,你可以用指針指向一個字元串,然後你會驚訝你竟然可以這樣:
char *p="hello,world";asm mov dx,p,然後用int 33 ah=9的功能輸出這個字元串而不會有錯誤(這也表現出指針的特點,它是一個二位元組的(TC20下)變數,含有的是一個地址,這與其指向的變數的類型是毫無關系的).
內匯匯編語句不支持->這個運算符.還有標號的問題,在最後的例子中你會年看到一些特別之處!
上面所說的只是很細小並微少的一些事(也是很常遇到的),尚有很多的細節要說,但由於本人時間有限不能一一列舉,如C的結構在內聯匯編的應用等大家可以按照其運行機理去想想一下用法;另外,由於這只是一件學習的事,所以還是大家自己學(找一下有關文檔,當然現在已經沒有什麼比較完整的了),情況會好的多,我在對內聯匯編的學習過程中領會到了不少的東西,例如編譯原理方面的知識,以及如何做會使代碼更高效,占空間最少等的方法.最後向大家推薦一種方法,在利用TCC的-S開關可以生成C源文件的匯編代碼
(或許很多的人都用過)是很好的學習材料!祝大家學有所成!
Cstarter
02-11-17
/* 由於個人的時間和能力有限,難免有錯誤和不詳細的地方,請大家見諒!
My Email:[email protected] [email protected] QQ:170594633 */
一些例子:
下面這個例子是對沈美明 溫冬嬋的
<<IBM-PC 匯編語言程序設計>>清華版第十一章程序的改寫
可直接在命令行上鍵入 tcc filename 就可以,當然你要有TASM.EXE
/*
asm mus_frep dw 330,294,262,294,3 p(330)
asm dw 3 p(294),330,392,392
asm dw 330,294,262,294,4 p(330)
asm dw 294,294,330,294,262,-1
asm mus_time dw 6 p(25),50
asm dw 2 p (25,25,50)
asm dw 12 p(25),100
*/
asm mus_frep dw 330,392,330,294,330,392,330,294,330
asm dw 330,392,330,294,262,294,330,392,294
asm dw 262,262,220,196,196,220,262,294,330,262
asm dw -1
asm mus_time dw 3 p (50),25,25,50,25,25,100
asm dw 2 p (50,50,25,25),100
asm dw 3 p (50,25,25),100
main()
{
asm jmp start
/*設置發聲的頻率,這一段在沈美明 溫冬嬋的
<<IBM-PC 匯編語言程序設計>>清華版第十一章有詳細的說明 */
sound:
asm mov al,0b6h
asm out 43h,al
asm mov dx,12h
asm mov ax,533h*896
asm div di
asm out 42h, al
asm mov al,ah
/* 這個延時是用來防止兩次IO操作的最後一次操作的錯誤,
因為CPU比匯流排的速度快很多,所以 要延時等待第一次操作完成後再進行第二次操作*/
asm mov cx,1000
delay:
asm loop delay
asm out 42h,al
asm in al,61h
asm mov ah,al
asm or al,3
asm out 61h,al
/* 使用中斷15H功能86H延時CX:DX=微秒數*/
asm mov ax,2710h
asm mul bx
asm mov cx,dx
asm mov dx,ax
asm mov ah,86h
asm int 15h /*可用__int__(0x15);代替*/
asm mov al,ah
asm out 61h,al
asm jmp add_count
/*------------------*/
start:
asm mov si,offset mus_frep
asm lea bp,mus_time
frep:
asm mov di,[si]
asm cmp di,-1
asm je end_mus
asm mov bx,[bp]
asm jmp sound
add_count: /*標號不能用匯編語言寫*/
asm add si,2
asm add bp,2
asm jmp frep
end_mus:;
}
對於上面的程序大家可用偽寄存器的方法寫一個,要容易的多!
/*一個發聲程序!(引自<<PC技術內幕>>電力版--這個版不好,不如清華版的)*/
#include"dos.h"
main()
{
static union REGS ourregs;
outportb(0x43,0xb6);
outportb(0x42,0xee);
outportb(0x42,0);
outportb(0x61,(inportb(0x61)|0x03));
ourregs.h.ah=0x86;
ourregs.x.cx=0x001e;
ourregs.x.dx=0x8480;
int86(0x15,&ourregs,&ourregs);
outportb(0x61,(inportb(0x61)&0xfc));
}
『伍』 C語言編譯產生的.OBJ文件和匯編編譯產生的.OBJ文件,如何連接
一同學習。。。
Trubo C的命令行編譯連接
所謂命令行編譯,是指在dos下,調用Trubo C的tcc.exe程序.來完成對turbo C源程序的編譯連接工作.當選擇對後綴為*.asm的匯編程序文件編譯時,tcc還要調用TASM後才能對後綴為.asm的文件進行編譯,這種方式適合於c程序與匯編語言混合編程的編譯連接,當c程序嵌入匯編指令時,也必須用此方法編譯連接。
命令行編譯的格式為:
tcc [選項1 選項2 ...]文件名1 文件名2...其中選項是指對後面給出的文件進行連接時的選擇項,可選的常用選擇項如下所示:每個選項前都帶有"-"號,且大小寫是區分的。文件名是指源文件.c或目標文件.obj或庫文件.lib當不指定只編譯不連接時,tcc將完成編譯和連接兩個步驟,對.lib庫只進行形式上的連接,標准庫用戶不用進行連接。
例如:
tcc -ib:\include -lb:\lib -etest start.c body.obj myc當執行該命令時,表示將start.c源文件和body.obj目標文件及myc.c(命令行中該文件無後綴),分別進行編譯(對body.obj文件不再編譯),然後連接生成名為test的執行文件test.exe(由-test給出).
-ib:\include 表示包含文件的路徑是b:\include
-ib:\lib 表示庫文件的路徑是b:\lib
又例如:
tcc -ms -efile -lc:\tc\lib file1 file2.obj graphics.lib
其中-ms表示選擇小內存模式進行編譯,它也是turbo c的預設編譯模式,將file1進行編譯,然後和file2.obj 及graphics.lib進行連接.生成file.exe的可執行文件.其中graphcis.lib庫的路徑為c:\tc\lib,即意為在c:\tc\lib目錄下去尋找graphics.lib文件.當進行混合編程時,如果已有匯編程序s3.asm其命令行可寫為
tcc ic:\tc\include -lc:\tc\lib -mm s1 s2 s3.asm mylib.lib
表示用中模式(-mm)編譯源文件s1.c和s2.c,調用TASM對s3.asm進行編譯,然後連接生成可執行文件s1.exe,編譯時,到c:\tc\include目錄中去找包含文件,到
c:\tc\lib目錄中去找庫文件mylib.lib.
---------------------------------------
http://topic.csdn.net/t/20010308/22/81569.html
http://www.down22.org/plus/view.php?aid=15882
比VC難用。。。
『陸』 tcc和gcc編譯器的區別
tcc:小,僅c語言gcc:大, 僅c語言g++:大,c十十支持
『柒』 TKstudi C編譯器怎麼設置
VC就很了不起,因為使用這樣傻瓜化的工具只能讓你看不到事物的本質。接下來我們就來深入的認識Turbo C編譯器。 廣義的編譯器,包括了代碼編譯器(compiler),目標文件鏈接器(linker),庫文件管理工具(如tc的tlib,gcc的ar),編譯驅動工具(如VC的NMake,gcc的make),ANSI c/c++標準的頭文件和庫文件,擴展的頭文件和庫文件,集成開發環境(IDE),等等與編譯相關的工具,所有這些工具的集合,就組成了廣義上的編譯器。
狹義的編譯器,則僅指compiler。compiler只負責將源代碼,即.c/.cxx/.cpp文件編譯成為目標文件.o/.obj。編譯過程的輸入是源文件,包括自己書寫的.c和.h以及系統提供的.h文件,編譯的輸出是目標文件。需要強調的一點時,在compile階段,只處理源文件,所以不需要庫文件和額外的目標文件的參與,因此,只要代碼在語法上沒有錯誤,compile就一定能產生目標文件。
對於一個廣義的編譯器來說以下幾個部分是必備的:1.compiler,2.linker,3.系統提供的頭文件和庫文件。前面已經介紹了compiler,接下來看linker。
linker的功能是將目標文件進行裝配,將浮動的地址變為確定的地址,這個工作是通過修改目標文件的重定位項來實現的,其具體的過程可以參考"Linker & loader"這本書,這是一本詳細介紹linker和loader的好書,在此做個推薦。總之,link這一階段處理的輸入是目標文件,其輸出是可執行文件,或動態庫。
任何一個編譯器都會提供庫文件和與之對應的頭文件,C/C++編譯器一般都提供ANSI C/C++的庫和相應的頭文件。
從現在起我們就需要建立起一個概念,就是廣義的編譯過程,實際上是由編譯和鏈接兩個基本步驟組成的,如果能深刻的理解這兩個步驟,就是一大進步了。
在編譯器里,有一些默認的規定,我們需要了解。在編譯器中,bin目錄用於存放compiler、linker等工具,include目錄用於存放頭文件,lib目錄用存放庫文件,大多數的編譯器的目錄就是按這個來組織的。
接下來看Turbo C為我們提供了些什麼
bin目錄中:
CPP.EXE 是一個C語言預處理工具,就是負責對源代碼進行預編譯處理,不要理解為c++編譯器
TCC.EXE 是一個C語言的編譯器,可以將代碼編譯為目標文件,並且能自動調用tlink鏈接生成可執行文件
TASM.exe 是一個匯編工具,可以將x86的匯編代碼編譯成為目標文件
TLink.exe 是一個鏈接器,負責對目標文件、庫文件等進行鏈接
TLib.exe 是一個庫文件管理工具,可以將多個目標文件打包到一個庫文件里
BGIOBJ.exe 可以將BGI文件轉換為.obj文件
make.exe 符合GNU標準的make工具,可用於代碼編譯的管理
TURBOC.CFG tcc默認的編譯參數配置文件
以上所有的工具的使用方法都可以直接鍵入相應的命令進行查看,如鍵入tcc即可看到tcc的使用方法,因此這里不再講解。
BGI目錄中:
EGAVGA.BGI 是EGAVGA的bgi驅動
FONT目錄中:存放了BGI所使用到的各種字體文件
INCLUDE目錄中:是Turbo C的庫函數的所有的頭文件,當要使用某個庫函數時可以在這個目錄下搜索,找到其所在文件和原型,這里不在詳細敘述。
重點講一下Lib目錄:
init.obj文件是C語言的啟動代碼,它負責建立C程序運行的堆棧、初始化內存、調用C入口函數等。這部分代碼是使用匯編書寫的,其源代碼可以在TC(官方版)里找到,名稱為Init.ASM。
c0t.obj、c0s.obj、c0m.obj、c0c.obj、c0l.obj和c0h.obj文件,都是c code的入口函數實現,入口函數將會讀取環境變數,並調用c語言中的main函數,將命令行參數傳入main函數中,之後的控制權就交給了main函數,也就是我們常說的C的主函數main。由於Turbo C中有不同的內存模式,因此以上6個文件分別對應TC中6種不同的內存模式。
cc.lib、ch.lib、cl.lib、cm.lib、cs.lib五個文件都是TC提供的ANSI C標准庫的庫文件,分別對用不同的內存模式:
cc compact模式
ch huge模式
cl large模式
cm medium模式
cs small模式
『捌』 在TC中,怎樣用命令編譯lib庫
定義函數庫的方法及應用:
一、2個相關的命令
1、TCC——TC的DOS下的命令行編譯連接工具
2、TLIB——TC的DOS下的庫操作工具
二、1個自定義的函數庫的例子
1、
在TC集成環境下,編一個文件USERADD.C
#define
_NO_MAIN
int
add(int
*a,int
*b)
{
int
c;
c=(*a)+(*b);
return
c;
}
按ALT—F9編譯
生成一個
USERADD.OBJ文件。
2、按F10—F—O
退到DOSSHELL(DOS環境下)
COPY
USERADD.OBJ
到
..\LIB目錄,在\LIB目錄下執行
TLIB
USERLIB.LIB+USERADD.OBJ
就生成了一個自己的函數庫
USERLIB,在這擾猜喚個函數庫里就包含了函數模塊
int
add(int
*a,int
*b)
的二進制代碼。現在已經將自定義的函數放進了函數庫,就可以把原文件USERADD.C刪掉不要了。(當然,為了以後維護方便,還是作一個備份為好)。
以後如有其它的函數模塊,也可以編譯後用TLIB
命令加入到這個函數庫里。
3、寫一個包含文件
USER1.H,寫完後COPY到INCLUDE
目錄。內容如下:
int
add(int
*,int
*);
4、兆段作好了以上的自定義函數庫的准備工作,現在就可以使用了。
寫一個程序,取名為ADD-1.C,在程序中緩凱調用庫函數add(
);
#include
#include
void
main(
)
{
int
a,b,c;
a=20;b=30;
c=add(&a,&b);
printf(「%d」,c);
}
5、在DOS命令行下,執行
TCC
ADD-1.C
..\LIB\USERLIB.LIB
就OK!
運行ADD-1.EXE,可以看到輸出結果
50
Tc生成lib的方法:
擴展庫與自建LIB庫使用擴展庫TC所帶的庫在有的情況下是無法滿足功能要求的,自己寫一個太麻煩,找到了一個LIB庫又怕不會用。在WIN-TC中,對於使用外部的擴展庫(第三方LIB)提供了一個方便的解決方法:首先要確定你的LIB庫是FOR
TC版本的而不是FOR
VC或是其它的。如果確定是FOR
TC的版本的話就把你的首標文件(或稱頭文件),就是擴展名為*.h的文件拷貝到WIN-TC的include目錄里,然後把相應名稱的*.lib文件拷貝到lib目錄,然後再運行WIN-TC時選擇「編譯配置」菜單項,你會看到擴展庫信息欄目里有你的LIB庫文件名在上面了,但是沒有打鉤。然後你把它鉤選後再「確定」保存,以後的編譯程序時就自動鏈接該擴展庫了。自建立LIB庫將自己的代碼編譯成LIB庫的格式有利與保護自己的代碼版權。如何來生成自己的LIB庫呢?請按照下面的方法:
STEP
1——生成目標代碼(OBJ)
建立mylib的代碼文件/*********************
mylib.c
*********************/void
myfun(){printf("
myfun()
in
mylib.lib
");}然後保存為WIN-TC目錄下的mylib.c文件然後到菜單項:運行->編譯設置
看看「產生
OBJ
文件」是否已選擇,若未選擇則選擇之。然後回到主界面,點「編譯鏈接」按鈕(F9
『玖』 用C語言編寫的程序怎麼把它做成可以運用的軟體
1、建立一個可執行過程是先把源程序編譯成目標文件(帶.OBJ擴展名的機器代碼文件),然後再把目標文件通過連接程序轉換成可執行文件(帶.EXE擴展名)。
2、執行過程不同的開發環境有的不同,這里以TC2.0為例說明:
a、單個文件源代碼的編譯:
假設文件名為:hello.c,文件內容為:main(){printf("Hello World.");}
1)用TC2.0集成環境生成可執行文件:
在TC集成環境IDE中打開源代碼文件hello.c,然後按F9,即可生成可執行文件hello.exe。
2)從命令行直接編譯、連接,生成可執行文件:
在命令行執行tcc可以編譯c語言源文件,並把它連接成可執行文件。
格式:tcc [選擇項 選擇項 選擇項 ...] 文件名 文件名,如:tcc hello
b、多個文件源代碼的編譯:
1)先後輸入並編輯4個文件,並以file1.c、file2.c、file3.c、file4.c存儲在磁碟上。
2)在編譯狀態下,建立一個「項目文件」,它不包括任何程序語句,而只包括組成程序的所有文件的文件名 file3 file1 file2 file(擴展名可以省略)
3)將以上內容存檔,文件名自定,但擴展名必須為.prj(表示為工程文件)。
4)在TC環境中的Project菜單找到Project name,打開剛存的.prj文件。
5)按F9進行編譯連接。
6)按Ctrl+F9,運行可生成的可執行程序。
c、多文件也可以在命令行單個編譯,然後連接。