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

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

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

Так что добро пожаловать и приятного вам общения!!! ;)
 
Модераторы: 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:
1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
0 пользователей:


Рейтинг@Mail.ru
[ Script Execution time: 0,1512 ]   [ 19 queries used ]   [ Generated: 17.08.18, 23:02 GMT ]