В моем классе машинного языка мы должны перевести c++ в mips, проблема в том, что я мало знаю c++, просто базовые вещи, поэтому у меня возникают проблемы с занижением этой функции:
void IPtoDD(int arg0, char *arg1)
{
int temp, numChar, shift = 24;
for (int i=0; i<4; i++) {
temp = arg0 >> shift;
temp = temp & 0x000000ff;
numChar = byteToDec(temp,arg1);
arg1 += numChar;
*arg1++ = '.';
shift -= 8;
}
В частности
temp = arg0 >> shift;
temp = temp & 0x000000ff;
Оператор >>
является "оператором сдвига справа". Он сдвинет двоичное представление значения слева на x бит справа, где x - число справа. Как это выглядит? Вот некоторые примеры:
decimal: 128 >> 1 == 64
binary: 0b0000 0000 1000 0000 >> 1 == 0b0000 0000 0100 0000
decimal: 64 >> 1 == 32
binary: 0b0000 0000 0100 0000 >> 1 == 0b0000 0000 0010 0000
Обратите внимание, как 1 в больших двоичных числах сдвигается вправо на 1. В вашем коде вы arg0
по shift
, где arg0
- это некоторый ввод, а shift
- 24, 16, 8, затем 0, поскольку вы зацикливаете. Это означает, что первый цикл проходит, вы сдвигаете arg0
вниз на 24 бита, а затем сохраняете его в темпе.
Второй оператор является поразрядным И, который сравнивает каждый бит левой стороны с каждым соответствующим битом правой руки. Если оба бита равны 1, результирующий бит в том же положении равен 1, в противном случае - 0. Вот несколько примеров:
decimal: 7 & 15 == 7
binary: 0b0111 & 0b1111 == 0b0111
decimal: 5 & 12 == 4
binary: 0b0101 & 0b1100 == 0b0100
В ваших выражениях И выполняется с правым боковым значением 0x000000FF
которое является шестнадцатеричным эквивалентом 255, в десятичной форме.
Что делают ваши два заявления, представляющие интерес, извлечения каждого "байта" или "8-битного куска" из входного arg0
:
temp = arg0 >> shift;
temp = temp & 0x000000ff;
Input: arg0 = 0x12345678, shift = 24
Output: temp = 0x12
Input: arg0 = 0x12345678, shift = 0
Output: temp = 0x78
ДОБАВЛЕНИЕ О СЪЕМКЕ ПРАВО:
Вы смещаете целое число со знаком прямо здесь, но, к счастью, вы маскируете бит с помощью следующей маски И. Для полноты смещения сдвиг вправо на знаковое целое может сделать одну из двух вещей (при условии, что здесь 16-битные числа, результаты будут разными для 32-битных или 64-битных чисел):
Арифметический сдвиг вправо:
decimal: -128 >> 1 == -64
binary: 0b1111 1111 1000 0000 >> 1 == 0b1111 1111 1100 0000
Логический сдвиг вправо:
decimal: -128 >> 1 == 32704
binary: 0b1111 1111 1000 0000 >> 1 == 0b0111 1111 1100 0000
Обратите внимание, как арифметический сдвиг вправо "дублирует" верхний бит, где "логический сдвиг вправо" приносит нуль. Это определенная платформа, как это интерпретируется на самом деле, поэтому старайтесь держаться подальше от нее, если это возможно, и придерживайтесь смещения целых чисел без знака.
temp = arg0 >> shift
Это немного смещение. Целочисленное значение arg0
будет смещено вправо по числу shift
бит.
Например, если shift = 8 и arg0 = 0x1234, то temp будет назначен 0x12.
В вашем коде, если arg0 = 0x12345678 со сдвигом = 24, тогда temp становится 0x123456.
temp = temp & 0x000000ff;
Это побитовое and
операция. Шестнадцатеричный номер 0x0000000ff используется для маскировки младшего значащего байта перед его передачей в byteToDec().
Итак, в последнем примере, где arg0 = 0x12345678, temp смещается 24 до = 0x123456, затем замаскировано до 0x00000056.
Что касается MIPS, то для сдвига будет использоваться инструкция Shift Right Logical Variable (SRLV)
SRLV $d, $t, $s
Где $ d - регистр назначения, $ t - регистр источника, а $ s - регистр, содержащий значение числа сдвигов. Стоит понять, что этот сдвиг вводит нули слева и изменит значение целого числа со знаком, которое является отрицательным, но поскольку применяется маска, которая применяет нули для всех, кроме наименее значимого байта, это нормально и сохранит вам некоторые инструкции.
temp = arg0 >> shift
Это делает двоичный сдвиг справа от содержимого arg0
. Он делает это shift
число раз. Так как shift = 24
, он будет смещать arg0
вправо 24 раза.
temp = temp & 0x000000ff;
Это маскирует наиболее важные байты того, что содержится в temp
. Последний байт остается, так как все, &
"й изда с f
только отражает исходное значение.
В этой строке
temp = arg0 >> shift;
значение arg0 смещается от большинства значащих бит к самому низкому (будьте осторожны, это может быть слева направо или справа налево зависит от сущности ЦП) в значении сдвигов (первый раз 24, затем 16, затем 8)
temp = temp & 0x000000ff;
Двоичный И применяется к темпам, т.е. Все, кроме менее значительных 8 бит, сбрасываются до 0, менее значимые 8 бит не изменяются. Если вам нужно реализовать это в сборке, вам может не понадобиться делать двоичный файл AND, но вместо этого получить правильный байт.