2017-10-07 111 views
1

我試圖將PowerPC asm片段轉換爲C++。這是我到目前爲止所做的:PowerPC extsb在C

PPC: 
lis  r11, ((dword_83EEF800+0x10000)@h) 
lis  r10, 0x20 # 0x207E90 
addi  r11, r11, -0x800 # dword_83EEF800 
ori  r10, r10, 0x7E90 # 0x207E90 
lis  r9, 4 # 0x46E80 
ori  r9, r9, 0x6E80 # 0x46E80 
lwzx  r11, r11, r10 
subf  r11, r11, r28 
divw  r11, r11, r9 
extsb  r3, r11 // Problem 

C++: 
DWORD r11 = 0x83EEF800 + 0x10000; 
r11 += -0x800; 
DWORD r10 = 0x207E90; 
DWORD r9 = 0x46E80; 
r11 = *(DWORD*)(r11 + r10); 
r11 -= r28; 
r11 /= r9; 

現在我的問題,我到底怎麼會在C++中編碼「extsb」?該文檔說明了在這種情況下r11中的最低有效字節並將其存儲在r3的低序8位中。然後它將位56(在這種情況下是24,因爲它是一個32位寄存器)放入r3的其餘位。爲了讓R11的至少顯著字節我會做到這一點:

r11 & 0xFF 

,但我不知道如何讓24位,並用它來填補R3的其餘位。我只能使用本機C++!如果有人知道我可以如何將這個ppc操作轉換爲C++,請告訴我(如果我發佈的轉換後的ppc代碼有任何重大錯誤,請告訴我)。提前致謝!

參考:https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/com.ibm.aix.alangref/idalangref_extsb_instruction.htm

+0

難道你不能只使用內聯彙編? – user0042

+0

@ user0042 like'DWORD r3; __asm {extsb r3,r11}'?我可以做到這一點,但我想了解它是如何工作在C++ – SupaDupa

回答

1

extsb文件條目的標題說,記憶是短暫的擴展符號字節。即執行2's complement sign-extension.

它看起來像PowerPC從左邊開始編號的位,所以高位是位0,低位是位31.低8位的符號位因此是位24,並且此指令只是執行符號擴展。

#include <stdint.h> 
int32_t sign_extend_8(int src) { 
    return (int32_t) (int8_t) src; 
} 

編譯成(gcc4.8 for PowerPC, -O3 -std=c++03,因爲Godbolt沒有安裝更新的PPC GCC):

extsb %r3,%r3 
    blr 

所以這樣做,所以我們知道他們可能都是對的:

// requires 2's complement arithmetic right shifts 
int32_t extsb_manual(uint32_t src) { 
    src <<= 24; 
    return ((int32_t)src) >> 24; // signed right shift. 
} 

ISO C++表示它取決於實現當你移動一個負數時會發生什麼,但是大多數實現(和一些方言,例如GNU C++)保證了右移的2的補碼延伸。即轉移高位的副本。

這可以讓你用算術右移播放一點。例如foo >> 31產生0或-1(在2的補碼系統中)。

我很抱歉,但即時通訊不能使用C++ 11:

#include <cstdint>stdint.h不需要C++ 11。至少在C++ 03以前,它已經存在了,如果不是更早的話。 (Godbolt的PPC gcc4.8似乎被部分分解,#include <cstdint>出現了錯誤,可能是因爲它從一個較新的gcc的。這就是爲什麼我用C <stdint.h>頭,即使在C++。)


起初,我是假設「低8位「是0-7,就像我見過的所有其他架構一樣,第24位是高字節的一部分。這將使一個很奇怪的指令,但這裏的你怎麼能實現它(再次使用算術右移):

// requires 2's complement arithmetic right shifts 
uint32_t extsb_wrong(uint32_t src) { 
    int32_t signbits = src << (31-24); // move bit 24 to the top (bit 31) 
    signbits >>= 31;   // broadcast the sign bit 

    // replace the low 8 of the 0/-1 with the low 8 of the src  
    return ((uint32_t)signbits & ~0xFFU) | (src & 0xFFU); 
} 

當然這並不編譯爲extsb。這是一組實際的移位和AND/ORing。

+0

非常感謝,它現在正在工作! :)你似乎知道你的東西,保持良好的工作! – SupaDupa

1

的等價的C簡單的是通過投int8_t

r3 = (int32_t) (int8_t) r11; 
+0

哦,所以OP描述'extsb'錯了?他們說,它廣播24位的原始,而不是低8的符號位。我認爲助記符聽起來應該只是符號擴展,但它是PowerPC,所以它可以是任何東西... –

+0

i'對不起,但即時通訊不能使用C++ 11:/ – SupaDupa

+0

@PeterCordes對不起,我只是解釋它,這是我用作參考:https://www.ibm.com/support/knowledgecenter/en/ ssw_aix_72/com.ibm.aix.alangref/idalangref_extsb_instruction.htm – SupaDupa