2013-11-27 3 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 등록 타고 메모리 참조, 당신은 동일한 두 번 등록을 제공하고 있다는 점이다. 그런 다음 어셈블러는 레지스터 이름을 메모리 위치로 해석하므로 동일한 파일에 정의되지 않았다고 불평합니다.

레지스터가 부족하여 전역 변수를 사용하는 경우에만 스택 사용을 피할 수 있습니다.