На главную
ПРАВИЛА FAQ Помощь Участники Календарь Избранное DigiMania RSS
msm.ru
! Перед отправкой сообщения внимательно прочтите правила раздела!!!
1. Запрещается обсуждать написание вирусов, троянов и других вредоносных программ!
2. Помните, что у нас есть FAQ раздела Assembler и Полезные ссылки. Посмотрите, возможно, там уже имеется решение вашего вопроса.

3. Настоятельно рекомендуем обратить особое внимание на правила форума, которые нарушаются чаще всего:
  3.1. Заголовок темы должен кратко отражать её суть. Темы с заголовками типа "Срочно помогите!" или "Ассемблер" будут отправляться в Корзину для мусора.
  3.2. Исходники программ обязательно выделяйте тегами [code]...[/code] (одиночные инструкции можно не выделять).
  3.3. Нежелательно поднимать старые темы (не обновлявшиеся более года) без веской на то причины.

Не забывайте также про главные Правила форума!

Добро пожаловать и приятного вам общения!!! ;)
 
Модераторы: Jin X, Qraizer
  
> конвертация типов-продолжение, создание процедуры преобразования
    Простой арифмометр для целых положительных чисел, конвертация по Р.Мареку:
    ExpandedWrap disabled
      ...
      data:
        stroka db 10 dup (?),0
        rezult dd ?
      ...
      nabor:                    ;обработка кнопок полного цикла
        push  15
        push  offset stroka     ;получаем содержимое дисплея  
        push  [hedt]        
        call  GetWindowTextA@12
        add   eax,offset stroka ;добавляем его в ЕАХ    
        push  15
        push  eax               ;туда-же добавляем
        push  [EBP+14h]         ;символ нажатой кнопки
        call  GetWindowTextA@12
        call  settext
        mov   esi,eax           ;сбрасываем число в ESI, EAX - на очистку            
        jmp   exit    
      ...
      plus:                     ;набираем 1-е число-строку и жмём "+"...одна из 4-х кнопок
                                ;операций, начало цикла
        mov   edi,hbutS         ;фиксируем тип операции
        call  asc2dec           ;преобразуем ASCII-символы в 1-e дес.число --> ЕВХ
        mov   eax,ebx           ;копируем 1-e дес.число --> EAX
        call  clearproc         ;очищаем дисплей
      ...
      plus_ex:                  ;набираем 2-е число-строку и жмём "="
        xor  edi,edi            ;убираем хэндл кнопки из EDI
        call asc2dec            ;преобразуем ASCII-символы во 2-е дес. число --> EBX
        add  eax,ebx            ;сумма-итог в ЕАХ
        mov  [result],eax       ;сохраняем итог в result
        xor  eax,eax            ;очищаем ЕАХ (скопировал - очисти)
        call clearproc          ;очищаем дисплей
        call dec2asc            ;преобразуем дес. число в ASCII-строку и...
        call settext            ;...добавляем её на дисплей
        jmp  exit               ;окончание "цикла" одной из 4-х операционных кнопок
      ...
      exit:                     ;заканчиваем работу программы
        xor   eax,eax
        xor   ebx,ebx
        jmp   finish  
      ...
      finish:
        pop   edi
        pop   esi
        pop   ebx
        pop   ebp
        ret   16  
      ...
      ;преобразуем строку в дес.число: суть --> 1234 = ((((1)*10 + 2)*10 + 3)*10) + 4
      ;вход --> ESI = stroka
      ;выход --> ЕВХ = дес. число    
      asc2dec  proc
        mov  esi,[stroka]                  
        mov  ecx,0Ah            ;ECX = основание системы счисления
        xor  ebx,ebx            ;ЕВХ = 0 <-- под десятичное число  
        cycl:                   ;после набора --> mov esi,eax и еах --> 0
          lodsb                 ;записываем байт из ES:ESI в AL  
          or   al,al            ;конец строки ?
          jz   exit             ;если 0
          sub  al,"0"           ;вычитаем 30h и сохраняем дес. цифру в AL
          push eax              ;сохраняем цифру в стеке - ЕАХ необходим для умножения
          mov  eax,ebx
          mul  ecx              ;умножить ЕВХ на ЕСХ и...
          mov  ebx,eax          ;...сохраняем в ЕВХ
          pop  eax              ;достаём цифру из стека и...  
          add  ebx,eax          ;...складываем с содержимым EBX
          jmp  cycl             ;и повторить
          exit:  
            ret
      asc2dec endp    
      ;преобразуем дес.число в строку:    
      dec2asc proc              ;выход: заполненная stroka
        pushad                  ;сохраняем все регистры общего назначения
        mov  ebx,10h            ;EBX = основание системы счисления
        mov  eax,[result]       ;EAX = дес.число
        mov  edi,[stroka]       ;EDI = указатель на строку
        xor  ecx,ecx            ;ECX = 0 - счетчик цифр в стеке
        conv:                   ;преобразуем число
          xor  edx,edx          ;сюда - остаток от деления - цифра
          div  ebx              ;делим ЕАХ на ЕВХ, частное в ЕАХ, остаток в EDX
          add  dl,"0"           ;преобразуем остаток в ASCII-символ и...
          push edx              ;...запихиваем в стек
          inc  ecx              ;увеличиваем счётчик цифр в стеке
          or   eax,eax          ;частное(ЕАХ) = 0 ?
          jnz  conv             ;если - нет, продолжаем
          cld                   ;сбрасываем флаг направления DF, запись вперёд
        write:                  ;записываем число
          pop  edx              ;выталкиваем символы из стека
          mov  eax,edx          ;копируем в ЕАХ          
          stosb                 ;записываем byte из AL в буфер по адресу ES:EDI
          loop write            ;если - нет, переходим к следующей цифре
          mov  byte ptr [edi],0 ;заканчиваем строку 0-вым байтом
          popad
          ret
      dec2asc endp
      ...
      end  main

    Примеры операций:
    44 + 22 = 866762083(1563948387)...
    44 - 22 = 866762083(1563948387)...
    44 * 22 = 866762083(1563948387)...
    44 : 22 = 866762083(1563948387)...в скобочках - после перезагрузки арифмометра. Что интересно - при наборе с клавы - результаты другие.
    Помогите - кто чем может, особенно в части "stroka db 10 dup (?),0" - что-то мне тут не нравится.
    :-?
      Просмотрел беглым взглядом.
      Первое, что бросается в глаза:
      1. В asc2dec: mov esi,[stroka] – записываете в esi содержимое строки, хотя должен быть адрес, надо mov esi,offset stroka (или lea esi,[stroka]).
      2. Аналогично в dec2asc: вместо mov edi,[stroka] должно быть mov edi,offset stroka (или lea edi,[stroka]).
      Вообще, странно, что здесь не возникает исключения, и программа не рушится.
      vpmultishiftqb vscatterpf0dps vfmsubadd132pd vgatherpf1dps vpclmulhqlqdq vcmptrue_ussd vaeskeygenassist
        Можно попробовать ускорить(?) dec2asc, убрав 'or eax,eax' способом:
        1. Заменить 'add dl, "0"' на 'lea edx, ...'
        2. Заменить 'inc eax' на 'lea eax, ...'
          Славян, а с чего вдруг lea edx,[edx+'0'] будет быстрее, чем add dl,'0', а lea eax,[eax+1] быстрее, чем inc eax ?
          Она может быть медленнее иногда, но точно не быстрее в данном случае...
          vpmultishiftqb vscatterpf0dps vfmsubadd132pd vgatherpf1dps vpclmulhqlqdq vcmptrue_ussd vaeskeygenassist
            Скорость не за счёт ускорение атомарной операции, а за счёт того, что:
            1. lea edx, [edx+...] идёт параллельно с lea ecx, [ecx+1]
            2. lea ecx, [ecx+1] идёт параллельно с jnz
            3. убрана одна инструкция or, на которую завязан переход jnz
              Славян, как же ты хочешь избавиться от or ?
              div не меняет значение флага ZF в зависимости от результата в Intel, только в AMD.

              Реальное ускорение будет тогда, когда div будет заменён mul'ом.
              А параллельность и так будет, надо только переставить местами какие-то операции.
              ExpandedWrap disabled
                ; будем считать, что в EDX содержится исходное число, а EDI уже указывает на строку вывода
                dec2asc proc
                  push ebx
                  xor ecx,ecx  ; счётчик цифр
                 @@next:
                  mov eax,0CCCCCCCDh
                  lea ebx,[edx+'0']
                  mul edx
                  shr edx,3  ; edx = частное
                  lea eax,[edx+edx*4]
                  add ecx,1
                  add eax,eax  ; eax = частное*10
                  sub ebx,eax  ; ebx = остаток+'0'
                  push ebx
                  test edx,edx
                  jnz @@next
                 @@out:
                  pop eax
                  stosb
                  dec ecx
                  jnz @@out
                  xor al,al
                  stosb
                  pop ebx
                  ret
                dec2asc endp
              Вот только большой вопрос - нужно ли ему такое ускорение?
              Ещё мне push не очень нравится, можно просто писать строку задом наперёд (std).

              p.s. Кстати, ещё один косяк в коде автора: mov ebx,10h вместо mov ebx,10.
              vpmultishiftqb vscatterpf0dps vfmsubadd132pd vgatherpf1dps vpclmulhqlqdq vcmptrue_ussd vaeskeygenassist
                Благодарю за поддержку. С конвертацией я разобрался и арифмометр заработал, но...как-то странно:

                ascbuf db 10 dup (" ") - это массив, он начинается с "0" (добавляем при развороте: mov byte ptr [edi],0)

                Проверил диапазон правой стороны буфера, из bin2asc:

                для lea edi,ascbuf:

                1+1=4 8 0 2
                1+12=2 6 4 13
                1+123=2 4 2 5 24
                1+1234=2 4 0 3 6 35

                для lea edi,ascbuf-1: по идее - это правый крайний байт буфера

                1+1=8 0 2
                1+12=6 4 13
                1+123=4 2 5 24
                1+1234=4 0 3 6 35

                для lea edi,ascbuf-2:

                1+1=0 2
                1+12=4 13
                1+123=2 5 24
                1+1234=0 3 6 35

                для lea edi,ascbuf-3:

                1+1= 2
                1+12= 13
                1+123=5 24
                1+1234=3 6 35

                для lea edi,ascbuf-4:

                1+1= пусто
                1+12= 3
                1+123= 24
                1+1234=6 35

                Эта логика мне пока неподвластна. Что посоветуете?
                Сообщение отредактировано: cupoma58 -
                  Цитата cupoma58 @
                  для lea edi,ascbuf-1: по идее - это правый крайний байт буфера
                  Это не правый крайний байт буфера, а байт перед буфером.

                  А что вот это за шифр вы приводите, я не понимаю:
                  Цитата cupoma58 @
                  1+1=4 8 0 2
                  1+12=2 6 4 13
                  1+123=2 4 2 5 24
                  1+1234=2 4 0 3 6 35


                  Добавлено
                  Запись идёт в буфер в прямом порядке, а не в обратном.
                  Просто цифры при записи в строку извлекаются из стека в обратном порядке.
                  Так что, строка не начинается с 0, а заканчивается нулём.
                  vpmultishiftqb vscatterpf0dps vfmsubadd132pd vgatherpf1dps vpclmulhqlqdq vcmptrue_ussd vaeskeygenassist
                    [QUOTE=Jin X,1533208820,3775537][quote=cupoma58,1533201100,3775532] А что вот это за шифр вы приводите, я не понимаю[/QUOTE]
                    Благодарю за подсказку. С конвертацией, вроде-бы, разобрался, но результаты
                    работы арифмометра - не радуют:
                    ExpandedWrap disabled
                      ascbuf db 10 dup (" ") --> ascbuf db "          ",0
                       
                      bin2asc: lea edi,ascbuf
                                
                          1+1=4 8 0      2         21+31=4 8 0   52          45+55=4 0   100                      
                         1+12=2 6 4     13       221+162=4 8 0  383          81+21=4 8   102                  
                        1+123=2 4 2 5   24        91+123=2 6 4  214          43+51=4 8 0  94                    
                       1+1234=2 4 0 3 6 35     1563+1234=4 8 0 2797        150+250=4 8 0 400
                       
                         21-14=        7        3-2=            1
                        121-14=2 1 6 107      165-7=2 3 7 7    58
                         96-52=       44       25*5=5 7 7 8 0 125
                       285-143=      142        2*3=5 7 7 2 0 0 6


                    Вышеприведённая шифровка - это результаты работы арифмометра.
                    Непонятно - откуда берутся "паровозы", кто их добавляет? Может - по-байтно оперировать?
                    Подскажите - что не так? (cupoma58.ru/assembler_04.html,data.html,const.html)
                      cupoma58, расшифруйте эти цифры, я не понимаю что они значат...
                      vpmultishiftqb vscatterpf0dps vfmsubadd132pd vgatherpf1dps vpclmulhqlqdq vcmptrue_ussd vaeskeygenassist
                        Цитата Jin X @
                        cupoma58, расшифруйте эти цифры, я не понимаю что они значат...

                        Благодарю за подсказку. Приведённый "шифр" - это результаты работы на активированном арифмометре. Ответы правильные, но к ним добавляются "паровозы".
                        Откуда они берутся - не могу понять.
                          Цитата cupoma58 @
                          Цитата Jin X @
                          cupoma58, расшифруйте эти цифры, я не понимаю что они значат...

                          Благодарю за подсказку. Приведённый "шифр" - это результаты работы на активированном арифмометре. Ответы правильные, но к ним добавляются "паровозы".
                          Откуда они берутся - не могу понять.

                          Кое-что я подправил, но правильный ответ только в операции "div". К итогу "сложение - вычитание" добавляется "0", а к итогу "умножение" - "00". В чём дело - не пойму.
                          :wall:
                            Цитата cupoma58 @
                            Цитата cupoma58 @
                            Цитата Jin X @
                            cupoma58, расшифруйте эти цифры, я не понимаю что они значат...

                            Благодарю за подсказку. Приведённый "шифр" - это результаты работы на активированном арифмометре. Ответы правильные, но к ним добавляются "паровозы".
                            Откуда они берутся - не могу понять.

                            Кое-что я подправил, но правильный ответ только в операции "div". К итогу "сложение - вычитание" добавляется "0", а к итогу "умножение" - "00". В чём дело - не пойму.
                            :wall:

                            Всё, разобрался, тема закрыта. Кому интересно - арифмометр для целых, положительных чисел (cupoma58.ru/assembler.html)
                            :victory:
                            1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                            0 пользователей:


                            Рейтинг@Mail.ru
                            [ Script Execution time: 0,1411 ]   [ 14 queries used ]   [ Generated: 15.11.18, 09:10 GMT ]