源代碼和GCC中文手冊可自由下載
緣由:首先單純的uart驅動,沒有什麼難度,配置2440寄存器即可實現。
stdio程序移植libc庫,實現printf scanf sscanf 等函數,利用串口獲取十進制數,轉換成十六進制。
功能較簡單,但是對於libc庫的移植較複雜,其中還涉及gnu assemble語法等等,因此比較感興趣,想總結一下。
1. 首先是頂層Makefile。
其中一句:
INCLUDEDIR := $(shell pwd)/include
CFLAGS := -Wall -O2
CPPFLAGS := -nostdinc -I$(INCLUDEDIR)
參考gcc中文手冊 -nostdinc:
不要在標準系統目錄中尋找頭文件.只搜索`-I'選項指定的目錄(以及當前目錄,如果合適).
結合使用`-nostdinc'和`-I-'選項,你可以把包含文件搜索限制在顯式指定的目錄.
-I$(INCLUDEDIR)
指定當前目錄下的include目錄爲頭文件的搜索目錄。
2. 查看lib目錄下的Makefile
libc.a: $(objs)
${AR} -r -o $@ $^
這裏用到了AR命令,AR爲arm-linux-ar, 關於ar命令有篇文章講的較細緻可以參考:關於靜態鏈接庫
也可以參考 arm-linux-ar --help
ar作用是生成靜態庫
-r 表示:replace existing or insert new file(s) into the archive, 替換歸檔庫中已存在的文件或插入新的文件。
-o:preserve original dates ,保留原來的日期。
3. Ctype分析
我看了半天,大致明白了Ctype的作用,其實就是分析一個字符是什麼類型的
#define __ismask(x) (_ctype[(int)(unsigned char)(x)])
#define isupper(c) ((__ismask(c)&(_U)) != 0)
這裏以isupper來舉例,isupper顧名思義,判斷字符是否爲大寫。假設字符爲大寫字母'A' ,則
isupper('A') => ((__ismask(‘A’)&(_U)) != 0) => (_ctype[65] & _U != 0 ) , 查看_ctype[65] 值爲 _U|_X ,則 (_U|_X) & _U ,結果爲true。
ctype.h 提供了 兩個函數: __tolower __toupper ,支持大小寫字母轉換。
4. __attribute__
有關__attribute__有篇文章較詳細:Using GNU C __attribute__
另外還有一份 :The GNU C Reference Manual
繼續拓展 attribute,
/* like printf() but to standard error only */
extern void eprintf(const char *format, ...)
__attribute__((format(printf, 1, 2))); /* 1=format 2=params */
這裏1 代表指定傳入函數的第1個參數是格式化字符串, 2 代表指定從函數的第幾個參數開始按上述規則進行檢查。開始我也沒理解文檔中英文的含義。參見這篇博客:__attribute__ 詳解
5. gcclib.h
/* gcclib.h -- definitions for various functions 'borrowed' from gcc-2.95.3 */
/* I Molton 29/07/01 */
#define BITS_PER_UNIT 8
#define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT)
typedef unsigned int UQItype __attribute__ ((mode (QI)));
typedef int SItype __attribute__ ((mode (SI)));
typedef unsigned int USItype __attribute__ ((mode (SI)));
typedef int DItype __attribute__ ((mode (DI)));
typedef int word_type __attribute__ ((mode (__word__)));
typedef unsigned int UDItype __attribute__ ((mode (DI)));
#ifdef __ARMEB__
struct DIstruct {SItype high, low;};
#else
struct DIstruct {SItype low, high;};
#endif
typedef union
{
struct DIstruct s;
DItype ll;
} DIunion;
參考mode的定義:
mode (mode)
- This attribute specifies the data type for the declaration--whichevertype corresponds to the modemode. This in effect lets yourequest an integer or floating point type according to its width.
- 結合上述說明,
- typedef unsigned int UQItype __attribute__ ((mode (QI)));
- 定義了一個新的類型 UQItype, mode屬性用來標識它的位寬。QI的定義參見下面兩篇文章:
具體代碼一目瞭然。
6. va_start va_arg va_end 的使用 參見文章: va_start和va_end使用詳解
(待續)