2010-05-02 67 views
2

這是目前我和我的隊友所堅持的作業項目。我們對大會的介紹並沒有太多介紹,這應該是我們的第一個家庭作業練習。任務是創建一個將0xAABBCCDD轉換爲0xDDCCBBAA的程序。ARM Assembly - Converting Endianness

我不是在尋找答案,因爲那樣會打敗目的,但是我們對這個愚蠢的事情的困難感到非常沮喪。我們認爲我們在創建一個可行的解決方案方面有一個良好的開端,但我們無法拿出該計劃的其餘部分。

首先,我們掩蓋每一個三元組(AA),(BB),(CC),(DD)到一個不同的寄存器:

LDR R0, LittleEndian // 0xAABBCCDD 
AND R1, R0, #0xFF000000 // 0xAA 
AND R2, R0, #0x00FF0000 // 0xBB 
AND R3, R0, #0x0000FF00 // 0xCC 
AND R4, R0, #0x000000FF // 0xDD 

然後我們試圖把它們重新對準到R0寄存器,但如果我們能來到地獄了一個很好的解決方案......

我們最大的努力來自:

ORR R0, R1, LSL #24 
ORR R0, R2, LSL #8 
ORR R0, R3, LSR #8 
ORR R0, R4, LSR #24 

它生產0xBBBBCCDD一些奇怪的原因;我們真的不知道。

任何提示將不勝感激。再次,我們正在尋求幫助,但不是解決方案。

乾杯!

+2

還有一個特殊的功能。 BSWAP。 – 2012-07-14 09:16:00

回答

3

我認爲你需要做的(ARM有點生疏):在第一個指令

MOV R0, R1, LSR #24 
ORR R0, R2, LSR #8 
ORR R0, R3, LSL #8 
ORR R0, R4, LSL #24 

也就是說,MOV因爲你不想從舊R0什麼影響新值。

我看不出有什麼辦法讓這個更「暗示」,就像你已經有效地完成了所有的工作一樣。

+0

你認爲你可以詳細闡述一下這段代碼的工作原理嗎?爲什麼有必要首先將整個事物擺脫? – IAE 2010-05-02 22:27:22

+1

好吧,如果你在R0中仍然有R0的原始值,而你只是'或'將新的字節寫入R0,那麼不是隻有重新定位的字節R0會與R0的原始值一起產生一個不正確的結果。 – 2010-05-02 22:33:03

+0

感謝您的解釋!幫助了很多^^ – IAE 2010-05-02 22:36:24

3

您的代碼目前看起來不錯。

你的錯誤是,你已經顛倒了LSL和LSR的含義。

以R0例如:

AND R1, R0, #0xFF000000 // 0xAA 

這種操作的結果不會產生和0xAA。它生成0xAA000000。

的第二指令,其處理R1:

ORR R0, R1, LSL #24 

將數據移出寄存器。前8位沒有剩餘空間。

如果OTOH您的數據轉移到右邊是這樣的:

ORR R0, R1, LSR #24 

的數據最低字節結束。你想要它的位置。這應該給你足夠的幫助,以完成你的功課。 :-)

+0

感謝您的支持!如果你不介意的話,我還有另一個問題。 #24代表2^n,在這種情況下是2^24,對嗎?但是,如果我們總共只有0x00000000 = 8位,那麼我們真的在做過多的事情,寫入#24是不必要的,或者? – IAE 2010-05-02 22:19:53

+1

@SoulBeaver:否,則有8「半字節」(十六進制數字),其每一個是4位。 '0xAABBCCDD'是32位寬。 – 2010-05-02 22:56:42

1

另外,在使用ORR來移回位之前,看起來您可能沒有清除R0寄存器(將其設置爲全零位)。

5

在ARMv6及以上,你可以只使用rev指示,但我認爲你不能做到這一點無論出於何種原因。

至於爲什麼你得到了你做的結果是,我通過你的代碼了,並評論被操作的寄存器的實際值:

LDR R0, LittleEndian // r0 = 0xAABBCCDD 
AND R1, R0, #0xFF000000 // r1 = 0xAA000000 
AND R2, R0, #0x00FF0000 // r2 = 0x00BB0000 
AND R3, R0, #0x0000FF00 // r3 = 0x0000CC00 
AND R4, R0, #0x000000FF // r4 = 0x000000DD 

ORR R0, R1, LSL #24  // r0 = 0xAABBCCDD | 0x00000000 = 0xAABBCCDD 
ORR R0, R2, LSL #8  // r0 = 0xAABBCCDD | 0xBB000000 = 0xBBBBCCDD 
ORR R0, R3, LSR #8  // r0 = 0xBBBBCCDD | 0x000000CC = 0xBBBBCCDD 
ORR R0, R4, LSR #24  // r0 = 0xBBBBCCDD | 0x00000000 = 0xBBBBCCDD 

這裏發生的事情是,你有你的移動方向向後;而不是左移24移0xAA000000,要 24接班,讓0x000000AA。此外,你永遠不歸零的r0的內容,您也需要做這種方法的工作。如果你解決了這些問題,你的代碼將按預期工作(儘管有更緊湊的方法來完成相同的任務)。

2

雖然這個問題已很舊我一直想加入我的建議的代碼,因爲它只是需要6個指令,而不是8也只需要3個寄存器,而不是5.這應該是任何東西的最佳解決方案在armv6之前(它有rev指令)。

// We're starting with r0 = 4321 
mov r2, r0, lsr #24    // r2 = 0004 
and r1, r0, #16711680   // r1 = 0300 
orr r2, r2, r0, lsl #24   // r2 = 1004 
orr r2, r2, r1, lsr #8   // r2 = 1034 
and r0, r0, #65280    // r0 = 0020 
orr r0, r2, r0, lsl #8   // r0 = 1234