这个汇编代码什么都没做

我正在使用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" ); 

代码没有做任何事情。

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

编辑:在读完你的答案之后,我还有另一个问题:我如何在寄存器中放置一个常数值? 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)”。 阅读之后: 修复后无效的常数? 我不知道如何把这个值放到r3中,因为我似乎无法用mov.I使用armv4,而不是armv7。 在链接中提出的这个解决方案对我不起作用:

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

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

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

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

 00000000 
: 0: e92d4008 push {r3, lr} 4: e59f0008 ldr r0, [pc, #8] ; 14 8: ebfffffe bl 0 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 
: 0: e92d4008 push {r3, lr} 4: e59f0008 ldr r0, [pc, #8] ; 14 8: ebfffffe bl 0 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 : 0: e59f0000 ldr r0, [pc] ; 8  4: eafffffe b 0  8: 560000a0 strpl r0, [r0], -r0, lsr #1 

那好吧。 您走在正确的道路上,看看C编译器生成了什么,然后模仿或修改它。 我怀疑这是你的ioread是问题,而不是外部结构(你为什么要做一个64位的32位读取的东西,也许这就是问题,它很可能会被实现为64位)。

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

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

不确定在assembly中这样做有什么意义。 如果你坚持这一点,以下应该会更好一些:

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