РБМК и движок OpenGL на MASM

Тема в разделе "WASM.OpenGL", создана пользователем ml64, 25 апр 2026.

  1. ml64

    ml64 Active Member

    Публикаций:
    0
    Регистрация:
    29 окт 2017
    Сообщения:
    119
    1. Пересадил на последнюю редакцию движка.
    2. Заменил x87 на SSE, так понятнее и человеку, и машине (оставил только fsincos).
    3. Развернул полигоны, чтобы не мерцали.
    4. Добавил свет
    5. Выставил камеру

    Мышкой всё двигается, как в CAD-системах:
    • с зажатой левой кнопкой - поворот камеры,
    • с зажатой правой кнопкой - поворот объекта,
    • с зажатым колесом - перенос камеры,
    • прокрутка колеса - наезд камеры,
    • двойной щелчок колесом - исходное положение
    С клавиатуры:
    • стрелки, PagUp, PageDown - движение камеры,
    • WSADQE - движение объекта (разница заметна при поворотах после смещения, см. координаты на статус-баре),
    • пробели первое нажатие Esc - сброс в исходное положение,
    • второе нажатие Esc - выход,
    • F1, Ctrl+W - акселераторы.

    Под Windows 11 (Core i3, NVIDIA 1650) всё нормально

    Voxel_01c.jpg

    ATI Rage Mobility-M1 под Windows Me гонит пургу со скоростью 37 FPS:

    Voxel_01c_old.jpg
    --- Сообщение объединено, 28 сен 2026 ---
    Вот такой движок на MASM 32.
    А парсера как не было, так и нет
     

    Вложения:

    • Voxel_01с.zip
      Размер файла:
      40 КБ
      Просмотров:
      49
    Последнее редактирование: 28 сен 2026
    MaKsIm и GRAFik нравится это.
  2. GRAFik

    GRAFik Active Member

    Публикаций:
    0
    Регистрация:
    14 мар 2020
    Сообщения:
    563
    На моём музейном экспонате процессора и Windows 10 Pro x64 - всё ок ! Скорость 325 FPS и действительно стало красивее и лучше ( подсветка и т.п. ). Вот что значит - профессиональный подход к делу!

    Вопрос с управлением поворота вокруг оси снимается - разобрался. Просто стало чуть по-другому - нужно правую кнопку мыши удерживать. Так что - всё ок! :)
     
    Последнее редактирование: 28 сен 2026
    ml64 нравится это.
  3. ml64

    ml64 Active Member

    Публикаций:
    0
    Регистрация:
    29 окт 2017
    Сообщения:
    119
    Я пересветил, на самом деле.
    У света три компонента: рассеянное, диффузное и бликовое.
    Я сделал рассеянное и диффузное слишком ярким, а бликовое не делал.
    Сейчас исправил. Стало равномернее.
    Но почему ATI Rage Mobility-M1 ломает полигоны - не знаю. Надо разбираться.
    --- Сообщение объединено, 28 сен 2026 ---
    Так и не нашёл, в чём проблема у ATI Rage Mobility-M1.
    Но зато попутно сделал много улучшений, например единый источник света с тремя компонентами, а не три по одному в одном месте.
    И обогатил лог:
    --- Сообщение объединено, 28 сен 2026 ---
    Она у меня работает под Windows Me на драйвере версии 1.1.0, написанном под Windows 95. Ну хоть не бета.
     

    Вложения:

    • voxel01d.zip
      Размер файла:
      191,1 КБ
      Просмотров:
      55
    • Voxel32_01h.zip
      Размер файла:
      40,2 КБ
      Просмотров:
      51
    MaKsIm и GRAFik нравится это.
  4. GRAFik

    GRAFik Active Member

    Публикаций:
    0
    Регистрация:
    14 мар 2020
    Сообщения:
    563
    А мой самый первый файл то же самое или работает ?
    --- Сообщение объединено, 28 сен 2026 ---
    Казалось бы, куда ещё лучше, но последний вариант действительно, самый лучший. Правда FPS чуть просел с 325 на 290, ну это по-моему, ерунда ( в смысле, не критично :) ).
     
  5. ml64

    ml64 Active Member

    Публикаций:
    0
    Регистрация:
    29 окт 2017
    Сообщения:
    119
    Да, то же самое.
    ATI Rage Mobility-M1 у меня почему-то не пересекает плоскости. Почему - не пойму. Всё перепроверил.
    Вот самый простой пример - пересечение куба и пола:
    ErrorCube.jpg
    Буфер глубины даже не скрывает оси внутри куба.
    --- Сообщение объединено, 28 сен 2026 ---
    Разобрался. Надо было сделать так:
    Код (ASM):
    1. ;gluPerspective Arguments
    2. fovy real8 45.0
    3. zNear real8 100.0 ;Было 1.0
    4. zFar real8 100000.0 ;Было 1000000.0
    Я закладывал универсальные значения (от миллиметра до километра)
    На старой видеокарте z-буфер не справлялся. А сейчас мой старичок выдаёт вот такую красоту!
    GRAFik, спасибо за алгоритм!

    VoxelCompaq.jpg
     
    MaKsIm и GRAFik нравится это.
  6. ml64

    ml64 Active Member

    Публикаций:
    0
    Регистрация:
    29 окт 2017
    Сообщения:
    119
    Движок под х32 готов!
    Вот они, возможности ассемблера - исполняемый файл размером 17 килобайт:
    • Регистрация класса окна и цикл сообщений
    • Меню с акселераторами
    • Полная инициализация OpenGL-контекста с выбором пиксельного формата
    • Алгоритмическая сборка геометрии по заданной таблице элементов
    • Конвейерная отрисовка массивов glDrawArrays
    • 3D-навигация с помощью клавиатуры и мыши
    • SSE-процедуры умножения и поворота матриц камеры и объекта
    • Динамически обновляемый статус-бар из шести частей
    • Конвертер из IEEE-754 в десятичное ACSII-представление
    • Счётчик тактов и FPS
    • Логгер с форматированием десятичных чисел
    • Диалоги About и Close, разбор кодов ошибок
    • Свобода от CRT и сторонних библиотек.
    И всё это запускается на процессоре Intel 2000 года:
    CompaqRBMK.jpg

    Движок MASM32 - это не порт ранее опубликованного 64-битного движка.
    Это самостоятельная программа - кстати, более грамотно построенная, т.к.:
    • использует раздельные матрицы проекции, камеры и объекта,
    • рисует массивами с помощью конвейера glDrawArrays, а не отдельными вызовами glBegin/glEnd
     

    Вложения:

    • RBMK32_083.zip
      Размер файла:
      42,1 КБ
      Просмотров:
      51
    Последнее редактирование: 29 сен 2026
    MaKsIm и GRAFik нравится это.
  7. GRAFik

    GRAFik Active Member

    Публикаций:
    0
    Регистрация:
    14 мар 2020
    Сообщения:
    563
    ml64, так теперь нужно сделать такую же грамотно построенную 64-х битную версию, с учётом всех спецификаций win. 64 ABI и т.д. и т.п. Если, конечно, у вас найдётся время для этого. Я бы даже мог тоже в этом поучавствовать, если бы у вас, допустим, была бы проблема со временем, для выяснения каких-нибудь деталей и тонкостей, связаных с той же 64-х битной спецификацией.
     
  8. ml64

    ml64 Active Member

    Публикаций:
    0
    Регистрация:
    29 окт 2017
    Сообщения:
    119
    Да, и я её уже делаю.
    Вы тоже можете параллельно механически перевести Вашу анимированную программу с х32 на х64.

    Это совсем не рутина, а по-настоящему творческая работа. Там много интересного, например:
    а) использование новых инструкций, например, haddps, которой очень не хватало в SSE1,
    б) использование неразрушающих инструкций, которые экономят регистры,
    в) переупаковка из xmm-регистров в ymm-регистры,
    г) замена локальных переменных на регистры, т.к. их в 2 раза больше на х64 -
    следовательно, мы меньше обращаемся к памяти, а это критически важно в циклах и при пересчёте матриц.

    Что касается меня, то мне интересна история OpenGL (что я делаю сейчас):
    ОС​
    32​
    64​
    OpenGL​
    1.0​
    4.0​
    Конвейер​
    glDrawArrays​
    VBO​
    Доступ​
    API, display lists​
    Шейдеры​
    Т.е. я готовлю движок OpenGL-64 к восприятию шейдеров, чтобы туда можно было загрузить "Москвич" и вообще всё, что угодно, в формате .obj.

    --- Сообщение объединено, 29 сен 2026 ---

    К вопросу о display lists


    Не знаю, как перевести - дословно: "списки отображения", по сути - прекомпилированные функции, т.е. своеобразный кэш
    В дисплей-листах можно прекомпилировать непосредственные обращения glBegin/glEnd, но использование их с glDrawArrays запрещено спецификацией, т.е. это не наш случай.
    С методических целях я запёк установки света в дисплей-лист, но ощутимого прироста FPS это не дало.

    Код (ASM):
    1. BuildLightingDisplayList proc
    2.  
    3. push 4864h ;GL_COMPILE
    4. push LIST_LIGHTING
    5. call glNewList
    6.  
    7. ;2.1. Setup Lighting
    8. invoke glEnable,0B50h ;GL_LIGHTING
    9.  
    10. invoke glEnable,4000h ;GL_LIGHT0
    11.  
    12. push offset lightAmbient
    13. push 1200h ;GL_AMBIENT
    14. push 4000h ;GL_LIGHT0
    15. call glLightfv
    16.  
    17. push offset lightDiffuse
    18. push 1201h ;GL_DIFFUSE
    19. push 4000h ;GL_LIGHT0
    20. call glLightfv
    21.  
    22. push offset lightSpecular
    23. push 1202h ;GL_SPECULAR
    24. push 4000h ;GL_LIGHT0
    25. call glLightfv
    26.  
    27. ;2.2. Set Materials to Lighting
    28. push 1602h ;GL_AMBIENT_AND_DIFFUSE
    29. push 408h ;GL_FRONT_AND_BACK
    30. call glColorMaterial
    31.  
    32. push 0B57h ;GL_COLOR_MATERIAL
    33. call glEnable
    34.  
    35. push offset lightSpecular
    36. push 1202h ;GL_SPECULAR
    37. push 0408h ;GL_FRONT_AND_BACK
    38. call glMaterialfv
    39.  
    40. push 3f000000h ;0.5
    41. push 1601h ;GL_SHININESS
    42. push 0408h ;GL_FRONT_AND_BACK
    43. call glMaterialf
    44.  
    45. call glEndList
    46. ret
    47.  
    48. BuildLightingDisplayList endp

    Код (ASM):
    1. ;Compute Projection, Camera and Object Matrices
    2. call GetDefaults
    3.  
    4. ;Pre-compile the Display List:
    5. ;3.1. Setup Lighting
    6. ;3.2. Set Materials to Lighting
    7. call BuildLightingDisplayList
    8.  
    9. ;Apply Defaults
    10. call ResetScene

    Сборка во вложении.
     

    Вложения:

    • rbmk32_084.zip
      Размер файла:
      42,6 КБ
      Просмотров:
      52
    Последнее редактирование: 29 сен 2026
    MaKsIm и GRAFik нравится это.
  9. ml64

    ml64 Active Member

    Публикаций:
    0
    Регистрация:
    29 окт 2017
    Сообщения:
    119
    В процессе перевода с х32 на х64 понаходил ошибок.
    Из-за ошибки переполнения полностью переписал конвертер float-ANSI.
    Теперь х87 (80-битный fbstp) не используется. Только АЛУ, только хардкор.
    Всё как в ламповых учебниках: IEEE-754, знак, характеристика, мантисса.
    Теперь нули, бесконечности и нечисла обрабатываются отдельно. Ибо нефиг.
     

    Вложения:

    • RBMK32_090.zip
      Размер файла:
      43,5 КБ
      Просмотров:
      35
    • Voxel32_04.zip
      Размер файла:
      41,1 КБ
      Просмотров:
      33
    Последнее редактирование: 2 окт 2026 в 03:39
    MaKsIm и GRAFik нравится это.
  10. ml64

    ml64 Active Member

    Публикаций:
    0
    Регистрация:
    29 окт 2017
    Сообщения:
    119
    Так, 64-битная версия есть, но пока что это не более чем перевод.
    Эта версия использует 64-битные РОН, но не оптимизирована под AVX и рисует с помощью DrawArrays (OpenGL 1.1), а не VBO.

    Что касается 32-битных версий, то там всё намного интереснее.
    Когда я писал x32, я мыслил в парадигме stdcall, поэтому всё передавал через стек.
    Когда я перешёл к x64 и fastcall, то многое переработал и в 32-битных версиях.

    Например, обработчик клавиатуры у меня теперь забирает аргументы прямо из регистров, а не через стек:
    Код (ASM):
    1. ;Up Arrow | World moves Backward | Local +z axis
    2. cmp byte ptr[key+26h],0
    3. je @f
    4. movss xmm0,f32_posOne ;xmm0 = direction (either +1.0 or -1.0)
    5. call CameraWalkMagnitude
    6. mov ecx,2 ;2 is for Local z axis
    7. call CameraMove ;ecx = axis, xmm0 = magnitude
    В общем, 32-битные версии стали чище, проще и быстрее.
     

    Вложения:

    • rbmk64_136.zip
      Размер файла:
      46,2 КБ
      Просмотров:
      17
    • rbmk32_098.zip
      Размер файла:
      44 КБ
      Просмотров:
      19
    • Voxel32_09.zip
      Размер файла:
      43,6 КБ
      Просмотров:
      19
    Последнее редактирование: 4 окт 2026 в 16:07
  11. ml64

    ml64 Active Member

    Публикаций:
    0
    Регистрация:
    29 окт 2017
    Сообщения:
    119
    Свежий подгон.
    Обновил алгоритм пересчёта локальных координат в мировые.
    Теперь используется метод Крамера - тот самый, который проходят в 1 семестре 1 курса: .

    Вот так он выглядит на SSE1 (для процессоров с xmm0..xmm7):
    Код (ASM):
    1. GetGlobalOrigin proc ;ecx = pMtxLocal:DWORD ;edx = pVecGlobal:DWORD
    2.  
    3. ;Fastcall:
    4. ;ecx = pMtxLocal
    5. ;edx = pVecGlobal
    6.  
    7. ;XMM Comment Order: little-endian
    8.  
    9. ;p_local = A * p_world + t
    10. ;p_world = -A(-1) * t
    11.  
    12. ;p0 = det(A0) / det(A)
    13. ;p1 = det(A1) / det(A)
    14. ;p2 = det(A2) / det(A)
    15.  
    16. ;A =
    17. ;[m00 m04 m08]
    18. ;[m01 m05 m09]
    19. ;[m02 m06 m10]
    20. movaps xmm0,oword ptr[ecx+00*4] ;[m03 m02 m01 m00]
    21. movaps xmm1,oword ptr[ecx+04*4] ;[m07 m06 m05 m04]
    22. movaps xmm2,oword ptr[ecx+08*4] ;[m11 m10 m09 m08]
    23.  
    24. ;det(A)
    25. ;= m00*(m05*m10 - m06*m09)
    26. ;- m04*(m01*m10 - m02*m09)
    27. ;+ m08*(m01*m06 - m02*m05)
    28. call Determinant
    29. movss xmm3,xmm0 ;xmm3 = detA
    30.  
    31. ;t = (m12, m13, m14)
    32. movaps xmm5,oword ptr[ecx+12*4] ;[m15 m14 m13 m12]
    33. ;b = -t = (-m12, -m13, -m14)
    34. xorps xmm4,xmm4
    35. subps xmm4,xmm5 ;xmm4 = b
    36.  
    37. ;A0 = A with column 0 replaced by b
    38. ;[b0 m04 m08]
    39. ;[b1 m05 m09]
    40. ;[b2 m06 m10]
    41. movaps xmm0,xmm4 ;[b3 b2 b1 b0]
    42. movaps xmm1,oword ptr[ecx+04*4] ;[m07 m06 m05 m04]
    43. movaps xmm2,oword ptr[ecx+08*4] ;[m11 m10 m09 m08]
    44.  
    45. ;det(A0)
    46. ;= b0 *(m05*m10 - m06*m09)
    47. ;- m04*(b1*m10  - b2*m09)
    48. ;+ m08*(b1*m06  - b2*m05)
    49. call Determinant
    50.  
    51. ;p0 = det(A0) / det(A)
    52. divss xmm0,xmm3 ;xmm0 = detA0 / detA
    53. movss dword ptr[edx+00],xmm0
    54.  
    55. ;A1 = A with column 1 replaced by b
    56. ;[m00 b0 m08]
    57. ;[m01 b1 m09]
    58. ;[m02 b2 m10]
    59. movaps xmm0,oword ptr[ecx+00*4] ;[m03 m02 m01 m00]
    60. movaps xmm1,xmm4 ;[b3 b2 b1 b0]
    61. movaps xmm2,oword ptr[ecx+08*4] ;[m11 m10 m09 m08]
    62.  
    63. ;det(A1)
    64. ;= m00*(b1*m10  - m09*b2)
    65. ;- b0* (m01*m10 - m09*m02)
    66. ;+ m08*(m01*b2  - b1*m02)
    67. call Determinant
    68.  
    69. ;p1 = det(A1) / det(A)
    70. divss xmm0,xmm3 ;xmm0 = detA1 / detA
    71. movss dword ptr[edx+04],xmm0
    72.  
    73. ;A2 = A with column 2 replaced by b
    74. ;[m00 m04 b0]
    75. ;[m01 m05 b1]
    76. ;[m02 m06 b2]
    77. movaps xmm0,oword ptr[ecx+00*4] ;[m03 m02 m01 m00]
    78. movaps xmm1,oword ptr[ecx+04*4] ;[m07 m06 m05 m04]
    79. movaps xmm2,xmm4 ;[b3 b2 b1 b0]
    80.  
    81. ;det(A2)
    82. ;= m00*(m05*b2  - b1*m06)
    83. ;- m04*(m01*b2  - b1*m02)
    84. ;+ b0* (m01*m06 - m05*m02)
    85. call Determinant
    86.  
    87. ;p2 = det(A2) / det(A)
    88. divss xmm0,xmm3 ;xmm0 = detA2 / detA
    89. movss dword ptr[edx+08],xmm0
    90.  
    91. ret
    92. GetGlobalOrigin endp

    Определитель:

    Код (ASM):
    1. Determinant proc
    2.  
    3. ;Fastcall:
    4. ;xmm0 = [a03 a02 a01 a00]
    5. ;xmm1 = [a13 a12 a11 a10]
    6. ;xmm2 = [a23 a22 a21 a20]
    7. ;Preserved
    8. ;xmm3 = [??? ??? ??? detA]
    9. ;xmm4 = [???  b2  b1  b0]
    10. ;Accessible
    11. ;xmm5..xmm7
    12. ;Output:
    13. ;xmm0 = [??? ??? ??? det]
    14.  
    15. ;XMM Comment Order: little-endian
    16.  
    17. ;det
    18. ;= a00*(a11*a22 - a12*a21)
    19. ;+ a01*(a12*a20 - a10*a22)
    20. ;+ a02*(a10*a21 - a11*a20)
    21.  
    22. ;A = [a13, a10, a12, a11]
    23. movaps xmm5,xmm1
    24. shufps xmm5,xmm5,11001001b
    25.  
    26. ;B = [a23, a21, a20, a22]
    27. movaps xmm6,xmm2
    28. shufps xmm6,xmm6,11010010b
    29.  
    30. ;A*B = [a13*a23, a10*a21, a12*a20, a11*a22]
    31. mulps xmm5,xmm6
    32.  
    33. ;C = [a13, a11, a10, a12]
    34. movaps xmm6,xmm1
    35. shufps xmm6,xmm6,11010010b
    36.  
    37. ;D = [a23, a20, a22, a21]
    38. movaps xmm7,xmm2
    39. shufps xmm7,xmm7,11001001b
    40.  
    41. ;C*D = [a13*a23, a11*a20, a10*a22, a12*a21]
    42. mulps xmm6,xmm7
    43.  
    44. ;[0, cz, cy, cx]
    45. subps xmm5,xmm6
    46.  
    47. ;det = dot(col0, cross)
    48.  
    49. ;[0, a02*cz, a01*cy, a00*cx]
    50. mulps xmm0, xmm5
    51.  
    52. ;Horizontal sum of lanes 0..2
    53. movaps xmm6,xmm0
    54. shufps xmm6,xmm6,01001110b ;Rotate Right by 2 Lanes
    55. addps xmm0,xmm6
    56. movaps xmm6,xmm0
    57. shufps xmm6,xmm6,10110001b ;Swap Even and Odd Lanes
    58. addss xmm0,xmm6 ;result in xmm0[0]
    59.  
    60. ret
    61. Determinant endp

    И за это машина награждает: 600 FPS на Intel Iris Xe 2023 года (Gen 11):
    597FPS.jpg 432FPS.jpg
     

    Вложения:

    • Voxel32_10.zip
      Размер файла:
      44,9 КБ
      Просмотров:
      8
    • RBMK32_100.zip
      Размер файла:
      45 КБ
      Просмотров:
      9
    • RBMK64_138.zip
      Размер файла:
      46,7 КБ
      Просмотров:
      9
  12. GRAFik

    GRAFik Active Member

    Публикаций:
    0
    Регистрация:
    14 мар 2020
    Сообщения:
    563
    Аналогично. Как тот Буриданов осёл не могу определиться, что лучше ? :)
     

    Вложения:

  13. ml64

    ml64 Active Member

    Публикаций:
    0
    Регистрация:
    29 окт 2017
    Сообщения:
    119
    Ну чисто субъективно мне нравится тот вариант, где оси вращения взаимно перпендикулярны.
    Но можно угол поворота/радиус/скорость сделать настраиваемыми (клавиши +/-, стрелочки, PgUp/PgDn, колесо мышки).
    А ещё - что мне нравится в компиляторах - выбор набора инструкций по cpuid:
    Код (ASM):
    1. 00007FF6CD492720 | 0FA2                  | cpuid                                        |
    2. 00007FF6CD492722 | 81F1 6E74656C         | xor ecx,6C65746E                             |
    3. 00007FF6CD492728 | 81F2 696E6549         | xor edx,49656E69                             |
    4. 00007FF6CD49272E | 0BD1                  | or edx,ecx                                   |
    5. 00007FF6CD492730 | 8BE8                  | mov ebp,eax                                  |
    6. 00007FF6CD492732 | B8 01000000           | mov eax,1                                    |
    7. 00007FF6CD492737 | 81F3 47656E75         | xor ebx,756E6547                             |
    8. 00007FF6CD49273D | 0BD3                  | or edx,ebx                                   |
    9. 00007FF6CD49273F | 8D48 FF               | lea ecx,qword ptr ds:[rax-1]                 |
    10. 00007FF6CD492742 | 0FA2                  | cpuid                                        |
    11. 00007FF6CD492744 | 8BF9                  | mov edi,ecx                                  |
    12. 00007FF6CD492746 | 75 5E                 | jne 2_voxel64demo.7FF6CD4927A6               |
    13. 00007FF6CD492748 | 25 F03FFF0F           | and eax,FFF3FF0                              |
    14. 00007FF6CD49274D | 48:C705 90690100 0080 | mov qword ptr ds:[7FF6CD4A90E8],8000         |
    15. 00007FF6CD492758 | 48:C705 8D690100 FFFF | mov qword ptr ds:[7FF6CD4A90F0],FFFFFFFFFFFF |
    16. 00007FF6CD492763 | 3D C0060100           | cmp eax,106C0                                |
    17. 00007FF6CD492768 | 74 28                 | je 2_voxel64demo.7FF6CD492792                |
    18. 00007FF6CD49276A | 3D 60060200           | cmp eax,20660                                |
    19. 00007FF6CD49276F | 74 21                 | je 2_voxel64demo.7FF6CD492792                |
    20. 00007FF6CD492771 | 3D 70060200           | cmp eax,20670                                |
    21. 00007FF6CD492776 | 74 1A                 | je 2_voxel64demo.7FF6CD492792                |
    22. 00007FF6CD492778 | 05 B0F9FCFF           | add eax,FFFCF9B0                             |
    23. 00007FF6CD49277D | 83F8 20               | cmp eax,20                                   | 20:' '
    24. 00007FF6CD492780 | 77 24                 | ja 2_voxel64demo.7FF6CD4927A6                |
    25. 00007FF6CD492782 | 48:B9 010001000100000 | mov rcx,100010001                            |
    26. 00007FF6CD49278C | 48:0FA3C1             | bt rcx,rax                                   | rax:EntryPoint
    27. 00007FF6CD492790 | 73 14                 | jae 2_voxel64demo.7FF6CD4927A6               |
    28. 00007FF6CD492792 | 44:8B05 9F790100      | mov r8d,dword ptr ds:[7FF6CD4AA138]          |
    29. 00007FF6CD492799 | 41:83C8 01            | or r8d,1                                     |
    30. 00007FF6CD49279D | 44:8905 94790100      | mov dword ptr ds:[7FF6CD4AA138],r8d          |
    31. 00007FF6CD4927A4 | EB 07                 | jmp 2_voxel64demo.7FF6CD4927AD               |
     
  14. Ahimov

    Ahimov Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2024
    Сообщения:
    882
    ml64,

    Еще робот нашел.
    Код (Text):
    1. # Краткий отчёт по ошибкам
    2.  
    3. ## Критичные (ломают работу)
    4.  
    5. | # | Место | Суть |
    6. |---|-------|------|
    7. | 1 | `ScaleFraction`, pre-shift | `shr ebx,cl` при `cl ≥ 32`: `cl` маскируется до 5 бит (`cl & 31`), сдвиг неверный. Диапазон `ecx` до 118. Нужен каскадный сдвиг с ограничением `cl ≤ 31`. |
    8. | 2 | `mov pszOutput,rdi` (в начале) | Перезапись параметра **сдвинутым** указателем. Затем `Exp0`/`Exp255`/`Overflow` читают `pszOutput` и получают `buf+1` вместо `buf`. Минус не стирается. |
    9. | 3 | `szOverflow` | Не определена в `.data` (в комментариях только `szZero`, `szNaN`, `szInfinity`). Ошибка компоновки. |
    10. | 4 | `Infinity` | Не сбрасывает `rdi` на начало буфера. Для `-Inf` получается `"-Inf"`, для `-NaN` — `"NaN"`. Несогласованно. |
    11.  
    12. ## Средние (корректность)
    13.  
    14. | # | Место | Суть |
    15. |---|-------|------|
    16. | 5 | Округление дроби | `add eax,5; div 10` — half-up. `printf` использует half-even. Расхождение на граничных значениях. |
    17. | 6 | `-0.0` | `Exp0` стирает минус. `printf` даёт `-0.0000`. |
    18. | 7 | Соглашение вызова | Параметры объявлены как `proc binFloatValue:DWORD, pszOutput:QWORD`, но комментарии говорят про `esi`/`edi`. В 64-битном MASM параметры в `rcx/rdx`. Проверить `PROLOG`. |
    19.  
    20. ## Мелкие (стиль/скорость)
    21.  
    22. | # | Место | Суть |
    23. |---|-------|------|
    24. | 8 | `mov binFloatValue,esi` | Бесполезная (и опасная) запись в параметр. |
    25. | 9 | `r10` (sign) | Устанавливается, нигде не читается — мёртвый код. |
    26. | 10 | `loop` в `CopyLoop`/`CopyFrac` | Медленно (~5 тактов), лучше `dec ecx / jnz`. |
    27. | 11 | `div ebx` (ebx=10) | ~20–40 тактов, заменить умножением на магию `0xCCCCCCCD`. |
    28. | 12 | `lea r15, intBuf` / `fracBuf` | Зависит от корректности `PROLOG 100h` + `LOCAL`. Проверить. |
    29.  
    30. ## Что проверено и НЕ является ошибкой
    31.  
    32. - `mul edx` (100000): макс ~1.7e12 < 2^64 — ок.
    33. - `shrd eax,edx,cl` в `DoScale64`: результат < 100000 < 2^32 — ок.
    34. - `inc r11d` при carry из дроби: `intPart` не может быть `0xFFFFFFFF` — ок.
    35. - `shld edx,eax,cl` в `ShiftLeft`: `cl < 32` гарантировано — ок.
    36. - `LoopInt`/`LoopFrac`: `ebx=10` всегда установлен — ок.
    37. - `r15` в буферах: `intBuf[16]` (≤10 цифр), `fracBuf[8]` (ровно 4) — влезает.
    38.  
    39. ## Приоритет исправлений
    40.  
    41. 1. Убрать `mov binFloatValue,esi` и `mov pszOutput,rdi` (или поменять направление).
    42. 2. Починить pre-shift в `ScaleFraction`.
    43. 3. Определить `szOverflow`.
    44. 4. Решить вопрос знака для `-0.0`/`-NaN`/`-Inf`.
    45. 5. Заменить `div` на магию, `loop` — на `dec/jnz`.
    46. 6. Перейти на half-even, если нужна совместимость с `printf`.