2015-05-08 39 views
2

我正在研究一個程序的內存佈局。我正在使用gdb在小端(intel x86_64)Linux(32位)機器中檢查堆棧。但是,我無法理解這個處理器和gdb的big-endian和little-endian w.r.的概念。gdb:檢查堆棧和小尾數澄清

我的示例程序是:

1 #include<stdio.h> 
2 
3 int main(int argc, char **argv) { 
4  int a = 5; 
5  char b[] = "ABCDEFGH"; 
6 
7  return 0; 
8 } 

         [Code - 1] 

的指令的下列序列在gdb被執行。

(gdb) b 7 
Breakpoint 1 at 0x8048434: file args.c, line 7. 
(gdb) r 
Breakpoint 1, main (argc=1, argv=0xbffff4f4) at args.c:7 
7  return 0; 

(gdb) x/20xw $esp 
0xbffff410: 0x0011e0c0 0x08049ff4 0xbffff448 0xbffff4f4 
0xbffff420: 0x00284324 0x00283ff4 0x08048470 0x00000005 
0xbffff430: 0x4115d4a5 0x45444342 0x00484746 0x6a078d00 
0xbffff440: 0x08048470 0x00000000 0xbffff4c8 0x00144bd6 
0xbffff450: 0x00000002 0xbffff4f4 0xbffff500 0xb7fff858 


          [Code - 2] 

起初,我很困惑在堆棧存儲器地址是否0xbffff430以上包含值0x410xa5。所以我檢查了從地址0xbffff433開始的堆棧。

(gdb) x/8xw 0xbffff433 
0xbffff433: 0x44434241 0x48474645 0x078d0000 0x0484706a 
0xbffff443: 0x00000008 0xfff4c800 0x144bd6bf 0x00000200 

          [code - 3] 

從上面的輸出可以明顯看出,在地址0xbffff433包含值0x41。因此,地址0xbffff430包含值0xa5。因此,我們可以得出結論:在GCC顯示在以下順序內存地址: -

0xbffff433: [0xbffff436][0xbffff435][0xbffff434][0xbffff433] [0xbffff43a] [0xbffff439][0xbffff438][0xbffff437] 
       D   C   B   A    H    G    F   E 

然而,由於英特爾x86_64的是little-endian的,從我的理解中的字符數組存儲順序(MSB在最小的地址)應如下: -

0xbffff433: [0xbffff436][0xbffff435][0xbffff434][0xbffff433] [0xbffff43a][0xbffff439][0xbffff438][0xbffff437] 
       A   B   C   D    E   F   G   H 

Q(一):能否請一些解釋,其中我收到錯了嗎? (b):此外,從上面的[code 2]我們可以看到,變量a的值存儲在地址0xbffff42c。變量a的值爲:0x00000005。這裏LSB也存儲在最小的內存地址。 (c):但是,Q(a)和(b)的問題在存儲地址時不會顯示。例如,從code - 4下面我們可以檢查在地址0xbffff448 EBP(0xbffff4c8)存儲

(gdb) x/4xw $ebp 
0xbffff448: 0xbffff4c8 0x00144bd6 0x00000002 0xbffff4f4 

可以清楚地看到,該地址存儲在順序如下: -

0xbffff448: [0xbffff44b][0xbffff44a][0xbffff449][0xbffff448] 
       0xbf  0xff  0xf4  0xc8 

注:1)我在ubuntu-10.04-desktop-i386的虛擬機上試過上面的代碼。我證實了我的機器的字節順序使用下面的代碼:

#include <stdio.h> 
int main() 
{ 
    unsigned int i = 1; 
    char *c = (char*)&i; 
    if (*c)  
     printf("Little endian"); 
    else 
     printf("Big endian"); 
    getchar(); 
    return 0; 
} 

2)我查了以下螺紋太Is GDB interpreting the memory address correctly?但我仍然無法理解的概念。

謝謝。

+1

x86上C中的char類型長度爲1個字節。沒有考慮到排序的前提。 x86上的C中的數組從低位地址變爲高位地址。使用'x/9xb b'或'x/9cb b'來查看字符數組的前9個元素b。 'x/xw'中的'w'表示「打印4字節的單詞」。 –

+0

感謝您的解釋!你能否把它作爲答案發布,以便我能接受它? –

+0

一個很好的問題,我不明白答案。你能否提供更多信息? – gfan

回答

1

x86上C中的char類型是1個8位字節長,1個字節的對齊;沒有考慮到排序的前提。 x86上的C中的數組從低位地址變爲高位地址。 x/xw中的w表示「打印4字節字」,這對於顯示32位整數和(在32位系統上)指針是很好的,但對於字符或字符數組來說不是那麼好。使用x/9xb bx/9cb b來查看字符數組b的前9個元素,顯示爲字節。