<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 匯編技術(shù)內(nèi)幕(4)

          匯編技術(shù)內(nèi)幕(4)

          作者: 時(shí)間:2016-11-24 來源:網(wǎng)絡(luò) 收藏
          兩個(gè)以上的局部變量棧分配

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

          本文引用地址:http://www.ex-cimer.com/article/201611/320806.htm

          編譯該程序后,用mdb反匯編得出如下結(jié)果:
          # 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,創(chuàng)建Stack Frame
          main+3: subl $0x18,%esp ; 為局部變量i,j,k分配棧空間,并保證棧16字節(jié)對(duì)齊
          main+6: andl $0xf0,%esp
          main+9: movl $0,%eax
          main+0xe: subl %eax,%esp ; main+6至main+0xe,再次保證棧16字節(jié)對(duì)齊
          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,結(jié)果存入EDX
          main+0x32: leal -0xc(%ebp),%eax ; 將k的地址裝入到EAX
          main+0x35: addl %edx,(%eax) ; i+j+k,結(jié)果存入地址ebp-0xc即k中
          main+0x37: movl -0xc(%ebp),%eax ; 將k的值裝入EAX,作為返回值
          main+0x3a: leave ; 撤銷Stack Frame
          main+0x3b: ret ; main函數(shù)返回
          >


          問題:為什么3個(gè)變量分配了0x18字節(jié)的棧空間?
          在2個(gè)變量的時(shí)候,分配??臻g的指令是:subl $8,%esp
          而在3個(gè)局部變量的時(shí)候,分配??臻g的指令是:subl $0x18,%esp
          3個(gè)整型變量只需要0xc字節(jié),為何實(shí)際上分配了0x18字節(jié)呢?
          答案就是:保持16字節(jié)棧對(duì)齊。
          gcc默認(rèn)的編譯是要16字節(jié)棧對(duì)齊的,subl $8,%esp會(huì)使棧16字節(jié)對(duì)齊,而8字節(jié)空間只能滿足2個(gè)局部變量,如果再分配4字節(jié)滿足第3個(gè)局部變量的話,那棧地址就不再16字節(jié)對(duì)齊的,而同時(shí)滿足空間需要而且保持16字節(jié)棧對(duì)齊的最接近的就是0x18。
          如果,各定義一個(gè)50字節(jié)和100字節(jié)的字符數(shù)組,在這種情況下,實(shí)際分配多少??臻g呢?答案是0x8+0x40+0x70,即184字節(jié)。
          下面動(dòng)手驗(yàn)證一下:
          # 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 ; 為兩個(gè)字符數(shù)組分配??臻g,同時(shí)保證16字節(jié)對(duì)齊
          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進(jìn)制換算10進(jìn)制
          184
          > 0x40+0x70+0x8=X ; 表達(dá)式計(jì)算,結(jié)果指定為16進(jìn)制
          b8
          >


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



          評(píng)論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();