【发布时间】:2020-03-06 06:41:23
【问题描述】:
考虑以下代码:
// String literals
#define _def0Impl(a0) #a0
#define _def0(a0) _def0Impl(a0)
// Labels
#define _asm_label(tag) tag: asm volatile (_def0(tag) ":")
// Assume 32 bits
typedef unsigned int uptr;
int main (int argc, void *argv[]) {
register int ctr, var;
uptr tbl[0x4];
ctr = 0x0;
var = 0x0;
// Push some tasks to tbl ...
// Suppose that tbl holds {&&tag0, &&tag1, &&tag2, &&tag1}
// Suppose that ctr holds 0xC
// tag* may exported to somewhere else.
ctr = 0x3 * sizeof(uptr);
tbl[0x0] = &&tag0;
tbl[0x1] = &&tag1;
tbl[0x2] = &&tag2;
tbl[0x3] = &&tag1;
// Run tasks table
goto *(((uptr)&tbl[0x0]) + ctr);
_asm_label(tag2);
// Task I
ctr -= sizeof(uptr);
var += 0x1;
goto *(((uptr)&tbl[0x0]) + ctr);
_asm_label(tag1);
// Task II
ctr -= sizeof(uptr);
var -= 0x1;
goto *(((uptr)&tbl[0x0]) + ctr);
_asm_label(tag0);
// Continue executation
return var;
}
我可以用内联汇编重写这个实现吗?
旧语句
考虑以下代码:
#define _asm_label(tag) asm volatile(tag ":")
// PowerPC for example
#define _asm_jump(tag) asm volatile ("b " tag)
#define _asm_bar() asm volatile ("" ::: "cc", "memory")
int main(int argc, void *argv[]) {
register int var;
var = 0;
_asm_jump("bar");
_asm_bar(); // Boundary
var += 1;
_asm_label("bar");
_asm_bar(); // Boundary
var += 1;
return var;
}
用-O0 gcc 生成:
li 30,0
b bar
# 0 "" 2
addi 30,30,1
bar:
# 0 "" 2
addi 30,30,1
mr 9,30
mr 3,9 # r3 = 0x1
但使用 -O2:
b bar
# 0 "" 2
bar:
# 0 "" 2
lwz 0,12(1) # restore link register
li 3,2 # incorrect
由于语句已优化,因此输出不正确。
有没有办法在 GCC 中设置优化的“障碍”?
编辑:尝试 #1
将 volatile 添加到 var。
使用-O2:
li 9,0
stw 9,8(1)
# 10 "attempt1.c" 1
b bar
# 0 "" 2
lwz 9,8(1)
addi 9,9,1
stw 9,8(1)
# 15 "attempt1.c" 1
bar:
# 0 "" 2
lwz 9,8(1)
lwz 0,28(1)
addi 9,9,1
stw 9,8(1)
在这种情况下,var 被放入堆栈 (r1 + 0x8)。
但是,将 volatile 置于 var 将停止所有关于 var 的优化。
我正在考虑使用 asm goto,但它仅适用于 gcc >= 4.5, iirc。
【问题讨论】:
-
试着让
var也变得易变。