这个汇编代码什么都没做

时间:2014-04-01 09:59:19

标签: c assembly arm

我正在使用C文件,这是这样的:

    #define v2      0x560000a0
    int main(void)
    {
        long int v1;
        v1 = ioread32(v2);
        return 0;
    }

并且我已经提取了这部分以在汇编中编写它:

int main ()
{
    extern v1,v2;
    v1=ioread32(v2);
    return 0;
}

我正在尝试使用armv4的汇编代码在v1中写入v2的值。使用

arm-linux-gnueabi-gcc -S -march=armv4 assembly_file.c

我收到了这段代码:

.arch armv4
.eabi_attribute 27, 3
.fpu vfpv3-d16
.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   "txind-rsi.c"
.text
.align  2
.global main
.type   main, %function

main:
@ Function supports interworking.
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 1, uses_anonymous_args = 0
stmfd   sp!, {fp, lr}
add fp, sp, #4
ldr r3, .L2
ldr r3, [r3, #0]
mov r0, r3
bl  ioread32
mov r2, r0
ldr r3, .L2+4
str r2, [r3, #0]
mov r3, #0
mov r0, r3
sub sp, fp, #4
ldmfd   sp!, {fp, lr}
bx  lr

.L3:
.align  2

.L2:
.word   v1
.word   v2
.size   main, .-main
.ident  "GCC: (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3"
.section    .note.GNU-stack,"",%progbits

我使用该代码以这种方式将其放回C文件中:

asm volatile(
    "stmfd  sp!, {fp, lr}\n"
    "add    fp, sp, #4\n"
    "ldr    r3, =v1\n"
    "ldr    r3, [r3, #0]\n"
    "mov    r0, r2\n"
    "ldr    r3, =v2\n"
    "str    r2, [r3, #0]\n"
    "sub    sp, fp, #4\n"
    "ldmfd  sp!, {fp, lr}\n"
    "bx lr"
);

代码没有做任何事情。

实际上,它会阻止目标工作。 有人知道为什么吗?

EDITED: 在阅读你的答案后,我有另一个问题: 我如何在寄存器中放置一个常量值? C中的代码是这样的:

#define v2      0x560000a0
int main(void)
{
    long int value = 0x0000ffff;
    long int v1;
    v1 = ioread32(v2);
    iowrite32(v2,value);
    return 0;
}

我试过这个:

asm volatile("mov r3, #value");

我得到一个汇编信息:“值符号在不同的部分”; 我也试过了

asm volatile("mov r3, #0x0000ffff);

和汇编程序消息是: “修复后的无效常量(ffff)”。阅读完本后:Invalid constant after fixup? 我不知道如何把这个值放到r3中,因为我似乎无法用mov.I使用armv4,而不是armv7。在链接中提出的这个解决方案对我不起作用:

asm volatile("ldr   r3, =#0000ffff\n");

2 个答案:

答案 0 :(得分:2)

你的代码没有问题,bx lr是终止main的正确方法,没有问题。由于您正在访问的地址,您的代码很可能会崩溃,它可能不是您可以访问的地址...

#define v2      0x560000a0
    int main(void)
    {
        long int v1;
        v1 = ioread32(v2);
        return 0;
    }

如果优化C编译步骤,您可以看到更简洁的版本

00000000 <main>:
   0:   e92d4008    push    {r3, lr}
   4:   e59f0008    ldr r0, [pc, #8]    ; 14 <main+0x14>
   8:   ebfffffe    bl  0 <ioread32>
   c:   e3a00000    mov r0, #0
  10:   e8bd8008    pop {r3, pc}
  14:   560000a0    strpl   r0, [r0], -r0, lsr #1

这在asm中并不难实现。

.globl main
main:
    push {r3,lr}
    ldr r0,=0x560000A0
    bl ioread32
    mov r0,#0
    pop {r3,pc}

组装和拆卸

00000000 <main>:
   0:   e92d4008    push    {r3, lr}
   4:   e59f0008    ldr r0, [pc, #8]    ; 14 <main+0x14>
   8:   ebfffffe    bl  0 <ioread32>
   c:   e3a00000    mov r0, #0
  10:   e8bd8008    pop {r3, pc}
  14:   560000a0    strpl   r0, [r0], -r0, lsr #1

您已将代码简化为v1变为死代码,但函数调用无法优化,因此返回将被丢弃。

如果你不使用main但是创建一个单独的函数返回

#define v2      0x560000a0
    long int fun(void)
    {
        long int v1;
        v1 = ioread32(v2);
        return v1;
    }

...该死...尾部优化:

00000000 <fun>:
   0:   e59f0000    ldr r0, [pc]    ; 8 <fun+0x8>
   4:   eafffffe    b   0 <ioread32>
   8:   560000a0    strpl   r0, [r0], -r0, lsr #1
好吧,好吧。您走在正确的道路上,看看C编译器生成了什么,然后模仿或修改它。我怀疑这是你的ioread是问题,而不是外部结构(你为什么用32位读取做64位的事情,也许这就是问题很长,它很可能会被实现为64位)。 / p>

答案 1 :(得分:1)

最后的bx lr会尝试从当前函数返回。你可能不希望这样。我想这也是崩溃的原因,因为你不要让编译器撤消它在函数序言中所做的任何设置。

此外,在您的asm块中,您不使用任何本地,因此您不需要调整堆栈指针,也不需要新的堆栈帧。由于您已将值加载到mov r0, r2r3也会被破坏。如果您只是直接加载到您想要的任何寄存器中,您可以删除mov。此外,在gcc内联asm中,您应该告诉编译器您修改了哪些寄存器。不这样做也会导致崩溃,因为您可能会覆盖编译器所依赖的值。

不确定在装配中这样做有什么意义。如果你坚持这一点,以下应该会有所改善:

asm volatile(
    "ldr    r3, =v1\n"
    "ldr    r2, [r3, #0]\n"
    "ldr    r3, =v2\n"
    "str    r2, [r3, #0]\n" ::: "r2", "r3"
);