新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 匯編技術內幕(4)

        匯編技術內幕(4)

        作者: 時間:2016-11-24 來源:網絡 收藏
        兩個以上的局部變量棧分配

        程序如下:
        # vi test3.c
        int main()
        {
        int i, j=2, k=4;
        i=3;
        i=++i;
        k=i+j+k;
        return k;
        }

        本文引用地址:http://www.104case.com/article/201611/320806.htm

        編譯該程序后,用mdb反匯編得出如下結果:
        # gcc test3.c -o test3
        # mdb test3
        Loading modules: [ libc.so.1 ]
        > main::dis
        main: pushl %ebp
        main+1: movl %esp,%ebp ; main至main+1,創建Stack Frame
        main+3: subl $0x18,%esp ; 為局部變量i,j,k分配棧空間,并保證棧16字節對齊
        main+6: andl $0xf0,%esp
        main+9: movl $0,%eax
        main+0xe: subl %eax,%esp ; main+6至main+0xe,再次保證棧16字節對齊
        main+0x10: movl $2,-8(%ebp) ; j=2
        main+0x17: movl $4,-0xc(%ebp) ; k=4
        main+0x1e: movl $3,-4(%ebp) ; i=3
        main+0x25: leal -4(%ebp),%eax ; 將i的地址裝入到EAX
        main+0x28: incl (%eax) ; i++
        main+0x2a: movl -8(%ebp),%eax ; 將j的值裝入到 EAX
        main+0x2d: movl -4(%ebp),%edx ; 將i的值裝入到 EDX
        main+0x30: addl %eax,%edx ; j+i,結果存入EDX
        main+0x32: leal -0xc(%ebp),%eax ; 將k的地址裝入到EAX
        main+0x35: addl %edx,(%eax) ; i+j+k,結果存入地址ebp-0xc即k中
        main+0x37: movl -0xc(%ebp),%eax ; 將k的值裝入EAX,作為返回值
        main+0x3a: leave ; 撤銷Stack Frame
        main+0x3b: ret ; main函數返回
        >


        問題:為什么3個變量分配了0x18字節的棧空間?
        在2個變量的時候,分配棧空間的指令是:subl $8,%esp
        而在3個局部變量的時候,分配棧空間的指令是:subl $0x18,%esp
        3個整型變量只需要0xc字節,為何實際上分配了0x18字節呢?
        答案就是:保持16字節棧對齊。
        gcc默認的編譯是要16字節棧對齊的,subl $8,%esp會使棧16字節對齊,而8字節空間只能滿足2個局部變量,如果再分配4字節滿足第3個局部變量的話,那棧地址就不再16字節對齊的,而同時滿足空間需要而且保持16字節棧對齊的最接近的就是0x18。
        如果,各定義一個50字節和100字節的字符數組,在這種情況下,實際分配多少棧空間呢?答案是0x8+0x40+0x70,即184字節。
        下面動手驗證一下:
        # vi test4.c
        int main()
        {
        char str1[50];
        char str2[100];
        return 0;
        }
        # mdb test4
        Loading modules: [ libc.so.1 ]
        > main::dis
        main: pushl %ebp
        main+1: movl %esp,%ebp
        main+3: subl $0xb8,%esp ; 為兩個字符數組分配棧空間,同時保證16字節對齊
        main+9: andl $0xf0,%esp
        main+0xc: movl $0,%eax
        main+0x11: subl %eax,%esp
        main+0x13: movl $0,%eax
        main+0x18: leave
        main+0x19: ret
        > 0xb8=D ; 16進制換算10進制
        184
        > 0x40+0x70+0x8=X ; 表達式計算,結果指定為16進制
        b8
        >


        問題:定義了多個局部變量時,棧分配順序是怎樣的?
        局部變量棧分配的順序是按照變量聲明先后的順序,同一行聲明的變量是按照從左到右的順序入棧的,在test2.c中,變量聲明如下:
        int i, j=2, k=4;
        而反匯編的結果中:
        movl $2,-8(%ebp) ; j=2
        movl $4,-0xc(%ebp) ; k=4
        movl $3,-4(%ebp) ; i=3
        其中不難看出,i,j,k的棧中的位置如下圖:
        +----------------------------+------> 高地址
        | EIP (_start函數的返回地址) |
        +----------------------------+
        | EBP (_start函數的EBP) | <------ main函數的EBP指針(即SFP框架指針)
        +----------------------------+
        | i (EBP-4) |
        +----------------------------+
        | j (EBP-8) |
        +----------------------------+
        | k (EBP-0xc) |
        +----------------------------+------> 低地址



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 根河市| 崇文区| 万安县| 信丰县| 绵阳市| 五寨县| 东辽县| 龙门县| 镇坪县| 凤翔县| 霍州市| 建德市| 佛学| 平利县| 浦县| 将乐县| 镇沅| 新野县| 横山县| 武平县| 彰化市| 田阳县| 长岭县| 县级市| 鞍山市| 平武县| 巴彦淖尔市| 紫阳县| 介休市| 章丘市| 肇庆市| 通渭县| 南宫市| 望奎县| 长沙市| 咸宁市| 泰州市| 徐汇区| 焉耆| 邓州市| 嘉鱼县|