韋東山stdio裸機程序分析

韋東山裸機程序

GCC中文手冊


源代碼和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的定義參見下面兩篇文章:

Machine Modes

Using vector instructions through built-in functions

              具體代碼一目瞭然。

6.  va_start va_arg va_end 的使用 參見文章:  va_start和va_end使用詳解

(待續)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章