關於C99標準在keilMDK中實驗引發的,ADR指令認識,ARM寄存器之R12,及C89,C90,C95,C99標準的區別

本次實驗的起源是這樣的:
看到C99標準裏面支持變量用到時再定義,然後做了以下實驗,定義函數,看反彙編結果。
void test_c99(void)
{
     char i=0;
     printf("i=%d", i);

     char j=0;
     printf("j=%d", j);

     char k=0;
     printf("k=%d", k);

     char l=0;
     printf("l=%d", l);

     char m=0;
     printf("m=%d", m);

     char n=0;
     printf("n=%d", n);

     char o=0;
     printf("o=%d", o);
    
     char p=0;
     printf("p=%d", p);

     char q=0;
     printf("q=%d", q);

     char r=0;
     printf("r=%d", r);

     char s=0;
     printf("s=%d", s);

     char t=0;
     printf("t=%d", t);

     char str[3]="Jim";
     printf("str=%s", str);
}
test_c99
          0x70007724:    e92d5fff    ._-.    PUSH     {r0-r12,lr}
          0x70007728:    e3a04000    .@..    MOV      r4,#0           //從R4寄存器開始使用,每定義一個變量使用一個寄存器
          0x7000772c:    e1a01004    ....    MOV      r1,r4               //將剛剛定義並初始化的變量(r4中)取出,放到r1中
          0x70007730:    e28f0fce    ....    ADR      r0,{pc}+0x340 ; 0x70007a70     //取出"i=%d"字符串的地址到r0中
          0x70007734:    fa00027f    ....    BLX      __2printf ; 0x70008138               //調用printf函數,函數調用的傳參規則是:func(r0,r1,r2,r3) 
                                                                                                                   //具體要看ABI規範或Procedure Call Standard for ARM
          0x70007738:    e3a05000    .P..    MOV      r5,#0
          0x7000773c:    e1a01005    ....    MOV      r1,r5
          0x70007740:    e28f0e33    3...    ADR      r0,{pc}+0x338 ; 0x70007a78
          0x70007744:    fa00027b    {...    BLX      __2printf ; 0x70008138
          0x70007748:    e3a06000    .`..    MOV      r6,#0
          0x7000774c:    e1a01006    ....    MOV      r1,r6
          0x70007750:    e28f0fca    ....    ADR      r0,{pc}+0x330 ; 0x70007a80
          0x70007754:    fa000277    w...    BLX      __2printf ; 0x70008138
          0x70007758:    e3a07000    .p..    MOV      r7,#0
          0x7000775c:    e1a01007    ....    MOV      r1,r7
          0x70007760:    e28f0e32    2...    ADR      r0,{pc}+0x328 ; 0x70007a88
          0x70007764:    fa000273    s...    BLX      __2printf ; 0x70008138
          0x70007768:    e3a08000    ....    MOV      r8,#0
          0x7000776c:    e1a01008    ....    MOV      r1,r8
          0x70007770:    e28f0fc6    ....    ADR      r0,{pc}+0x320 ; 0x70007a90
          0x70007774:    fa00026f    o...    BLX      __2printf ; 0x70008138
          0x70007778:    e3a09000    ....    MOV      r9,#0
          0x7000777c:    e1a01009    ....    MOV      r1,r9
          0x70007780:    e28f0e31    1...    ADR      r0,{pc}+0x318 ; 0x70007a98
          0x70007784:    fa00026b    k...    BLX      __2printf ; 0x70008138
          0x70007788:    e3a0a000    ....    MOV      r10,#0
          0x7000778c:    e1a0100a    ....    MOV      r1,r10
          0x70007790:    e28f0fc2    ....    ADR      r0,{pc}+0x310 ; 0x70007aa0
          0x70007794:    fa000267    g...    BLX      __2printf ; 0x70008138
          0x70007798:    e3a0b000    ....    MOV      r11,#0                                   //寄存器r11中存放定義的新變量
          0x7000779c:    e1a0100b    ....    MOV      r1,r11                              
          0x700077a0:    e28f0c03    ....    ADR      r0,{pc}+0x308 ; 0x70007aa8
          0x700077a4:    fa000263    c...    BLX      __2printf ; 0x70008138
          0x700077a8:    e3a00000    ....    MOV      r0,#0                                       //寄存器已經不夠用了,需要通過堆棧來存儲新定義的變量。
                                                                                                                        //r12之後有特殊用途,具體看架構手冊或Procedure Call Standard for ARM
                                                                                                                        //gooogleman博客有篇 arm中r12(IP)的用途
          0x700077ac:    e58d000c    ....    STR      r0,[sp,#0xc]
          0x700077b0:    e28f0fbe    ....    ADR      r0,{pc}+0x300 ; 0x70007ab0
          0x700077b4:    e59d100c    ....    LDR      r1,[sp,#0xc]
          0x700077b8:    fa00025e    ^...    BLX      __2printf ; 0x70008138
          0x700077bc:    e3a00000    ....    MOV      r0,#0
          0x700077c0:    e58d0008    ....    STR      r0,[sp,#8]
          0x700077c4:    e28f0fbb    ....    ADR      r0,{pc}+0x2f4 ; 0x70007ab8
          0x700077c8:    e59d1008    ....    LDR      r1,[sp,#8]
          0x700077cc:    fa000259    Y...    BLX      __2printf ; 0x70008138
          0x700077d0:    e3a00000    ....    MOV      r0,#0
          0x700077d4:    e58d0004    ....    STR      r0,[sp,#4]
          0x700077d8:    e28f0e2e    ....    ADR      r0,{pc}+0x2e8 ; 0x70007ac0
          0x700077dc:    e59d1004    ....    LDR      r1,[sp,#4]
          0x700077e0:    fa000254    T...    BLX      __2printf ; 0x70008138
          0x700077e4:    e3a00000    ....    MOV      r0,#0
          0x700077e8:    e58d0000    ....    STR      r0,[sp,#0]
          0x700077ec:    e28f0fb5    ....    ADR      r0,{pc}+0x2dc ; 0x70007ac8
          0x700077f0:    e59d1000    ....    LDR      r1,[sp,#0]
          0x700077f4:    fa00024f    O...    BLX      __2printf ; 0x70008138
          0x700077f8:    e8bd9fff    ....    POP      {r0-r12,pc}

$d                                                                                                              //這裏是常量表區
    0x70007a40:    202d492d    -I-     DCD    539838765
    0x70007a44:    5049752d    -uIP    DCD    1346991405
    0x70007a48:    7325202d    - %s    DCD    1931812909
    0x70007a4c:    00000d0a    ....    DCD    3338
    0x70007a50:    41203a50    P: A    DCD    1092631120
    0x70007a54:    49205050    PP I    DCD    1226854480
    0x70007a58:    2074696e    nit     DCD    544500078
    0x70007a5c:    202e2e2e    ...     DCD    539897390
    0x70007a60:    00000000    ....    DCD    0
    0x70007a64:    73626577    webs    DCD    1935828343
    0x70007a68:    65767265    erve    DCD    1702261349
    0x70007a6c:    000d0a72    r...    DCD    854642
    0x70007a70:    64253d69    i=%d    DCD    1680162153
    0x70007a74:    00000000    ....    DCD    0
    0x70007a78:    64253d6a    j=%d    DCD    1680162154
    0x70007a7c:    00000000    ....    DCD    0
    0x70007a80:    64253d6b    k=%d    DCD    1680162155
    0x70007a84:    00000000    ....    DCD    0
    0x70007a88:    64253d6c    l=%d    DCD    1680162156
    0x70007a8c:    00000000    ....    DCD    0
    0x70007a90:    64253d6d    m=%d    DCD    1680162157
    0x70007a94:    00000000    ....    DCD    0
    0x70007a98:    64253d6e    n=%d    DCD    1680162158
    0x70007a9c:    00000000    ....    DCD    0
    0x70007aa0:    64253d6f    o=%d    DCD    1680162159
    0x70007aa4:    00000000    ....    DCD    0
    0x70007aa8:    64253d70    p=%d    DCD    1680162160
    0x70007aac:    00000000    ....    DCD    0
    0x70007ab0:    64253d71    q=%d    DCD    1680162161
    0x70007ab4:    00000000    ....    DCD    0
    0x70007ab8:    64253d72    r=%d    DCD    1680162162
    0x70007abc:    00000000    ....    DCD    0
    0x70007ac0:    64253d73    s=%d    DCD    1680162163
    0x70007ac4:    00000000    ....    DCD    0
    0x70007ac8:    64253d74    t=%d    DCD    1680162164
從反彙編中可以看到,很多ADR指令,這裏截取一條分析
          0x70007770:    e28f0fc6    ....    ADR      r0,{pc}+0x320 ; 0x70007a90
原來以爲{pc}表示的是pc+8。後來看了ADR的指令解釋才明白,這是一條僞指令表示當前執行指令(0x70007770) + 0x320 = 0x70007a90
而不再是按照流水線理解。僞指令在經過彙編器彙編的過程中,會被分解成ADD或SUB指令的形式。
再看一條普通的帶有PC指針偏移的LDR指令:
0x700082ec:    4a0f        .J      LDR      r2,[pc,#60] ; [0x7000832c] = 0x228e
這裏pc是0x700082ec + 0x3C(#60) +0X4(三級指令流水線,thumb指令,每條指令2字節)= 0x7000832c
ADR produces position-independent code, because the assembler generates an instruction that adds or subtracts a value to the PC.
另:推薦一篇博客:《ARM彙編中的ldr和adr的區別及其在uboot中相關源碼的分析》http://blog.csdn.net/ce123_zhouwei/article/details/7277114

關於R0-R15寄存器的描述,除了看ARM架構手冊(如ARMV7)也可參照AAPCS(Procedure Call Standard for the ARM® Architecture).

以上的程序是在keilMDK下編譯的STM32F103工程。keilMDK默認編譯是C89標準的(ARM編譯器手冊中講的是C90標準或C95標準,關於C標準參照:http://www.cprogramdevelop.com/4149211/ 或附錄)。如果但keilMDK聲明是支持C99的,只需要在編譯選項中增加--c99即可(參照ARM手冊:using the compiler.pdf)









附錄

C language specification: C89, C90, C95, C99

Tag: gcc, C + + / C, c, compiler, language CategoryC Author: y1039569960 Date: 2013-01-22

This article is reproduced

[K & R C] 1978 years, Dennis Ritchie and Brian Kernighan co-launched "The C Programming Language" of the first edition (in accordance with established practice, the classics must have referred to, the writings referred to as K & R), a reference guide in the end of the book (Reference Manual ) one gives a complete definition of the C language, to become the de factostandard for the C language was known as K & R C. This year, the C language is ported to a variety of models, and are subject to a wide range of support, the C language in the software development almost dominate the world.

C89 (ANSI C) with the C language in many areas of promotion, application, some new featurescontinue to be a variety of compiler implemented and added. Thus, the establishment of a new "unambiguous, specific platform-independent C language definition become more and more important things. In 1983, ASC X3 (ANSI under responsible for information technologystandards of the institution, now renamed as INCITS) set up a dedicated Technical Committee J11 (J11 Commission, Stands for X3J11), responsible for drafting the draftstandard on the C language. 1989, the draft ANSI formally adopted the American NationalStandards, known as the C89 standard.

C90 (ISO C)? followed the "The C Programming Language" second edition was published, the book contents updated according to the ANSI C (C89). In 1990, the ISO / IEC JTC1/SC22/WG14 (ISO / IEC Joint Technical Commission I 22 Sub-Committee 14 Working Group) efforts, ISO approved ANSI C as an international standard. So the ISO C (also known as C90) was born. In addition to some of the details of the standard document printing arrangement ISO C (C90) and ANSI C (C89) is technically exactly the same.

[C95], ISO 1994, 1996 were published C90 errata document, correct some typographical errors, and in 1995 passed a C90 Technical Supplement C90 slight expansion after expansion ISO C is called C95.

[C99] 1999, ANSI and ISO passed the latest version of the C language standards and technical errata document, thestandard is known as C99. This is basically on the C language, the most authoritative definition.

, C compiler provides full support of C89 (C90) C99 provides only partial support, there are still some support for some K & R C style.

The C language specification C89 (c90), C95 (94) and c99. C89 is a the earliest C languagespecification, 89, 90, introduced first by the American National Standards Institute ANSI version, and later was accepted as ISO international standard (ISO / IEC 9899:1990), and thus sometimes known as C90. 94 and 96, respectively c90 two bug fixes, gcc support is a revised version of the c89 (90) C language specification. 90 Specification Version amendment in 1995, called C95 or AMD1. GCC also supports C95 specifications. The latest C specification (ISO / IEC 9899:1999), often called the C99 specification amendments enacted in 1999. C99 2001 C99error correction, gcc supports the revised specification, but so far, gcc also did not complete the full support of the C99 specification.

Attached: C language origin

       The first prototype of origin] C language is Algol 60 1963, Cambridge University developed it into a CPL (Combined Programing Language). In 1967, the University of Cambridge Matin Richards simplified CPL language BCPL language. In 1970, Ken Thompson of Bell Laboratories (Bell Labs) will BCPL modify, and named their B language means to extract the essence of the CPL (the Boiling CPL down to its basic good features). And wrote the first UNIX system B language. In 1973, AT & T Bell Labs, Dennis Ritchie (DMRitchie) on the basis of language BCPL and B to design a new language, take the second letter in the name of BCPL, which is the famous C language. Shortly thereafter, the UNIX kernel (Kernel) and applications entirely in C rewritten Since then, C language has become the most widely used UNIX environment mainstream programming languages.




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