deXo-fan Ответов: 3

Есть ли 96-битный тип данных в C++, например .Системы сети.десятичное?


Привет,

Ну, название этого вопроса, возможно, само собой разумеется, но в то же время я уже знаю, что ответ на этот вопрос - "нет". Поэтому позвольте мне немного развить свой вопрос и цель.

Несколько лет назад в C++ был 12-байтовый целочисленный тип, по крайней мере, в компиляторе Microsoft. Но даже тогда это не имело смысла, потому что, как вы знаете, C++ преобразуется в ассемблерный код, и два самых больших целочисленных типа в ассемблере, насколько мне известно, это TBYTE и REAL10-оба размером 10 байт, причем REAL10-тип с плавающей запятой, а TBYTE-целочисленный тип. Итак, мой первый вопрос: поскольку 12-байтовый тип, о котором я упоминал ранее, является/был внутренним, неструктурированным типом, как он может поддерживаться в сборке? Что делать, если вы назначили значение настолько большое, что для него потребуется больше, чем 10 байт, предоставленных, скажем, TBYTE?

Мой второй вопрос включает в себя .NET. У нас есть 12-байтовая система.Десятичный тип, и все указывает на то, что он также является внутренним. Если вы посмотрите на IL-код, сгенерированный при компиляции вашей программы, вы можете увидеть, что это также не структура, библиотека или что-то еще, кроме типа, который, как представляется, непосредственно поддерживается MSIL и который прекрасно обрабатывается вашим компьютером, занимая не больше оперативной памяти, чем эти 12 байт.

Как это возможно, если сборка не предоставляет тип такого размера или функцию для обработки значений такого размера? Я прекрасно знаю, что .NET-программы компилируются в другой набор двоичных инструкций, чем неуправляемые программы C++, но вы все равно можете использовать такую программу, как MASM32, для разборки .NET-программ-и это имеет для меня идеальный смысл, поскольку .Чистые двоичные файлы по-прежнему состоят из самых простых инструкций, которые процессор должен уметь распознавать.

Итак, подводя итог тому, что стало более длинным вопросом, чем я намеревался:
1) Как я могу написать программу в сборке, которая может обрабатывать 12-байтовые значения с внутренними типами?
2) если 1) невозможно, то как это возможно в C# / .NET?

Спасибо.

Что я уже пробовал:

Я попытался найти нужный мне 12-байтовый тип данных в интернете.
Я попытался проанализировать дизассемблированную программу .NET, используя такой тип, но безрезультатно.
Я пытался написать свой собственный код для обработки таких значений, но это не совсем то, что я хочу.

raddevus

Я тоже часто задавался этим вопросом, и это отличный вопрос. Спасибо, что задали его здесь, где есть люди, которые могут предложить некоторые ответы. Действительно большой. Спасибо

deXo-fan

Я ценю твою благодарность, раддевус, и надеюсь, что ты получишь от этих решений столько же, сколько и я, потому что, как ты уже заметил, они дали нам несколько удивительных ответов!

3 Ответов

Рейтинг:
7

Patrice T

Цитата:
Несколько лет назад в C++ был 12-байтовый целочисленный тип, по крайней мере, в компиляторе Microsoft. Но даже тогда это не имело смысла, потому что, как вы знаете, C++ преобразуется в ассемблерный код, и два самых больших целочисленных типа в ассемблере, насколько мне известно, это TBYTE и REAL10-оба размером 10 байт, причем REAL10-тип с плавающей запятой, а TBYTE-целочисленный тип. Итак, мой первый вопрос: поскольку 12-байтовый тип, о котором я упоминал ранее, является/был внутренним, неструктурированным типом, как он может поддерживаться в сборке? Что делать, если вы назначили значение настолько большое, что для него потребуется больше, чем 10 байт, предоставленных, скажем, TBYTE?

На уровне процессора существуют только регистры, и они имеют размер 8, 16, 32 и 64 бита.
Память в основном адресуется словами из 8 бит (байт), на современном оборудовании к памяти обычно обращаются много 64 бит (8 байт) для повышения эффективности из-за аппаратного дизайна.
Таким образом, 12 - байтовое целое число происходит из эпохи 32-битного (4 байта) аппаратного обеспечения и составляет 3 слова по 4 байта.
Процессор имеет функции для обработки данных большего размера, чем регистры. Подробности об этом не будут вписываться в рамки этого текстового поля.
Работа с большими числами с помощью инструкций x86[^]


