ARM gcc内联汇编程序优化问题

ARM gcc内联汇编程序优化问题,arm,assembly,Arm,Assembly,为什么当我有优化标志-O3时,我的内联汇编程序例程不工作,但它与其他优化标志(-O0,-O1,-O2,-Os)一起工作 我甚至将volatile添加到我所有的汇编指令中,我认为这会告诉编译器不要触摸或重新排序任何东西 致意 Gigu先生这确实应该是一个评论,但出于某种原因,我无法发表评论:( 编译器优化不应该真的弄乱你的程序集。因此,正如Igor所说,这种“不起作用”的方式是什么?也许你的ASM分支成了一个函数,这个函数已经被编译器优化,给你的程序集代码可能依赖的结果带来了不同的结果 关于编译器

为什么当我有优化标志-O3时,我的内联汇编程序例程不工作,但它与其他优化标志(-O0,-O1,-O2,-Os)一起工作

我甚至将volatile添加到我所有的汇编指令中,我认为这会告诉编译器不要触摸或重新排序任何东西

致意


Gigu先生

这确实应该是一个评论,但出于某种原因,我无法发表评论:(

编译器优化不应该真的弄乱你的程序集。因此,正如Igor所说,这种“不起作用”的方式是什么?也许你的ASM分支成了一个函数,这个函数已经被编译器优化,给你的程序集代码可能依赖的结果带来了不同的结果


关于编译器的一些源文件或更多信息可能有用

这确实应该是一个注释,但由于某些原因,我无法发布一个注释:(

编译器优化不应该真的弄乱你的程序集。因此,正如Igor所说,这种“不起作用”的方式是什么?也许你的ASM分支成了一个函数,这个函数已经被编译器优化,给你的程序集代码可能依赖的结果带来了不同的结果


关于编译器的一些源文件或更多信息可能有用

GCC内联汇编程序对正确的规范非常敏感

特别是,您必须非常精确地指定正确的约束,以确保编译器不会决定“优化”您的汇编代码。有几件事需要注意。举个例子

以下两项:

int myasmfunc(int arg) /* definitely buggy ... */ { register int myval asm("r2") = arg; asm ("add r1, r0, #22\n" ::: "r1"); asm ("adds r0, r1, r0\n" ::: "r0", "cc"); asm ("subeq r2, #123\n" ::: "r2"); asm ("subne r2, #213\n" ::: "r2"); return myval; } 正如您所看到的,这两个版本都没有达到您希望看到的效果;但是,在
gcc-c-O8…
上,代码的第二个版本最终是:

Disassembly of section .text: 00000000 : 0: e1a03000 mov r3, r0 4: e2833016 add r3, r3, #22 ; 0x16 8: e0933000 adds r3, r3, r0 c: 0240007b subeq r0, r0, #123 ; 0x7b 10: 124000d5 subne r0, r0, #213 ; 0xd5 14: e12fff1e bx lr 第节的分解。正文: 00000000 : 0:e1a03000 mov r3,r0 4:e2833016添加r3,r3,#22;0x16 8:e0933000添加r3、r3、r0 c:0240007b子等式r0,r0,#123;0x7b 10:124000d5子网r0,r0,#213;0xd5 14:E12FF1E bx lr 这就是您在程序集中指定的内容,以及您所期望的内容


士气:对约束、操作数赋值要明确准确,并将相互依赖的汇编行保持在相同的
asm()
块中(生成多行语句)。

GCC内联汇编程序对正确的规范非常敏感

特别是,您必须非常精确地指定正确的约束,以确保编译器不会决定“优化”您的汇编代码。有几件事需要注意。举个例子

以下两项:

int myasmfunc(int arg) /* definitely buggy ... */ { register int myval asm("r2") = arg; asm ("add r1, r0, #22\n" ::: "r1"); asm ("adds r0, r1, r0\n" ::: "r0", "cc"); asm ("subeq r2, #123\n" ::: "r2"); asm ("subne r2, #213\n" ::: "r2"); return myval; } 正如您所看到的,这两个版本都没有达到您希望看到的效果;但是,在
gcc-c-O8…
上,代码的第二个版本最终是:

Disassembly of section .text: 00000000 : 0: e1a03000 mov r3, r0 4: e2833016 add r3, r3, #22 ; 0x16 8: e0933000 adds r3, r3, r0 c: 0240007b subeq r0, r0, #123 ; 0x7b 10: 124000d5 subne r0, r0, #213 ; 0xd5 14: e12fff1e bx lr 第节的分解。正文: 00000000 : 0:e1a03000 mov r3,r0 4:e2833016添加r3,r3,#22;0x16 8:e0933000添加r3、r3、r0 c:0240007b子等式r0,r0,#123;0x7b 10:124000d5子网r0,r0,#213;0xd5 14:E12FF1E bx lr 这就是您在程序集中指定的内容,以及您所期望的内容


士气:对约束、操作数赋值要明确、准确,并将相互依赖的汇编行保持在同一块中(生成多行语句)。

定义“不工作”.你期望它做什么?发生了什么事?例行程序是怎么做的?你怎么称呼它?你能公布来源吗?你看过生产的二进制文件的分解吗?在两年后重新审视我的问题后,我意识到我的问题是多么荒谬,信息非常少。这让FrankH成功地解决了一个问题更令人印象深刻回答我的问题。问题是我没有在内联汇编程序中指定任何破坏寄存器值的clobber列表。使用某些优化的原因可能是巧合。定义“不工作”.你期望它做什么?发生了什么事?例行程序是怎么做的?你怎么称呼它?你能公布来源吗?你看过生产的二进制文件的分解吗?在两年后重新审视我的问题后,我意识到我的问题是多么荒谬,信息非常少。这让FrankH成功地解决了一个问题更令人印象深刻回答我的问题。问题是我没有在内联汇编程序中指定任何破坏寄存器值的破坏器列表。使用某些优化的原因可能是巧合。新手不能评论。:-)首先你需要50分。我会给你10分,但这完全是毫无根据的。在
gcc
中,编译器优化会以非常重要的方式干扰你的内联程序集,除非你非常小心你的要求。这对许多人来说是可以理解的,但这是出于设计/意图,不太可能改变。@FrankH-Oh,没有意识到GCC也会玩弄内联汇编,抱歉新手不能评论:-)你需要先得50分。在
gcc
中,编译器优化将以非常重要的方式干扰内联程序集,除非您非常小心地提出要求。这对许多人来说是一个可以理解的抱怨,但这是出于设计/意图,不太可能改变。@FrankH-Oh,不知道GCC也会在内联汇编中捣乱,抱歉