Blog. Just Blog

Быстрый поиск

Введите фрагмент названия статьи для поиска

Полезные функции для работы с датами на Ассемблере

05.06.2014 | Категория: Образ мышления: Assembler | Автор: ManHunter

Полезные функции для работы с датами на Ассемблере

Из разных источников насобирал различные полезные функции для работы с датами на Ассемблере. Преимущества их в том, что они работают очень быстро, хорошо оптимизированы и позволяют обходиться вообще без вызова системных функций. Все функции самодостаточные и не требуют для работы каких-либо дополнительных данных.

Читать статью целиком »
Просмотров: 8537 | Комментариев: 4

Преобразование вещественного числа в строку на Ассемблере

14.03.2014 | Категория: Образ мышления: Assembler | Автор: ManHunter
Ранее я выкладывал статью о том, как на Ассемблере перевести строку в вещественное число, теперь настало время произвести обратную операцию, то есть перевести вещественное число в строку. В отличие от целых чисел, где достаточно нескольких строк кода, с преобразованием вещественных чисел пришлось повозиться. В результате появилась следующая функция. За основу взята аналогичная функция из пакета MASM, но со значительными доработками.
  1. ;------------------------------------------------------------
  2. ; Функция перевода вещественного числа в строку
  3. ;------------------------------------------------------------
  4. ; Портирование с MASM, доработка и оптимизация - ManHunter
  5. ; Параметры:
  6. ;   lpFloat - указатель на вещественное число TBYTE
  7. ;   lpResult - указатель на строку-приемник результата
  8. ;------------------------------------------------------------
  9. proc    FloatToString lpFloat:DWORD, lpResult:DWORD
  10.         ; Локальные переменные
  11.         local   digits_count:DWORD
  12.         local   tmp:DWORD
  13.         local   old_cw:WORD
  14.         local   new_cw:WORD
  15.         local   saved_float:TBYTE
  16.         local   tmp1 rb 12h
  17.         local   tmp2 rb 12h
  18.  
  19.         ; Сохранить все регистры
  20.         pusha
  21.  
  22.         ; Указатель на строку-приемник
  23.         mov     edi,[lpResult]
  24.  
  25.         ; Это ноль?
  26.         mov     esi,[lpFloat]
  27.         cmp     dword [esi],0
  28.         jne     loc_not_zero
  29.         cmp     dword [esi+4],0
  30.         jne     loc_not_zero
  31.         cmp     word [esi+8],0x8000
  32.         je      loc_minus_zero
  33.         cmp     word [esi+8],0
  34.         jne     loc_not_zero
  35.         ; Записать в строку ноль
  36.         mov     al,'0'
  37.         stosb
  38.         jmp     loc_ret
  39. loc_minus_zero:
  40.         ; Записать в строку минус ноль
  41.         mov     ax,'-0'
  42.         stosw
  43.         jmp     loc_ret
  44. loc_not_zero:
  45.         ; Denormalized?
  46.         mov     ax,word [esi+8]
  47.         and     ax,7F80h
  48.         or      ax,ax
  49.         jnz     loc_not_denorm
  50.         cmp     dword [esi],0
  51.         jne     loc_denorm
  52.         cmp     dword [esi+4],0
  53.         je      loc_not_denorm
  54. loc_denorm:
  55.         mov     esi,szDen
  56.         movsd
  57.         movsd
  58.         movsd
  59.         jmp     loc_ret
  60. loc_not_denorm:
  61.         ; Infinity или NaN?
  62.         mov     ax,word [esi+8]
  63.         and     ax,7F80h
  64.         cmp     ax,7F80h
  65.         jne     loc_not_inf_nan
  66.  
  67.         ; Это Infinity?
  68.         cmp     dword [esi],0
  69.         jne     loc_nan
  70.         cmp     dword [esi+4],80000000h
  71.         jne     loc_nan
  72. loc_infinity:
  73.         mov     esi,szInf
  74.         movsd
  75.         movsb
  76. loc_plus_minus:
  77.         movsd
  78.         mov     esi,[lpFloat]
  79.         test    byte [esi+9],80h
  80.         jz      loc_ret
  81.         mov     esi,[lpResult]
  82.         mov     byte[esi],'-'
  83.         jmp     loc_ret
  84. loc_nan:
  85.         mov     esi,szNan
  86.         jmp     loc_plus_minus
  87.  
  88. loc_not_inf_nan:
  89.         ; Скопировать число в локальную переменную
  90.         push    edi
  91.         mov     esi,[lpFloat]
  92.         lea     edi,[saved_float]
  93.         movsd
  94.         movsd
  95.         movsw
  96.         pop     edi
  97.         ; Число отрицательное?
  98.         cmp     dword [saved_float+6],0
  99.         jge     loc_not_signed
  100.         ; Привести число к абсолютному значению
  101.         and     byte [saved_float+9],7Fh
  102.         ; Записать в строку минус
  103.         mov     al,'-'
  104.         stosb
  105.  
  106. loc_not_signed:
  107.         ; Проверить число на наличие дробной части и
  108.         ; подсчитать количество цифр в нем
  109.         fclex
  110.         ; Сохранить управляющее слово
  111.         fstcw   [old_cw]
  112.         ; Установить управляющее слово
  113.         mov     [new_cw],0000001001111111b
  114.         fldcw   [new_cw]
  115.         lea     esi,[saved_float]
  116.         fld     tbyte [esi]
  117.         fld     st
  118.         ; Выделить мантиссу и порядок
  119.         fxtract
  120.         fstp    st
  121.         fldlg2
  122.         ; Получить количество цифр в числе
  123.         fmulp   st1,st
  124.         fistp   [digits_count]
  125.         ; Если цифр больше 16, то число отображается в
  126.         ; нормализованном виде с мантиссой и экспонентой
  127.         cmp     [digits_count],10h
  128.         jnb     loc_not_integer
  129.         ; У числа есть дробная часть?
  130.         fld     st
  131.         frndint
  132.         fcomp   st1
  133.         fstsw   ax
  134.         test    ah,01000000b
  135.         ; Да, отображать число с дробной частью
  136.         jz      loc_not_integer
  137.  
  138.         ; Целое число без дробной части и экспоненты
  139.         lea     eax,[tmp1]
  140.         fbstp   [eax]
  141.  
  142.         ; Перевести BCD-число в строку
  143.         push    edi
  144.         lea     esi,[tmp1+8]
  145.         lea     edi,[tmp2]
  146.         mov     ecx, 9
  147. @@:
  148.         std
  149.         xor     eax,eax
  150.         lodsb
  151.         cld
  152.         rol     ax,12
  153.         rol     ah,4
  154.         add     ax,'00'
  155.         stosw
  156.         loop    @b
  157.         pop     edi
  158.  
  159.         ; Пропустить лидирующий ноль
  160.         mov     eax,11h
  161.         mov     ecx,[digits_count]
  162.         sub     eax,ecx
  163.         inc     ecx
  164.         lea     esi,[tmp2+eax]
  165.         cmp     byte [esi],'0'
  166.         jne     @f
  167.         inc     esi
  168.         dec     ecx
  169. @@:
  170.         ; Перенести полученное число из временного буфера
  171.         rep     movsb
  172.         jmp     loc_clear_stack
  173.  
  174. loc_not_integer:
  175.         mov     eax,10h
  176.         sub     eax,[digits_count]
  177.  
  178.         ; Преобразовать число в целое до 16 разрядов
  179.         mov     ecx,eax
  180.         cmp     eax,0
  181.         jge     @f
  182.         neg     eax
  183. @@:
  184.         ; Для чисел больше 0 корректировка округления в сторону 0
  185.         mov     [new_cw],0000101001111111b
  186.         cmp     ecx,0
  187.         jge     @f
  188.         mov     [new_cw],0000011001111111b
  189. @@:
  190.         ; Установить управляющее слово
  191.         fldcw   [new_cw]
  192.  
  193.         ; Возвести 10 в степень количества цифр
  194.         mov     [tmp],eax
  195.         fild    [tmp]
  196.         fld     [float2]
  197.         fyl2x
  198.         fld1
  199.         fld     st1
  200.         fprem
  201.         f2xm1
  202.         faddp
  203.         fscale
  204.  
  205.         ; Почистить стек
  206.         fxch    st1
  207.         fstp    st
  208.  
  209.         ; Если число меньше 0, то умножить, иначе разделить
  210.         cmp     ecx,0
  211.         jge     @f
  212.         fdivp   st1,st
  213.         jmp     loc_rounded
  214. @@:
  215.         fmulp   st1,st
  216.  
  217. loc_rounded:
  218.         ; Полученное значение меньше 1.0e16 ?
  219.         fcom    [float1]
  220.         fstsw   ax
  221.         test    ah,1
  222.         jz      @f
  223.         fmul    [float2]
  224.         dec     [digits_count]
  225. @@:
  226.         ; Целое число без дробной части и экспоненты
  227.         lea     eax,[tmp1]
  228.         fbstp   [eax]
  229.  
  230.         ; Перевести BCD-число в строку
  231.         push    edi
  232.         lea     esi,[tmp1+8]
  233.         lea     edi,[tmp2]
  234.         mov     ecx, 9
  235. @@:
  236.         std
  237.         xor     eax,eax
  238.         lodsb
  239.         cld
  240.         rol     ax,12
  241.         rol     ah,4
  242.         add     ax,'00'
  243.         stosw
  244.         loop    @b
  245.         pop     edi
  246.  
  247.         ; Числу требуется мантисса и экспонента?
  248.         lea     esi,[tmp2+1]
  249.         mov     ecx,[digits_count]
  250.         cmp     ecx,-0Fh
  251.         jl      loc_mantiss_and_exponent
  252.         cmp     ecx,10h
  253.         jg      loc_mantiss_and_exponent
  254.  
  255.         ; Заполнить дробную часть числа
  256.         inc     ecx
  257.         cmp     ecx,0
  258.         jg      @f
  259.         mov     ax,'0.'
  260.         stosw
  261.         neg     ecx
  262.         mov     al,'0'
  263.         rep     stosb
  264.         mov     ecx,10h
  265.         jmp     loc_fraction_filled
  266. @@:
  267.         rep     movsb
  268.         mov     al,'.'
  269.         stosb
  270.         mov     ecx,10h
  271.         sub     ecx,[digits_count]
  272.  
  273. loc_fraction_filled:
  274.         rep     movsb
  275.         jmp     @f
  276.  
  277. loc_clear_fraction:
  278.         ; Удалить завершающие нули дробной части
  279.         dec     edi
  280. @@:
  281.         cmp     byte [edi-1],'0'
  282.         jz      loc_clear_fraction
  283.         cmp     byte [edi-1],'.'
  284.         jnz     @f
  285.         dec     edi
  286. @@:
  287.         jmp     loc_clear_stack
  288.  
  289. loc_mantiss_and_exponent:
  290.         ; Дробная часть мантиссы
  291.         movsb
  292.         mov     al,'.'
  293.         stosb
  294.         movsd
  295.         movsd
  296.         movsw
  297.         ; Удалить завершающие нули дробной части
  298. @@:
  299.         cmp     byte [edi-1],'0'
  300.         jne     @f
  301.         cmp     byte [edi-2],'.'
  302.         je      @f
  303.         dec     edi
  304.         jmp     @b
  305. @@:
  306.         ; Символ и знак экспоненты
  307.         mov     al,'e'
  308.         stosb
  309.         mov     al,'+'
  310.         mov     ebx,[digits_count]
  311.         cmp     ebx, 0
  312.         jge     @f
  313.         mov     al,'-'
  314.         neg     ebx
  315. @@:
  316.         stosb
  317.  
  318.         ; Значение экспоненты
  319.         mov     eax,ebx
  320.         mov     ecx,10
  321.         mov     ebx,4
  322. @@:
  323.         dec     ebx
  324.         xor     edx,edx
  325.         div     ecx
  326.         add     dl,'0'
  327.         mov     [tmp1+ebx],dl
  328.         or      ebx,ebx
  329.         jnz     @b
  330.  
  331.         ; Пропустить лидирующие нули экспоненты
  332.         mov     ecx,4
  333.         lea     esi,[tmp1]
  334. @@:
  335.         lodsb
  336.         cmp     al,'0'
  337.         jne     @f
  338.         dec     ecx
  339.         jmp     @b
  340. @@:
  341.         dec     esi
  342.         rep     movsb
  343.  
  344. loc_clear_stack:
  345.         ; Восстановить управляющее слово
  346.         fldcw   [old_cw]
  347. loc_ret:
  348.         ; Окончание строки
  349.         mov     al,0
  350.         stosb
  351.  
  352.         ; Восстановить все регистры
  353.         popa
  354.         ret
  355.  
  356. float1  dq      1.0e16
  357. float2  dq      10.0
  358.  
  359. szInf   db      '+Infinity'
  360. szNan   db      '+NaN'
  361. szDen   db      'Denormalized'
  362.  
  363. endp
