簡體   English   中英

在32位字存儲器中連續讀取3個字節

[英]Reading successive 3 bytes in a 32-bit word memory

我有一個32位字可尋址存儲器,並且我的數據段可以在存儲器中的任何字節處開始和結束。

假設我的數據段從字0x3的字節2(0為最低字節)開始。

然后,我必須從字0x3的字節2和3和字0x4的字節0中讀取數據。 之后,我必須讀取字0x4的字節1、2和3,依此類推...並且僅當我所有3個字節都為零或我的數據段結束時才停止。 下一部分具有可擴展的邊界,可以移入我的數據部分,因此末尾字或字節不固定。

您是否對解決此問題的最佳算法有任何建議? 我想出了一種創建總共24位的兩個掩碼的方法,這些掩碼可以在單詞之間移動,但是這似乎有些過分,並且給了我很大的代碼。 我正在嘗試以最少的C指令來解決它。 期待您的建議。

從您的陳述中可以看出,您一次只能讀取32位字,而不能讀取16位或8位字,這也意味着您不必思考/談論對齊問題。

就像支持字節可尋址內存的處理器一樣,如果地址為0x1002並且有一些24位項,則可以用相同的方式實現它。

0x1002 = 0b0001000000000010低位兩位描述字中的字節,高位位代表字號/地址0b00010000000000 0b10,因此字地址0x400從字節2開始(字節序當然是一個因素,假設很小)。 您還知道4-0b10 = 2表示該字中還有兩個字節,如果需要第三個字節,則從下一個字的偏移量0開始。

因此您可以執行以下未經測試的代碼:

unsigned int get24 ( unsigned int x )
{  
    unsigned int ra;
    unsigned int ret;
    unsigned int wa;
    unsigned int shift;
    unsigned int rb;

    ret=0;
    wa=x>>2;
    shift=(x&3)<<3;
    rb=load32(wa);
    for(ra=0;ra<3;ra++)
    {
       ret<<=8;
       ret|=(rb>>shift)&0xFF;
       shift+=8;
       if(shift>=32)
       {
           wa++;
           rb=load32(wa);
           shift=0;
       }
    }
}

您可以在另一個答案中采用基於字節的方法,但是必須確保編譯器知道基於字的內存限制,不允許進行字節讀取(取決於體系結構),也不能進行未對齊的訪問(取決於架構)。

您可以嘗試基於表

//0x00000000 0x00FFFFFF
//0x00000000 0xFFFFFF00
//0x000000FF 0xFFFF0000
//0x0000FFFF 0xFF000000

unsigned int al[4]={0,0,24,16};
unsigned int ar[4]={0,0,8,8};
unsigned int bl[4]={8,0,16,24};
unsigned int br[4]={8,8,16,24};

unsigned int wa;
unsigned int off;
unsigned int ra;
unsigned int rb;
unsigned int ret;

wa=byte_address>>2;
off=byte_address&3;
rb=load32(wa);
ret=(rb<<bl[off])>>br[off];
//ret=(rb<<bl[off])>>(off<<3);
if(off&2)
{
    ra=load32(wa+1);
    //ret|=(ra<<al[off])>>ar[off];
    ret|=(ra<<al[off])>>8;
}

或基於跳轉表

wa=byte_address>>2;
rb=load32(wa);
//if(byte_address&0xC)
ra=load32(wa+1);
switch(byte_address&3)
{
    case 0:
    {
        ret=(rb<<8)>>8;
        break;
    }
    case 1:
    {
        ret=rb>>8;
        break;
    }
    case 2:
    {
        ret=(rb<<16)>>16;
        ret|=(ra<<24)>>8;
        break;
    }
    case 3:
    {
        ret=(rb<<24)>>24;
        ret|=(ra<<16)>>8;
        break;
    }
}

我不太理解下一節的意思, 可擴展的邊界它可以移動 忽略下面的代碼應該可以讀取數據:

int start_word = 3;
int start_byte = 2;
int end_word = 100;
uint8_t* p = data + start_word * 4 + start_byte;
uint8_t* end = data + end_word * 100;

while (p + 3 <= end) { // 3 more bytes must be available
    uint8_t b0 = *p++;
    uint8_t b1 = *p++;
    uint8_t b2 = *p++;
    if (b0 == 0 && b1 == 0 && b2 == 0)
         break;
    // do something with the 3 bytes
}

這個想法不是太在乎單詞,而是按字節工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM