2017-07-15 35 views
1

讓我們用gcc -g -O0 -o prog prog.c編譯下面的程序,並在其上運行gdb。如果我們一步一步來,我們會看到該行爲什麼gdb在gcc輸出上工作不正確?

4  switch (c) { 

後直接轉到行

38 return 0; 

這是不對的,因爲它首先必須去排隊

32   break; 

這是適當完成輸出產生與clang -g -O0 -o prog prog.c

GCC版本: GCC(Debian的6.4.0-1)6.4.0 20170704

鐺版本: 3.8.1-24(標籤/ RELEASE_381 /決賽)

int main(void) 
{ 
    char c = '\x1a'; 
    switch (c) { 
    case '\x18': /* C-x */ 
     break; 
    case '\x12': /* C-r */ 
     break; 
    case '\x13': /* C-s */ 
     break; 
    case '\x10': /* C-p */ 
     break; 
    case '\x0e': /* C-n */ 
     break; 
    case '\x02': /* C-b */ 
     break; 
    case '\x06': /* C-f */ 
     break; 
    case '\x05': /* C-e */ 
     break; 
    case '\x01': /* C-a */ 
     break; 
    case '\x04': /* C-d */ 
     break; 
    case '\x08': /* C-h */ 
     break; 
    case '\x1d': /* C-] */ 
     break; 
    case '\x16': /* C-v */ 
     break; 
    case '\x1a': /* C-z */ 
     break; 
    case '\x0d': /* C-m */ 
     break; 
    default: 
     (void) c; 
    } 
    return 0; 
} 
+0

是不是'0x1a',而不是'\ x1a'? – dlmeetei

+0

@dlmeetei我想這些是相同的 –

+0

因爲[gcc](https://godbolt.org/g/4t7aL2)和[clang](https://godbolt.org/g/z8Ck5s)爲這個例子生成不同的代碼。 – ks1322

回答

3

GDB不起作用不正確的是,它只是跨越編譯器生成的代碼。進而,由於無所事事這個虛擬實例,GCC生成this code

main: 
     push rbp 
     mov  rbp, rsp 
     mov  BYTE PTR [rbp-1], 26 
     movsx eax, BYTE PTR [rbp-1] 
     cmp  eax, 29 
     ja  .L2 
     mov  eax, eax 
     mov  rax, QWORD PTR .L4[0+rax*8] 
     jmp  rax 
.L4: 
     .quad .L2 
     .quad .L2 
     .quad .L2 
     .quad .L2 
     .quad .L2 
     .quad .L2 
     .quad .L2 
     .quad .L2 
     .quad .L2 
     .quad .L2 
     .quad .L2 
     .quad .L2 
     .quad .L2 
     .quad .L2 
     .quad .L2 
     .quad .L2 
     .quad .L2 
     .quad .L2 
     .quad .L2 
     .quad .L2 
     .quad .L2 
     .quad .L2 
     .quad .L2 
     .quad .L2 
     .quad .L2 
     .quad .L2 
     .quad .L2 
     .quad .L2 
     .quad .L2 
     .quad .L2 
.L2: 
     mov  eax, 0 
     pop  rbp 
     ret 

沒有爲break語句生成沒有相應的代碼,所以GDB不能走路了他們,因爲他們不存在。

另一方面,鏗鏘爲break聲明生成另一個more verbose code。這就是爲什麼你可以走在上面:

main:         # @main 
     push rbp 
     mov  rbp, rsp 
     mov  dword ptr [rbp - 4], 0 
     mov  byte ptr [rbp - 5], 26 
     movsx eax, byte ptr [rbp - 5] 
     dec  eax 
     mov  ecx, eax 
     sub  eax, 28 
     mov  qword ptr [rbp - 16], rcx # 8-byte Spill 
     mov  dword ptr [rbp - 20], eax # 4-byte Spill 
     ja  .LBB0_16 
     mov  rax, qword ptr [rbp - 16] # 8-byte Reload 
     mov  rcx, qword ptr [8*rax + .LJTI0_0] 
     jmp  rcx 
.LBB0_1: 
     jmp  .LBB0_17 
.LBB0_2: 
     jmp  .LBB0_17 
.LBB0_3: 
     jmp  .LBB0_17 
.LBB0_4: 
     jmp  .LBB0_17 
.LBB0_5: 
     jmp  .LBB0_17 
.LBB0_6: 
     jmp  .LBB0_17 
.LBB0_7: 
     jmp  .LBB0_17 
.LBB0_8: 
     jmp  .LBB0_17 
.LBB0_9: 
     jmp  .LBB0_17 
.LBB0_10: 
     jmp  .LBB0_17 
.LBB0_11: 
     jmp  .LBB0_17 
.LBB0_12: 
     jmp  .LBB0_17 
.LBB0_13: 
     jmp  .LBB0_17 
.LBB0_14: 
     jmp  .LBB0_17 
.LBB0_15: 
     jmp  .LBB0_17 
.LBB0_16: 
     jmp  .LBB0_17 
.LBB0_17: 
     xor  eax, eax 
     pop  rbp 
     ret 
.LJTI0_0: 
     .quad .LBB0_9 
     .quad .LBB0_6 
     .quad .LBB0_16 
     .quad .LBB0_10 
     .quad .LBB0_8 
     .quad .LBB0_7 
     .quad .LBB0_16 
     .quad .LBB0_11 
     .quad .LBB0_16 
     .quad .LBB0_16 
     .quad .LBB0_16 
     .quad .LBB0_16 
     .quad .LBB0_15 
     .quad .LBB0_5 
     .quad .LBB0_16 
     .quad .LBB0_4 
     .quad .LBB0_16 
     .quad .LBB0_2 
     .quad .LBB0_3 
     .quad .LBB0_16 
     .quad .LBB0_16 
     .quad .LBB0_13 
     .quad .LBB0_16 
     .quad .LBB0_1 
     .quad .LBB0_16 
     .quad .LBB0_14 
     .quad .LBB0_16 
     .quad .LBB0_16 
     .quad .LBB0_12 

如果你想gcc生成代碼break語句,你應該改變你例子switch聲明至少做什麼。例如增加一個變量i,並改變它的價值switch聲明:

int main(void) 
{ 
    int i = 0; 
    char c = '\x1a'; 
    switch (c) { 
    case '\x18': /* C-x */ 
     break; 
    case '\x12': /* C-r */ 
     break; 
    case '\x13': /* C-s */ 
     break; 
    case '\x10': /* C-p */ 
     break; 
    case '\x0e': /* C-n */ 
     break; 
    case '\x02': /* C-b */ 
     break; 
    case '\x06': /* C-f */ 
     break; 
    case '\x05': /* C-e */ 
     break; 
    case '\x01': /* C-a */ 
     break; 
    case '\x04': /* C-d */ 
     break; 
    case '\x08': /* C-h */ 
     break; 
    case '\x1d': /* C-] */ 
     break; 
    case '\x16': /* C-v */ 
     break; 
    case '\x1a': /* C-z */ 
     i = 1; 
     break; 
    case '\x0d': /* C-m */ 
     break; 
    default: 
     (void) c; 
    } 
    return 0; 
} 
相關問題