2013-11-27 40 views
3

我試圖從下面的代碼中刪除堆棧依賴關係。從彙編代碼中刪除堆棧依賴關係

void myfunction(struct kprobe *p, struct pt_regs *regs) 
{ 
     register void *rregs asm("r1") = regs; 
     register void *rfn asm("lr") = p->ainsn.insn_fn; 

     __asm__ __volatile__ (
       "stmdb sp!, {%[regs], r11}  \n\t" 
       "ldmia %[regs], {r0-r12}  \n\t"  
       "blx %[fn]     \n\t" 
       "ldr lr, [sp], #4   \n\t" /* lr = regs */ 
       "stmia lr, {r0-r12}   \n\t" 
       "ldr r11, [sp], #4   \n\t" 

       : [regs] "=r" (rregs), [fn] "=r" (rfn) 
       : "" (rregs), "1" (rfn) 
       : "r0", "r2", "r3", "r4", "r5", "r6", "r7", 
        "r8", "r9", "r10", "r12", "memory", "cc" 
       ); 
} 

在上面的函數,stmdb sp!, {%[regs], r11}r1r11到堆棧和以後它retrives。

在我的情況下,我應該避免在這裏使用堆棧。所以我重寫了

void myfunction(struct kprobe *p, struct pt_regs *regs) 
{ 
     int r1_bk = 0, r11_bk = 0; 
     register void *rregs asm("r1") = regs; 
     register void *rfn asm("lr") = p->ainsn.insn_fn; 
     register void *r1b_c asm("r1") = &r1_bk; 
     register void *r11b_c asm("r11") = &r11_bk;  

     __asm__ __volatile__ (
       "ldr %[r1b], r1  \n\t" 
       "ldr %[r11b], r11 \n\t" 
       "ldmia %[regs], {r0-r12}  \n\t" 
       "blx %[fn]     \n\t"  
       "ldr lr, %[r1b]    \n\t" /* lr = regs */ 
       "stmia lr, {r0-r12}   \n\t" 
       "ldr r11, %[r11b]   \n\t" 

       : [regs] "=r" (rregs), [fn] "=r" (rfn), [r1b] "=r" (r1b_c), [r11b] "=r" (r11b_c) 
       : "0" (rregs), "1" (rfn) 
       : "r0", "r2", "r3", "r4", "r5", "r6", "r7", 
        "r8", "r9", "r10", "r12", "memory", "cc" 
       ); 
} 

當我編譯時,下面的錯誤我得到。

/tmp/ccJMefdC.s: Assembler messages: 
/tmp/ccJMefdC.s:579: Error: internal_relocation (type: OFFSET_IMM) not fixed up 
/tmp/ccJMefdC.s:580: Error: internal_relocation (type: OFFSET_IMM) not fixed up 
/tmp/ccJMefdC.s:583: Error: internal_relocation (type: OFFSET_IMM) not fixed up 
/tmp/ccJMefdC.s:585: Error: internal_relocation (type: OFFSET_IMM) not fixed up 

我在這裏引用internal relocation not fixed up。但它沒有給出明確的想法。請分享你的知識。

+0

我沒有看到你恢復r1,而我看到你正在加載r14中的r1b(這是LR)。這是想要的嗎? – Jekyll

+0

r1b的內容保存r1值。請參閱''ldr%[r1b],r1「' – Jeyaram

+0

我已經看到了,我沒有看到」ldr r1,%[r1b]「恢復原始值,但這甚至沒有在原始代碼中完成只有r11被恢復。所以我認爲它不會改變任何東西,對不起 – Jekyll

回答

4

您的內嵌asm調用了幾乎所有的寄存器,並且通過volatile指令明確告知編譯器它不應該跳過或嘗試移動該調用以優化寄存器使用。這意味着編譯器在生成myfunction的等效指令時需要將寄存器保存到某處,然後發出該內聯彙編。

讓我證明給你看:

$ cat asm_vol.c 
void f() { 
    asm volatile("" : : : "r0", "r2", "r3", "r4", "r5", "r6", "r7", 
        "r8", "r9", "r10", "r12", "memory", "cc"); 
} 
$ arm-linux-gnueabihf-gcc -c -O2 asm_vol.c 
$ arm-linux-gnueabihf-objdump -d asm_vol.o 

asm_vol.o:  file format elf32-littlearm 


Disassembly of section .text: 

00000000 <f>: 
    0: e92d 07f0 stmdb sp!, {r4, r5, r6, r7, r8, r9, sl} 
    4: e8bd 07f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl} 
    8: 4770  bx lr 
    a: bf00  nop 
2

的原因錯誤信息是ldr採取註冊和存儲的參考,您提供的同一註冊兩次。彙編程序然後將寄存器名稱解釋爲內存位置,因此會抱怨它沒有在同一個文件中定義。

由於您已經用完了寄存器,所以只能通過使用全局變量來避免堆棧使用。