緊急求助!ARM-GCC對於函數指標調用的編譯有錯誤?【已經找到原因】__函數

來源:互聯網
上載者:User

函數指標是實現回呼函數的基礎,回呼函數是C程式架構的基礎。所以函數指標的重要性不言而喻。然而最近在ARM開發板上測試程式時,發現函數指標雖然能編譯通過,但是運行時確總是報錯。如下是一個最簡單的測試程式源碼。

static void test(){    puts("test\n");}static void(*f)() = test;void Main(void){    led_init();    key_init();    io_init(0);    f();    while(1){        puts("-------hello from main()----------\n");        delay(100000);    }}

使用gcc -S編譯得到的彙編代碼如下:

    .cpu arm10tdmi    .eabi_attribute 20, 1    .eabi_attribute 21, 1    .eabi_attribute 23, 3    .eabi_attribute 24, 1    .eabi_attribute 25, 1    .eabi_attribute 26, 2    .eabi_attribute 30, 6    .eabi_attribute 34, 0    .eabi_attribute 18, 4    .file   "main.c"    .section    .rodata    .align  2.LC0:    .ascii  "test\012\000"    .text    .align  2    .syntax unified    .arm    .fpu softvfp    .type   test, %functiontest:    @ args = 0, pretend = 0, frame = 0    @ frame_needed = 1, uses_anonymous_args = 0    push    {fp, lr}    add fp, sp, #4    ldr r0, .L2    bl  puts    nop    pop {fp, pc}.L3:    .align  2.L2:    .word   .LC0    .size   test, .-test    .data    .align  2    .type   f, %object    .size   f, 4f:    .word   test    .section    .rodata    .align  2.LC1:    .ascii  "-------hello from main()----------\012\000"    .text    .align  2.LC1:    .ascii  "-------hello from main()----------\012\000"    .text    .align  2    .global Main    .syntax unified    .arm    .fpu softvfp    .type   Main, %functionMain:    @ args = 0, pretend = 0, frame = 0    @ frame_needed = 1, uses_anonymous_args = 0    push    {fp, lr}    add fp, sp, #4    bl  led_init    bl  key_init    mov r0, #0    bl  io_init    ldr r3, .L6    ldr r3, [r3]    blx r3.L5:    ldr r0, .L6+4    bl  puts    ldr r0, .L6+8    bl  delay    b   .L5.L7:    .align  2.L6:    .word   f    .word   .LC1    .word   100000    .size   Main, .-Main    .ident  "GCC: (GNU) 6.2.0"    .section    .note.GNU-stack,"",%progbits

可見函數指標調用時,被編譯成了BLX指令。這個指令是跳轉並且換運行狀態(ARM和THUMB切換)。顯然這樣編譯是錯誤的,還請高手幫忙分析一下,到底是哪裡出了問題。

是需要特殊的編譯參數嗎。

頭疼。。。

2016-12-20 更新:

已經找到原因,關鍵點如下:

GCC把絕對位址調用(包括函數指標調用)編譯為BLX Rn指令。BX,BLX指令用於絕對跳轉(B,BL則用於跳轉),轉到Rn中包含的地址。總之,其中的X有兩個意思:(1)表示根據Rn的最低位是否為0,確定是否進行ARM/Thum切換。(2)可以絕對位址跳轉。

S3C2440A的指令集中沒有BLX,只有BX。故運行時會無效指令錯誤。

解決思路:
(1)給GCC適當的參數運行,來避免產生BLX指令。目前尚不清楚需要什麼參數選項。
(2)利用Undefined例外處理常式來類比BLX指令。這個看起來複雜,實現起來其實非常簡單,已經在v0.9中實現。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.