arm-none-eabi-gcc C指针

时间:2013-11-26 03:13:31

标签: c gcc assembly arm disassembly

所以在arm-none-eabi-gcc中使用C语言。我一直有指针问题,它们似乎不存在。也许我将错误的cmds传递给编译器。

这是一个例子。

    unsigned int * gpuPointer = GetGPU_Pointer(framebufferAddress);
    unsigned int color = 16;
    int y = 768;
    int x = 1024;

    while(y >= 0)
    {
        while(x >= 0)
        {
            *gpuPointer = color;
            color = color + 2;
            x--;
        }

        color++;
        y--;
        x = 1024;
    }

和反汇编程序的输出。

81c8:   ebffffc3    bl  80dc <GetGPU_Pointer>
81cc:   e3a0c010    mov ip, #16 ; 0x10
81d0:   e28c3b02    add r3, ip, #2048   ; 0x800
81d4:   e2833002    add r3, r3, #2  ; 0x2
81d8:   e1a03803    lsl r3, r3, #16
81dc:   e1a01823    lsr r1, r3, #16
81e0:   e1a0300c    mov r3, ip
81e4:   e1a02003    mov r2, r3
81e8:   e2833002    add r3, r3, #2  ; 0x2
81ec:   e1a03803    lsl r3, r3, #16
81f0:   e1a03823    lsr r3, r3, #16
81f4:   e1530001    cmp r3, r1
81f8:   1afffff9    bne 81e4 <setup_framebuffer+0x5c>

81e4周围不应该有str cmd吗?要进一步添加GetGPU_Pointer来自汇编程序文件,但有一个声明就是这样。

extern unsigned int * GetGPU_Pointer(unsigned int framebufferAddress);

我的直觉是它的荒谬简单,但我很想念它。

2 个答案:

答案 0 :(得分:7)

您永远不会更改gpuPointer的值,并且您尚未声明它指向volatile。因此,从编译器的角度来看,您将覆盖单个内存位置(*gpuPointer)768 * 1024次,但由于您从未使用您正在写入的值,因此编译器有权通过在循环结束。

答案 1 :(得分:4)

添加到rici的答案(upvote rici not me)......

它变得更好,拿走你提供的东西并包装它

extern unsigned int * GetGPU_Pointer ( unsigned int );
void fun ( unsigned int framebufferAddress )
{
    unsigned int * gpuPointer = GetGPU_Pointer(framebufferAddress);
    unsigned int color = 16;
    int y = 768;
    int x = 1024;

    while(y >= 0)
    {
        while(x >= 0)
        {
            *gpuPointer = color;
            color = color + 2;
            x--;
        }

        color++;
        y--;
        x = 1024;
    }

}

优化

00000000 <fun>:
   0:   e92d4008    push    {r3, lr}
   4:   ebfffffe    bl  0 <GetGPU_Pointer>
   8:   e59f3008    ldr r3, [pc, #8]    ; 18 <fun+0x18>
   c:   e5803000    str r3, [r0]
  10:   e8bd4008    pop {r3, lr}
  14:   e12fff1e    bx  lr
  18:   00181110    andseq  r1, r8, r0, lsl r1

因为代码实际上除了那个商店之外什么都不做。

现在,如果你要修改指针

while(x >= 0)
{
    *gpuPointer = color;
    gpuPointer++;
    color = color + 2;
    x--;
}

然后你得到了你正在寻找的商店

00000000 <fun>:
   0:   e92d4010    push    {r4, lr}
   4:   ebfffffe    bl  0 <GetGPU_Pointer>
   8:   e59f403c    ldr r4, [pc, #60]   ; 4c <fun+0x4c>
   c:   e1a02000    mov r2, r0
  10:   e3a0c010    mov ip, #16
  14:   e2820a01    add r0, r2, #4096   ; 0x1000
  18:   e2801004    add r1, r0, #4
  1c:   e1a0300c    mov r3, ip
  20:   e4823004    str r3, [r2], #4
  24:   e1520001    cmp r2, r1
  28:   e2833002    add r3, r3, #2
  2c:   1afffffb    bne 20 <fun+0x20>
  30:   e28ccb02    add ip, ip, #2048   ; 0x800
  34:   e28cc003    add ip, ip, #3
  38:   e15c0004    cmp ip, r4
  3c:   e2802004    add r2, r0, #4
  40:   1afffff3    bne 14 <fun+0x14>
  44:   e8bd4010    pop {r4, lr}
  48:   e12fff1e    bx  lr
  4c:   00181113    andseq  r1, r8, r3, lsl r1

或者如果你使它变得不稳定(然后不必修改它)

volatile unsigned int * gpuPointer = GetGPU_Pointer(framebufferAddress);

然后

00000000 <fun>:
   0:   e92d4008    push    {r3, lr}
   4:   ebfffffe    bl  0 <GetGPU_Pointer>
   8:   e59fc02c    ldr ip, [pc, #44]   ; 3c <fun+0x3c>
   c:   e3a03010    mov r3, #16
  10:   e2831b02    add r1, r3, #2048   ; 0x800
  14:   e2812002    add r2, r1, #2
  18:   e5803000    str r3, [r0]
  1c:   e2833002    add r3, r3, #2
  20:   e1530002    cmp r3, r2
  24:   1afffffb    bne 18 <fun+0x18>
  28:   e2813003    add r3, r1, #3
  2c:   e153000c    cmp r3, ip
  30:   1afffff6    bne 10 <fun+0x10>
  34:   e8bd4008    pop {r3, lr}
  38:   e12fff1e    bx  lr
  3c:   00181113    andseq  r1, r8, r3, lsl r1

然后你得到你的商店

arm-none-eabi-gcc -O2 -c a.c -o a.o
arm-none-eabi-objdump -D a.o
arm-none-eabi-gcc (GCC) 4.8.2
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

问题是,正如所写的那样,你没有告诉编译器多次更新指针。因此,在我的第一个例子中,它没有理由甚至实现循环,它可以预先计算答案并将其写入一次。为了强制编译器实现循环并多次写入指针,你需要使它变得易变和/或修改它,取决于你真正需要做的事情。