Да, в asm есть операции, которые работают с данными в разных форматах, и вы можете вызывать эти типы.Но есть ноль типа безопасность .Это хороший способ выразить это.
, поэтому инструкция INC «знает», что должна интерпретировать биты, которыми она манипулирует, как целое число.
Но этонеуклюжий способ выразить это. INC ничего не «знает» ;он просто передает операнд в двоичный сумматор в ALU. Это полностью зависит от программиста (или компилятора), чтобы использовать правильные инструкции в правильном порядке в правильных байтах, чтобы получить желаемый результат. Например, реализовать переменные высокого уровня с типами.
Каждая инструкция asm делает то, что говорит на банке, не больше, не меньше.Раздел «Операция» в записи справочного руководства по набору инструкций описывает полное влияние, которое он оказывает на архитектурное состояние машины, включая флаги и возможные исключения.например, inc
.Или более сложная инструкция с более интересным псевдокодом, который показывает, куда вносится каждый бит, BMI2 pdep r32a, r32b, r/m32
(и диаграммы).PDF-файл Intel, из которого они извлечены, содержит вступительный раздел, в котором объясняются любые обозначения, такие как CF ← Bit(BitBase, BitOffset);
для bts
(бит-тест и установка)
Всеэто всего лишь байты (включая указатели и числа с плавающей запятой, целые числа, строки и даже код в архитектуре фон Неймана, такой как x86).(Или на машинах с некоторыми вещами, которые не кратны 1 байту, все просто биты.)
Ничто не может волшебным образом масштабировать индексы по ширине шрифта для вас.(Хотя AVX512 использует масштабированный disp8
в режимах адресации, поэтому 8-битное смещение может кодировать до -128 .. + 127 раз векторной ширины, а не столько байтов. В сборке на уровне источника вы все равно пишетесмещения байтов, и ассемблер может использовать, когда это возможно, более компактную кодировку машинного кода.)
Если вы хотите использовать inc al
в младшем байте указателя для циклического перебора первых 256 байтов(выровненный) массив, это совершенно нормально.(И эффективно на процессорах, отличных от семейства P6, где вы получите остановку частичного регистра при чтении полного регистра.)
В некоторой степени верно, что x86 имеет встроенную поддержку многих типов.Большинство целочисленных инструкций содержат байты, слова, слова и qword размер операнда .И, конечно же, есть инструкции FP (float
/ double
/ long double
), и даже в основном устаревшие данные BCD.
Если вы заботитесь о переполнении со знаком и без знака, вы смотрите на OFили CF соответственно.(Таким образом, целое число со знаком и без знака зависит от того, какие флаги вы смотрите после факта для большинства инструкций, потому что add / sub - это та же самая двоичная операция для unsigned и дополнения до 2).
Но умножение расширяется,делите, приходите в подписанной и неподписанной версиях.Один операнд imul
против mul
(и BMI2 mulx
) выполняет умножение со знаком или без знака N x N => 2N-битное умножение.(Но часто вам не нужен результат с высокой половиной и вы можете просто использовать более эффективный imul r32, r/m32
(или другой размер операнда). Низкая половина умножения - это тот же двоичный операнд для интерпретации входных данных со знаком или без знака; только старшая половина отличается в зависимости от того, имеет ли MSB входов положительное или отрицательное значение-место.)
Не всегда хорошая идея использовать тот же размер операнда, что и тип данных C ++вы реализуете.например, 8-битный и 16-битный часто могут быть вычислены с 32-битным размером операнда, избегая проблем с частичным регистром.Для add / sub перенос переносится только из LSB в MSB, поэтому вы можете выполнять 32-битные операции и использовать только младшие 8 битов результата.(Если вам не нужно сдвиг вправо или что-то в этом роде.) И, конечно, размер 8-битного операнда для cmp
может оказаться полезным, но это не запись каких-либо 8-битных регистров.
x86 типы / форматы данных включают в себя гораздо больше, чем просто целое число
- двоичное целое число со знаком 2 и двоичное целое число без знака
- IEEE
float
и double
, с операндами памяти SSE и SSE2 и x87. - 16-разрядный float с половинной точностью (
vcvtph2ps
и наоборот):загружать / хранить только.Некоторые процессоры Intel имеют половинную точность multi / add в GPU , но ядра x86 IA могут конвертировать только для экономии пропускной способности памяти и использовать по крайней мере float
для векторных математических инструкций FP. - 80-битная расширенная точность с x87
- 80-битный BCD с x87
fbstp
- упакованный и неупакованный BCD, поддерживаемый флагом AF (nibble-carry) и такие инструкции, как DAA (десятичное значение упакованного BCD, AL после добавления) и AAA (ASCII, корректирующее после добавления: для неупакованного BCD в AL, AH).не в 64-битном режиме
- битовые карты с
bt
/ bts
/ etc: bts [rdi], eax
может выбрать бит вне dword на rdi
.В отличие от назначения регистра, битовый индекс не маскируется с помощью &0x1f
(https://www.felixcloutier.com/x86/bt). (вот почему bt/bts/etc mem,reg
так много мопов, тогда как reg, reg и mem, немедленныенеплохо).
См. также Как читать нотацию Intel Opcode для получения списка всех нотаций, используемых в справочном руководстве по набору команд Intel. Например, r /m8 - это 8-битный регистр целых чисел или ячейка памяти. imm8 - это 8-битное значение (обычно расширяется до размера операнда, если он больше 8).
В руководстве используются m32fp для операндов памяти FP x87, против m32int для x87 fild
/ fistp
(целочисленная загрузка / сохранение) и других инструкций x87 с целочисленным источникомкак fiadd
.
Также такие вещи, как m16: 64 , дальний указатель в памяти (сегмент: смещение), например, в качестве операнда для косвенного дальнего jmp
или дальний call
. Конечно, было бы разумно сосчитать дальние указатели и "тип", который поддерживает x86. Есть инструкциикак lgs rdi, [rsi]
, который загружает gs:rdi
из операнда 2 + 8 байтов, на который указывает rsi
.(Конечно, чаще используется в 16-битном коде.)
m128 / xmm может быть не тем, что вы на самом деле называете «типом данных», хотя;никакие инструкции SIMD фактически не рассматривают операнд как 128-битное или 512-битное целое число.64-битные элементы являются самыми большими для всего, кроме случайных чисел.(Или чисто побитовые операции, но на самом деле это 128 отдельных операций И параллельно, никакого взаимодействия между соседними битами вообще нет.)