Параметры вызова: lpFloat - указатель на вещественное число TBYTE (10 байт), lpResult - указатель на строку-приемник результата. Функция самодостаточная, не требует никаких дополнительных переменных в секции данных и вспомогательных функций, исходное число не меняется. В отличие от MASM'овской функции, поддерживаются вещественные числа в диапазоне -1e4932..+1e4932, увеличено количество отображаемых цифр после запятой, улучшена точность округления мантиссы для очень больших и очень маленьких чисел, улучшено форматирование значения экспоненты и выполнены другие действия по оптимизации алгоритма.

Читать статью целиком »
Просмотров: 11156 | Комментариев: 27

Оптимизация умножения на константу на Ассемблере

05.08.2013 | Категория: Образ мышления: Assembler | Автор: ManHunter
В предыдущей статье по оптимизации мы рассматривали замену команд деления, как это описано в "AMD Athlon Processor x86 Code Optimization Guide". Но в этом же мануале описана оптимизация умножения на константу. Тут нет универсальных алгоритмов, по которым можно было бы однозначно определить нужную последовательность команд замены, как в случае с делением. Для каждой константы набор команд определяется на основании их "весовых коэффициентов" и количества тактов процессора, необходимых для их выполнения. В качестве примера приведена вот такая табличка оптимизации умножения с 2 до 32. Ее всегда можно посмотреть и в самом мануале, но лучше пусть будет под рукой.
  1. ; Умножение на 2
  2. add reg1, reg1          ; 1 такт процессора
  3.  
  4. ; Умножение на 3
  5. lea reg1, [reg1+reg1*2] ; 2 такта процессора
  6.  
  7. ; Умножение на 4
  8. shl reg1, 2             ; 1 такт процессора
  9.  
  10. ; Умножение на 5
  11. lea reg1, [reg1+reg1*4] ; 2 такта процессора
  12.  
  13. ; Умножение на 6
  14. lea reg1, [reg1+reg1*2] ; 3 такта процессора
  15. add reg1, reg1
  16.  
  17. ; Умножение на 7: 
  18. mov reg2, reg1          ; 2 такта процессора
  19. shl reg1, 3
  20. sub reg1, reg2
  21.  
  22. ; Умножение на 8: 
  23. shl reg1, 3             ; 1 такт процессора
  24.  
  25. ; Умножение на 9: 
  26. lea reg1, [reg1+reg1*8] ; 2 такта процессора
  27.  
  28. ; Умножение на 10: 
  29. lea reg1, [reg1+reg1*4] ; 3 такта процессора
  30. add reg1, reg1
  31.  
  32. ; Умножение на 11:
  33. lea reg2, [reg1+reg1*8] ; 3 такта процессора
  34. add reg1, reg1
  35. add reg1, reg2
  36.  
  37. ; Умножение на 12:
  38. lea reg1, [reg1+reg1*2] ; 3 такта процессора
  39. shl reg1, 2
  40.  
  41. ; Умножение на 13:
  42. lea reg2, [reg1+reg1*2] ; 3 такта процессора
  43. shl reg1, 4
  44. sub reg1, reg2
  45.  
  46. ; Умножение на 14:
  47. lea reg2, [reg1+reg1]   ; 3 такта процессора
  48. shl reg1, 4
  49. sub reg1, reg2
  50.  
  51. ; Умножение на 15:
  52. lea reg1, [reg1+reg1*2] ; 4 такта процессора
  53. lea reg1, [reg1+reg1*4]
  54.  
  55. ; Умножение на 16:
  56. shl reg1, 4             ; 1 такт процессора
  57.  
  58. ; Умножение на 17:
  59. mov reg2, reg1          ; 2 такта процессора
  60. shl reg1, 4
  61. add reg1, reg2
  62.  
  63. ; Умножение на 18:
  64. lea reg1, [reg1+reg1*8] ; 3 такта процессора
  65. add reg1, reg1
  66.  
  67. ; Умножение на 19:
  68. lea reg2, [reg1+reg1*2] ; 3 такта процессора
  69. shl reg1, 4
  70. add reg1, reg2
  71.  
  72. ; Умножение на 20:
  73. lea reg1, [reg1+reg1*4] ; 3 такта процессора
  74. shl reg1, 2
  75.  
  76. ; Умножение на 21:
  77. lea reg2, [reg1+reg1*4] ; 3 такта процессора
  78. shl reg1, 4
  79. add reg1, reg2
  80.  
  81. ; Умножение на 22:
  82. lea reg2, [reg1+reg1*4] ; 4 такта процессора
  83. add reg1, reg1
  84. lea reg1, [reg1+reg2*4]
  85.  
  86. ; Умножение на 23:
  87. lea reg2, [reg1+reg1*8] ; 3 такта процессора
  88. shl reg1, 5
  89. sub reg1, reg2
  90.  
  91. ; Умножение на 24:
  92. lea reg1, [reg1+reg1*2] ; 3 такта процессора
  93. shl reg1, 3
  94.  
  95. ; Умножение на 25:
  96. lea reg1, [reg1+reg1*4] ; 4 такта процессора
  97. lea reg1, [reg1+reg1*4]
  98.  
  99. ; Умножение на 26:
  100. lea reg2, [reg1+reg1*2] ; 4 такта процессора
  101. add reg1, reg1
  102. lea reg1, [reg1+reg2*8]
  103.  
  104. ; Умножение на 27:
  105. lea reg1, [reg1+reg1*2] ; 4 такта процессора
  106. lea reg1, [reg1+reg1*8]
  107.  
  108. ; Умножение на 28:
  109. lea reg2, [reg1*4]      ; 3 такта процессора
  110. shl reg1, 5
  111. sub reg1, reg2
  112.  
  113. ; Умножение на 29:
  114. lea reg2, [reg1+reg1*2] ; 3 такта процессора
  115. shl reg1, 5
  116. sub reg1, reg2
  117.  
  118. ; Умножение на 30:
  119. lea reg2, [reg1+reg1]   ; 3 такта процессора
  120. shl reg1, 5
  121. sub reg1, reg2
  122.  
  123. ; Умножение на 31:
  124. mov reg2, reg1          ; 2 такта процессора
  125. shl reg1, 5
  126. sub reg1, reg2
  127.  
  128. ; Умножение на 32:
  129. shl reg1, 5             ; 1 такт процессора
