Blog. Just Blog

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

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

Функции urldecode и urlencode на Ассемблере

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

Функции urldecode и urlencode на Ассемблере

Моя реализация функций PHP urldecode и urlencode, а также двух их разновидностей rawurldecode и rawurlencode на Ассемблере. Алгоритм их работы описан в документации. Единственное отличие от оригинальной функции rawurlencode в том, что кодируется вся строка целиком, а не только буквенно-цифровые символы. На мой взгляд, это более логичное поведение функции с приставкой "raw". В остальном никаких отличий нет.

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

Как преобразовать кириллическую строку из UTF-8 в cp1251

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

Как преобразовать кириллическую строку из UTF-8 в cp1251

При разработке одной программы мне понадобилось преобразовать строки на русском языке из формата UTF-8 в формат cp1251. Внезапно выяснилось, что никакие средства WinAPI не позволяются выполнить эту операцию "одной строкой". Пришлось рассматривать даже варианты с табличным преобразованием, но потом нашлось более простое решение задачи. Алгоритм преобразования получился необычный, но зато гарантированно рабочий. Может быть это поможет сохранить время и нервы кому-нибудь еще.

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

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

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

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

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

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

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

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

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". Как написано в мануале, эта программа должна рассчитывать оптимальный алгоритм умножения на константу. К сожалению, ни саму программу, ни этот диск в интернетах мне найти не удалось, поэтому больше ничего про нее сказать не могу. Неизвестны ни алгоритм ее работы, ни диапазон констант, которые она в состоянии оптимизировать. Если кто-то знает где его взять, то, пожалуйста, напишите. Буду очень благодарен.

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

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