как эффективно построить маску - PullRequest
0 голосов
/ 24 марта 2012

У меня есть метод в c # только с 1 параметром (это переопределение, поэтому я не могу изменить его сигнатуру для включения большего количества параметров):

read_address(long adr)

где adr - адресная память, которую я хочу прочитать, но я должен передать адрес и одновременно указать, является ли адрес для чтения 16- или 32-битным, а если 32-битным, более того, я должен указать, хочу ли я читать верхнее или нижнее слово, поэтому я хотел бы узнать эффективный способ сделать это с помощью параметра adr.

Я подумал построить маску, например, если я хочу прочитать адрес 614 (десятичный), я могу добавить две цифры до или назад:

10614: первая цифра 1 обозначает размер = 32 бита, а вторая 0 = младшее слово
11614: первая цифра 1 обозначает размер = 32 бита, а вторая 1 = старшее слово

для обозначения 16 бит, нет необходимости указывать нижний или верхний, поэтому:

00614 = 614 будет означать 16-бит.

Также я могу сделать это, вернув эти две цифры обратно:

61410
61411

Поэтому, когда я получаю это число через параметр addr, мне нужно проанализировать его, чтобы узнать, является ли оно 16 или 32-разрядным, а в случае 32 - младшим или верхним словом.

РЕДАКТИРОВАНИЕ:

Я думаю, что не очень хорошо объяснил ...

Например, представьте, что этот метод read_address, receive и address (addr) для чтения. Это вызывается из другого метода method_A, который знает, является ли он 16- или 32-разрядным, а если 32-разрядным, он разделяется на два слова. Лучший пример для чтения 614:

Method_A(....)
{
   if 16-bit then

   {
       call read_address(620) // Supose 620 is 16 bit
   }

   if 32-bit then

   { 

       // suppose 614 is 32 bit so split into two reads

       call read_address(61410)  // to read first word

       call read_address(61411) // to read second word

   } 

}

поэтому в read_address я должен знать, является ли он 16- или 32-разрядным, а если 32-разрядным, я также должен знать, является ли оно нижним или верхним словом.

read_address(long addr)

{

    // decode if addr is 16 or 32 bit and if 32 bit, decode if lower

    // or upper word and do some stuff


    // So suppose it arrives 61410... how to decode it in order to know,

    // address to read is 614 and is 32-bit (1) and I want to read lower word (0)


}

Ответы [ 2 ]

3 голосов
/ 24 марта 2012

Вы упоминаете, что слово "верхний / верхний" имеет значение только тогда, когда addr указывает 32-разрядный адрес - надеюсь, вы имели в виду, что оно рассчитывает только на 16-разрядный код? (если нет, как вы узнаете, является ли значение «10» маской или адресом?)

Я бы не использовал десятичные позиции для маски, а скорее разделил бы 64 бита на два 32-битных числа (целые числа) и использовал бы двоичные флаги.

Пример 614 в виде 64-битного числа в двоичном виде будет (надеюсь, я правильно понял порядковый номер, но он должен проиллюстрировать ситуацию):

00000010 00000000 00000000 00000000 01100110 00000010 00000000 00000000
|              Mask               | |            Address              |

Затем вы можете использовать [Flags] enum, чтобы определить маску, и привести целое число маски к этому перечислению. Вот пример создания и разбора адреса:

    public void Main()
    {
        // Some test values.
        ushort address16 = ushort.MaxValue;
        uint address32 = uint.MaxValue;

        // Upper:
        ulong valueUpper = address16;           // Value contains 0x000000000000FFFF
        valueUpper = valueUpper << 48;          // Value contains 0xFFFF000000000000
        valueUpper += (uint)Mask.Upper;         // Value contains 0xFFFF000000000001

        // Lower:
        ulong valueLower = address16;           // Value contains 0x000000000000FFFF
        valueLower = valueLower << 32;          // Value contains 0x0000FFFF00000000
        // No need to set a 0-bit, it is already 0

        // DWord:
        ulong valueDword = address32;           // Value contains 0x00000000FFFFFFFF
        valueDword = valueDword << 32;          // Value contains 0xFFFFFFFF00000000
        valueDword += (uint)Mask.DoubleWord;    // Value contains 0xFFFFFFFF00000010

        ulong addr1 = ParseAddress((long)valueUpper);
        ulong addr2 = ParseAddress((long)valueLower);
        ulong addr3 = ParseAddress((long)valueDword);
    }

    public ulong ParseAddress(long address)
    {
        // Casting to ulong, as negative values don't make sense in addresses or bitwise operations.
        ulong value = (ulong)address;

        // Take the mask from the least significant bits
        Mask mask = (Mask)(value & uint.MaxValue);

        // Shift the mask bytes "off" the addr, get the remaining address. 
        ulong addr = ((ulong)value >> 32);

        // Is the doubleword bit set?
        if ((mask & Mask.DoubleWord) == Mask.DoubleWord)
        {
            return addr;
        }
        else if ((mask & Mask.Upper) == Mask.Upper)
        {
            return (addr >> 16);
        }
        else
        {
            return addr;
        }
    }

    [Flags]
    public enum Mask : uint
    {
        Upper = 1,
        DoubleWord = 2,
    }
0 голосов
/ 24 марта 2012

это переопределение, поэтому я не могу изменить его подпись для включения большего количества параметров

Хотя вы не можете переопределить виртуальный метод и изменить его подпись одновременно, вы может определить перегрузку в вашем подклассе, которая принимает эти дополнительные параметры.например:

class SuperClass
{
    public virtual void read_address(long adr)
    {

    }
}

class SubClass : SuperClass
{
    public override void read_address(long adr)
    {
        // call the overload with your default values e.g. 32 and false
        this.read_address(adr, 32, false);
    }

    public void read_address(long adr, int bytesToRead, bool upper)
    {
        // ...
    }
}
...