В разделе мануала, посвященном оптимизации целочисленного умножения, упоминается программа "FINDMUL", которая находится на "AMD Documentation CD-ROM". Как написано в мануале, эта программа должна рассчитывать оптимальный алгоритм умножения на константу. К сожалению, ни саму программу, ни этот диск в интернетах мне найти не удалось, поэтому больше ничего про нее сказать не могу. Неизвестны ни алгоритм ее работы, ни диапазон констант, которые она в состоянии оптимизировать. Если кто-то знает где его взять, то, пожалуйста, напишите. Буду очень благодарен.

Читать статью целиком »
Просмотров: 8182 | Комментариев: 7

Замена деления умножением на Ассемблере

07.07.2013 | Категория: Образ мышления: Assembler | Автор: ManHunter

Замена деления умножением на Ассемблере

При написании на Ассемблере алгоритмов, использующих деление на константу, операции деления можно заменять на операции умножения. Зачем это надо? Дело в том, что процессор выполняет операцию умножения в несколько раз быстрее, чем операцию деления. К примеру, на умножение тратится 5-9 тактов процессора (знаковое умножение) или 4-8 (беззнаковое умножение), тогда как для деления необходимо 22-47 тактов (знаковое деление) или 17-41 тактов (беззнаковое деление). В высокооптимизированных алгоритмах, таких как шифрование, математические расчеты, архивация больших объемов данных, подсчет контрольных сумм и других подобных задачах, экономия каждого такта процессора может дать значительный прирост общей скорости работы программы.