deXo-fan

Я определенно смотрю на страницу, на которую вы ссылаетесь, у меня есть чувство, что я собираюсь многому научиться!
Моя память (не моя оперативная память :P) может быть отключена, но я почти уверен, что однажды (когда long double был размером 12 байт) разобрал программу C++ с таким типом, и я обнаружил, что соответствующий ассемблерный код присвоил ей REAL10. Это было очень давно, но я почти уверен, что правильно помню и правильно читаю ассемблерный код, потому что помню, что думал, что это не имеет большого смысла.

Рейтинг:
20

OriginalGriff

Да, это можно сделать: просто потому, что что - то не поддерживается непосредственно процессором, это не значит, что вы не можете использовать его в ассемблере - подумайте о значении BigInt, где каждая десятичная цифра хранится в кусочке - так что две цифры помещаются в байт - и произвольное их количество может быть объединено в блок памяти, чтобы сформировать произвольно большое число, с которым вы все еще можете делать математику-при условии, что вы пишете операторы+, -, * / ^ и % в ассемблере для их обработки!

Десятичные числа в C# одинаковы: Десятичная Структура (Система) | Microsoft Docs[^] - они не соответствуют ни одному типу данных "процессор осведомлен", так что .NET framework содержит код, реализующий математические операции над ними.

Вам придется использовать (краткую и серьезно отсутствующую в деталях) информацию в ссылке, чтобы написать ассемблерные функции, которые обрабатывают десятичные значения, а затем принимают и возвращают 12-байтовые указатели значений (вероятно) для связи с .NET.

Я никогда не видел, как это делается, так что это может быть интересный проект для вас!

[редактировать]
Взгляните на это .NET reference source и вы увидите как это делает Microsoft: опорный источник[^]
[/редактировать]


raddevus

Действительно отличный и интересный ответ. Спасибо

deXo-fan

Фантастический ответ!
На самом деле когда-то я написал небольшую и очень простую библиотеку с алгоритмом, который был способен разделить любые два числа с плавающей запятой неограниченных размеров, но мой алгоритм был невероятно медленным, и я, возможно, не делал этого от всего сердца, так как меня беспокоило, что мои значения должны были быть заключены в кавычки (например, BigFloat bf = "123.456";), но я думаю, что ничего не поделаешь. Нет, если я хочу использовать числа, превышающие самое длинное (символьное) двойное значение.

Но со ссылкой, которую вы предоставили на справочный источник, я мог бы просто дать ему еще один шанс и приложить больше усилий на этот раз, потому что, как вы сказали, это может быть очень интересный проект для меня! И кстати, огромное спасибо за эту ссылку, я даже не подозревал, что она существует. Я всегда думал, что Microsoft очень тихо относится к своему коду.:D

OriginalGriff

Всегда пожалуйста!
MS выпустила весь исходный код для .NET еще в 2012 году IIRC в качестве справочных источников - и это удобный материал!
Кстати: в .NET также есть класс BigInteger:
https://docs.microsoft.com/en-us/dotnet/api/system.numerics.biginteger?view=netcore-3.1
Может быть, стоит взглянуть и на это тоже:
https://referencesource.microsoft.com/#System.Числа/Системы/Числа/Типа BigInteger.в CS

Рейтинг:
12

KarstenK

Существует поддержка в некоторых библиотеках C++, таких как Повышать для этого.

Некоторые компиляторы не обрабатывают точные размеры типов данных, но используют выравнивание Преимущество заключается в том, что используются полные байты, и поэтому скорость обработки лучше, потому что не требуется никаких усилий для однобитового доступа. Если вы можете использовать его, проверьте, не медленнее ли он, чем неоптимизированный код.


deXo-fan

Я попробую сначала собрать что-нибудь сам, но на самом деле я уже слышал о Boost раньше. Люди очень высоко отзываются о нем, если я не ошибаюсь.

Мне нравится то, что вы сказали об использовании выравнивания; это то, что я буду иметь в виду, если и когда я начну.