|
|||||||
|
Быстрое вычисление адреса пикселя через сдвиг и сложение вместо умножения. Зачем нужны готовые машинные инструкции сдвиг+сложение?
Время создания: 24.02.2026 10:44
Автор: xintrea
Текстовые метки: экран, дисплей, размер, разрешение, пиксель, точка, адрес, умножение, сложение, сдвиг, компьютерная, графика, координата
Раздел: Компьютер - Аппаратное обеспечение - Микроконтроллеры ARM
Запись: xintrea/mytetra_syncro/master/base/1771919059phceaj6rf5/text.html на raw.githubusercontent.com
|
|||||||
|
|
|||||||
|
Во многих процессорных архитектурах в процессе их развития, вместо отдельных команд сдвига и сложения появились "объединенные" команды, которые за один такт делают операцию "сложение со сдвигом". Например, в ARM есть одна из форм мнемотики ADD, в которой есть 4 операнда: ADD R0, R1, R2, LSL #2 ; это R0 = R1+ (R2 << 2) где:
Зачем такие странные машинные команды "сложение со сдвигом" вообще нужны? Эта команда может пригодиться, например, для быстрого вычисления адреса пикселя на стандартных размерах экранов через два-три сдвига и пару сложений. Если в процессоре существуют операции "сложение со сдвигом", то можно уместиться в две-три машинные команды, причем не используя умножение. Так как команды "сложения со сдвигом" во всех современных (и даже древних) процессорах обычно исполняются за один такт, то таким образом за 2 такта можно высчитать адрес точки по ее координатам, даже если в процессоре нет блока умножения. К примеру, регистр R1 содержит координату X, R2 - координату Y. Если один пиксель занимает 1 байт (например, это 256 цветов на пиксель), то чтобы получить адрес пикселя, надо Y умножить на ширину экрана (получится адрес начала линии с номером Y), и прибавить X. Стандартные ширины экранов устроены таким образом, что умножать на ширину можно просто одним-тремя сдвигами. Что имеется в виду? Вот какие ширины бывают: 320 pix (это 256 + 64) 640 pix (это 512 + 128) 800 pix (это 512 + 256 + 32) 1024 pix (это 1024) 1280 pix (это 1024 + 256) и т.д. Если ширина экрана, к примеру, 1280 точек, то чтобы получить адрес начала линии с номером Y не используя умножение, надо сделать два сдвига Y и одно сложение. Вот как из умножения получается формула со сдвигами и сложением: Адрес начала линии = Y * 1280 = Y * (1024 + 256) = Y * 1024 + Y * 256 = Y * 2^10 + Y * 2^8 = (Y << 10) + (Y << 8) А чтобы получить адрес пикселя надо еще прибавить X. Тогда получится формула: Адрес пикселя = (Y << 10) + (Y << 8) + X Эти вычисления на ARM укладываются в две команды: ADD R3, R2, R1, LSL #8 ; R3 = (Y << 8) + X ADD R0, R3, R1, LSL #10 ; R0 = (Y << 10) + R3 В результате в R0 лежит адрес пикселя. Если используется 2 байта на пиксель (64 тысячи цветов, High Color, 16 bit), то результат еще умножается на два, путем еще одного сдвига на один бит влево. Пытаться работать с "виртуальным" экраном шириной 2560 точек вместо 1280, в надежде не делать дополнительный сдвиг, не имеет смысла: все равно дополнительный сдвиг придется делать, так как при вычислении адреса в строке, прибавлять надо будет не X, а X*2. Режим 3 байта на пиксель (16М цветов, стандарт TrueColor, 24 bit) раньше считался самым медленным, когда еще не было команд "сложения со сдвигом", так как для его реализации требуется умножение на 3. А это дополнительно один сдвиг на один бит и одно сложение с самим собой. Но в современных процессорах эти две операции, как было сказано выше, выполняются вместе за один такт, так что работа с ним по производительности не отличается от режима 2 байта на пиксель. То же самое можно сказать и о режиме 4 байт на пиксель (32 bit) - ему нужно одно дополнительное умножение на 4, что эквивалентно одному сдвигу на 2 бита влево. |
|||||||
|
Так же в этом разделе:
|
|||||||
|
|||||||
|
|||||||
|