В руководстве по оптимизации "AMD Athlon Processor x86 Code Optimization Guide" вопрос замены деления умножением расписан очень подробно. Рассмотрены частные случаи деления, такие как деление на степень двойки, описан выбор алгоритма для знакового и беззнакового деления и приведен код для вычисления вспомогательных корректирующих значений. Кроме этого, в руководстве описаны методы оптимизации и других математических операций. Даже если вы никогда не будете использовать на практике замену деления умножением, почитать о других способах оптимизации будет очень полезно.

Читать статью целиком »
Просмотров: 14413 | Комментариев: 4

Расчет энтропии на Ассемблере

29.06.2012 | Категория: Образ мышления: Assembler | Автор: ManHunter
Энтропия - это количество информации, приходящейся на одно элементарное сообщение источника, вырабатывающего статистически независимые сообщения. Говоря проще, это условный коэффициент, показывающий распределение уникальных элементов в массиве данных. На практике, к примеру, анализаторы исполняемых файлов используют подсчет энтропии секции кода как часть эвристики, для определения насколько упакованы или зашифрованы файлы. Чем выше показатель энтропии - тем выше вероятность, что данные уже упакованы или зашифрованы, и тем меньше они могут быть подвергнуты повторной компрессии. Математическая формула расчета энтропии следующая:


