2017-08-18 57 views
0

我正在編寫C代碼並編譯爲PowerPC體系結構。我想告訴編譯器用分支替換所有類似返回的指令,直到函數代碼的末尾。這是由於一些奇怪的要求,在這段代碼中我不能使用任何返回來確保稍後再執行幾行彙編。GCC避免編譯分支鏈接寄存器(blr)語句

舉例來說,我編C代碼到下面的彙編代碼:

lis r9,4096 
lis r8,255 
lwz r10,0(r9) 
ori r8,r8,65535 
addi r9,r10,192 
cmplw cr7,r9,r8 
blelr- cr7 # Return if the cr7 register is "less than or equal" 
lis r8,512 
cmplw cr7,r9,r8 
bgtlr- cr7 # Return if the cr7 register is "greater than or equal" 
lwz r10,192(r10) 
lis r8,303 
ori r8,r8,65535 
addi r9,r10,320 
cmplw cr7,r9,r8 
blelr- cr7 # Return if the cr7 register is "less than or equal" 
lis r8,528 
cmplw cr7,r9,r8 
bgtlr- cr7 # Return if the cr7 register is "greater than or equal" 
lwz r10,320(r10) 
lis r8,287 
ori r8,r8,65535 
subi r9,r10,448 
cmplw cr7,r9,r8 
blelr- cr7 
lis r8,544 
cmplw cr7,r9,r8 
bgtlr- cr7 # Return if the cr7 register is "greater than or equal" 
lis r9,4919 
ori r9,r9,4919 
stw r9,-448(r10) 
blr # Return 

我想是所有與一個總是跳轉到該函數的代碼等作爲最終被替換的回報類的語句如下:

lis r9,4096 
lis r8,255 
lwz r10,0(r9) 
ori r8,r8,65535 
addi r9,r10,192 
cmplw cr7,r9,r8 
ble _END # Branch to the _END label if "less than" 
lis r8,512 
cmplw cr7,r9,r8 
bgt _END # Branch to the _END label if "greater than" 
lwz r10,192(r10) 
lis r8,303 
ori r8,r8,65535 
addi r9,r10,320 
cmplw cr7,r9,r8 
ble cr7 # Branch to the _END label if "less than" 
lis r8,528 
cmplw cr7,r9,r8 
bgt _END # Branch to the _END label if "greater than" 
lwz r10,320(r10) 
lis r8,287 
ori r8,r8,65535 
subi r9,r10,448 
cmplw cr7,r9,r8 
blelr- cr7 
lis r8,544 
cmplw cr7,r9,r8 
bgt _END # Branch to the _END label if "greater than" 
lis r9,4919 
ori r9,r9,4919 
stw r9,-448(r10) 
_END: 
blr # I guess it should stay otherwise the function call will continue executing "random" garbage such as the next function in the .text section. Via post-processing this would be easy to strip though! 

任何方法來自動執行此編譯偏好?

+0

'我不能在這段代碼中使用任何返回來確保稍後再執行幾行彙編。返回後,將這些「組裝線」與C分開調用? –

+1

我的意思是,你建議編譯器應該優化否定性:( –

+0

是的,因爲同樣的程序集會被附加在'C'函數的末尾,所以返回並不好,它仍然需要執行它並且它是從C函數機器代碼和程序集部分 – BullyWiiPlaza

回答

2

來自@Jester和@fuz的評論提供了一個答案,我只是把它寫下來。

您需要:

  1. 避免返回在函數中,在C代碼。因此請用goto替換return
  2. 防止編譯器弄清楚goto end;return;是一回事。內聯彙編是告訴編譯器「不要混淆這個」的好方法。

對於某些宏:

#define RETURN goto _end
#define END _end: asm volatile("")
void foo(int x) { if (x==1) RETURN; if (x==2) RETURN; printf("Hello, world\n"); END; }

asm volatile("")指示編譯器插入一些彙編代碼。編譯器不知道這個彙編代碼是幹什麼的,所以它不能做任何可以跳過它的優化(即使在0指令的情況下)。

+0

是的,'asm volatile(「」)'做了竅門。它按預期工作:) – BullyWiiPlaza