author: kx <kx@radix-linux.su> 2024-12-29 12:21:01 +0300
committer: kx <kx@radix-linux.su> 2024-12-29 12:21:01 +0300
commit: 3c780c88a0a0e98f7bb1ceaf7843c4560d2e0ce4
parent: 31f615c1e5a07398bdd68c74b81fbe64c45f169a
Commit Summary:
Diffstat:
1 file changed, 153 insertions, 0 deletions
diff --git a/man/ru/shifts.3mpu b/man/ru/shifts.3mpu
new file mode 100644
index 0000000..3252b01
--- /dev/null
+++ b/man/ru/shifts.3mpu
@@ -0,0 +1,165 @@
+.\" Copyright 2024 Andrew V.Kosteltsev (kx@radix-linux.su)
+.\"
+.\"
+.TH shifts 3 "December 27, 2024" "libmpu" "LibMPU Programmer's Manual"
+.SH NAME
+\fBishl\fP, \fBishr\fP, \fBisal\fP, \fBisar\fP \- операции сдвига на один бит
+.SH SYNOPSIS
+.nf
+.B #include <libmpu.h>
+.PP
+.BI "void ishl( mpu_int *" c ", mpu_int *" a ", int " nb " );
+.BI "void ishr( mpu_int *" c ", mpu_int *" a ", int " nb " );
+.BI "void isal( mpu_int *" c ", mpu_int *" a ", int " nb " );
+.BI "void isar( mpu_int *" c ", mpu_int *" a ", int " nb " );
+.fi
+.SH DESCRIPTION
+Для операций сдвигов на один бит входным операндом служит переменная размером \fBnb\fP байт,
+находящаяся по адресу \fBa\fP, результат помещается в переменную того же размера,
+расположенную по адресу \fBc\fP. Пространства, занимаемые входной и выходной переменной
+в памяти могут пересекаться, как частично, так и полностью, что не влияет на правильность
+получаемого результата. Содержимое переменной, расположенной по адресу \fBa\fP останется
+неизменным, после выполнения операции, если занимаемое ей пространство не пересекается
+с пространством, занимаемым переменной \fBc\fP.
+.PP
+При выполнениии операций сдвига, флаг переноса \fBC\fP всегда содержит значение последнего
+выдвинутого бита. Существуют следующие виды операций сдвига:
+.PP
+
+.RS 3
+ SHL \- логический беззнаковый сдвиг влево на один бит.
+.RE
+.RS 3
+ SHR \- логический беззнаковый сдвиг вправо на один бит.
+.RE
+.RS 3
+ SAL \- арифметический сдвиг влево на один бит.
+.RE
+.RS 3
+ SAR \- арифметический сдвиг вправо на один бит.
+.RE
+
+.PP
+Следующие таблицы иллюстрируют выполнение операций \fBishl\fP, \fBishr\fP.
+.nf
+.sp
+ ┌────────────────┬───┬───────────────────┬────────────┐
+ │ SHL(<<): │ C │ значение операнда │ заполнение │
+ ├────────────────┼───┼───────────────────┼────────────┤
+ │ до операции │ │ 10110111 │ 0 │
+ ├────────────────┼───┼───────────────────┼────────────┤
+ │ после операции │ 1 │ 01101110 │ │
+ └────────────────┴───┴───────────────────┴────────────┘
+
+ ┌────────────────┬────────────┬───────────────────┬───┐
+ │ SHR(>>): │ заполнение │ значение операнда │ C │
+ ├────────────────┼────────────┼───────────────────┼───┤
+ │ до операции │ 0 │ 10110111 │ │
+ ├────────────────┼────────────┼───────────────────┼───┤
+ │ после операции │ │ 01011011 │ 1 │
+ └────────────────┴────────────┴───────────────────┴───┘
+.fi
+.sp
+Из таблиц видно, что при любом логическом сдвиге на освободившееся место всегда задвигается 0.
+Флаг переполнения \fBO\fP выставляется, если в результате операции операнд изменил знак.
+.PP
+Операция арифметического сдвига влево \fBisal\fP действует аналогично операции \fBishl\fP
+(также на пустое место справа задвигается 0). Операция арифметического сдвига вправо действует
+иначе: в освобождающуюся позицию слева копируется знаковый бит исходного операнда.
+Действие операций \fBisal\fP и \fBisar\fP показано с помощью следующих таблиц.
+.nf
+.sp
+ ┌────────────────┬───┬───────────────────┬────────────┐
+ │ SAL(<<): │ C │ значение операнда │ заполнение │
+ ├────────────────┼───┼───────────────────┼────────────┤
+ │ до операции │ │ 10110111 │ 0 │
+ ├────────────────┼───┼───────────────────┼────────────┤
+ │ после операции │ 1 │ 01101110 │ │
+ └────────────────┴───┴───────────────────┴────────────┘
+
+ ┌────────────────┬────────────┬───────────────────┬───┐
+ │ SAR(>>): │ заполнение │ значение операнда │ C │
+ ├────────────────┼────────────┼───────────────────┼───┤
+ │ до операции │ sign(1) │ 10110111 │ │
+ ├────────────────┼────────────┼───────────────────┼───┤
+ │ после операции │ │ 11011011 │ 1 │
+ └────────────────┴────────────┴───────────────────┴───┘
+.fi
+.sp
+Флаг переполнения при выполнении операции \fBisal\fP выставляется таким же образом, как
+и при операции \fBishl\fP. При выполнении операции \fBisar\fP, операнд не может изменить
+свой знак. Многократный сдвиг \fBisar\fP может, в конце концов, привести к потере значения,
+и положительное число задвинется в 0, а отрицательное в -1. По этому флаг переполнения \fBO\fP
+для операции \fBisar\fP сбрасывается в 0.
+.PP
+При выполнении операций \fBisal\fP, \fBisar\fP, \fBishl\fP, \fBishr\fP, так же выставляются
+флаги четности \fBP\fP, знака \fBS\fP и нуля \fBZ\fP. Флаг переноса из младшей тетрады \fBA\fP
+не определяется и просто сбрасывается в 0.
+.PP
+Сдвиг влево можно применять для удваивания чисел, а сдвиг вправо \- для деления на 2. Эти операции
+выполняются значительно быстрее, чем операции умножения и деления. Деление пополам нечетных чисел
+(например, 5 или 7) образует меньшие значения (2 или 3, соответственно) и устанавливает флаг
+переноса \fBC\fP в 1. При этом \fBC\fP, фактически, содержит остаток от деления. Такое использование
+операций сдвига требует контроля за флагом переполнения \fBO\fP. Для простоты, рассмотрим контроль
+флагов на 4\-битных знаковых переменных:
+.SS Примеры с 4\-битными операндами:
+\fBУмножение на 2\fP:
+.nf
+SAL(0111) = 7; результат = 1110 = -2, ошибка, должно быть 14, CF = 0, OF = 1
+.fi
+.sp
+\fBДеление на 2\fP:
+.nf
+SHR(1000) = -8; результат = 0100 = 4, ошибка, должно быть -4, CF = 0, OF = 1
+.fi
+.sp
+\fBДеление на 2\fP:
+.nf
+SAR(1000) = -8; результат = 1100 = -4, абсолютно точно, CF = 0, OF = 0
+.fi
+.sp
+\fBДеление на 2\fP:
+.nf
+SAR(0111) = 7; результат = 0011 = 3, остаток 1 (см. флаг C), абсолютно точно, CF = 1, OF = 0
+.fi
+.sp
+.SH EXAMPLES
+.nf
+.sp
+#include <libmpu.h>
+#include <stdio.h>
+
+int main( void )
+{
+ int rc = 0;
+
+ __mpu_init();
+ __mpu_extra_warnings = 1;
+
+ {
+ mpu_int128_t c, a;
+ int nb = NB_I8;
+ __mpu_char8_t sc[32], sa[32];
+
+ iatoi( a, "0b10110111", nb ); /* evaluate the A variable */
+
+ ishl( c, a, nb );
+ iitoa( sa, a, RADIX_BIN, LOWERCASE, nb ); /* convert A value to ASCII string SA */
+ iitoa( sc, c, RADIX_BIN, LOWERCASE, nb ); /* convert C value to ASCII string SC */
+ printf( "a = %s;\n", sa ); /* c = 0b10110111; */
+ printf( "c = %s;\n", sc ); /* c = 0b01101110; */
+ printf( "carry = %d;\n", __mpu_gtc() ); /* Carry Flag */
+ printf( "overflow = %d;\n", __mpu_gto() ); /* Overflow Flag */
+ }
+
+ __mpu_free_context();
+
+ return( rc );
+}
+.fi
+.SH SEE ALSO
+.BR iadd(3),
+.BR iadc(3),
+.BR isub(3),
+.BR isbb(3).
+