Формула расчета энтропии

Где p(i) - количество каждого уникального символа в строке, разделенное на общую длину строки. Программно это легко реализуется. Так, строка '012345' имеет показатель энтропии 2.58, строка '001122', так же как и '222200001111' - 1.58, а строка любой длины, состоящая из одинаковых символов, имеет нулевую энтропию. Я написал такую функцию на Ассемблере для расчета энтропии произвольного блока памяти:
  1. ;-----------------------------------------------------------------------
  2. ; Функция расчета энтропии блока памяти
  3. ; by ManHunter / PCL
  4. ; http://www.manhunter.ru
  5. ;
  6. ; Параметры:
  7. ; szStr - указатель на блок памяти для расчета
  8. ; dLen  - размер блока в байтах
  9. ; lpRes - указатель на приемник результата (DWORD)
  10. ;-----------------------------------------------------------------------
  11. proc    CalcEntropy szStr:DWORD, dLen:DWORD, lpRes:DWORD
  12.         locals
  13.         count   dd ?            ; Количество символов
  14.         cnt     rd 256          ; Счетчики символов
  15.         endl
  16.  
  17.         pusha
  18.  
  19.         ; Инициализация сопроцессора
  20.         finit
  21.  
  22.         ; Обнулить счетчики символов
  23.         lea     edi,[cnt]
  24.         mov     ecx,256
  25.         xor     eax,eax
  26.         rep     stosd
  27.  
  28.         ; Подсчет количества символов
  29.         mov     esi,[szStr]
  30.         mov     ecx,[dLen]
  31. .loc_count_chars:
  32.         xor     eax,eax
  33.         lodsb
  34.         shl     eax,2
  35.         inc     dword [cnt+eax]
  36.         loop    .loc_count_chars
  37.  
  38.         ; Начальное значение энтропии
  39.         fldz
  40.  
  41.         ; Расчет энтропии для каждого символа
  42.         mov     ecx,256
  43. .loc_calc_entr:
  44.         dec     ecx
  45.  
  46.         ; Получить количества символов
  47.         mov     eax,ecx
  48.         shl     eax,2
  49.         mov     eax,[cnt+eax]
  50.         ; Нулевые количества пропускаем
  51.         or      eax,eax
  52.         jz      @f
  53.  
  54.         mov     [count],eax
  55.  
  56.         fild    [dLen]  ; Длина строки
  57.         fild    [count] ; Количество символов
  58.         fdiv    st0,st1 ; P(i) = SUM(i)/total
  59.         fst     st1     ; Скопировать st0 в st1
  60.         fchs            ; Изменить знак
  61.         fxch    st1     ; Поменять местами регистры
  62.         fyl2x           ; H(i) = -P(i)*log2(P(i))
  63.         fadd    st1,st0 ; H = H+H(i)
  64.         ffree   st0
  65.         fincstp         ; Почистить стек
  66. @@:
  67.         ; Все символы обработали?
  68.         or      ecx,ecx
  69.         jnz     .loc_calc_entr
  70.  
  71.         ; Записать значение в ячейку памяти
  72.         mov     eax,[lpRes]
  73.         fstp    dword [eax]
  74.  
  75.         ffree   st0
  76.         fincstp         ; Почистить стек
  77.  
  78.         popa
  79.         ret
  80. endp
Функция самодостаточная, не требует никаких дополнительных переменных в сегменте данных. Единственная проблема может возникнуть в том случае, если количество каких-нибудь символов превысит размерность DWORD.

Читать статью целиком »
Просмотров: 6090 | Комментариев: 1

Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.07 сек. / MySQL: 3 (0.0045 сек.) / Память: 4.5 Mb
Наверх