Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.138.105.41] |
|
Сообщ.
#1
,
|
|
|
Простой арифмометр для целых положительных чисел, конвертация по Р.Мареку:
... 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" - что-то мне тут не нравится. |
Сообщ.
#2
,
|
|
|
Просмотрел беглым взглядом.
Первое, что бросается в глаза: 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]). Вообще, странно, что здесь не возникает исключения, и программа не рушится. |
Сообщ.
#3
,
|
|
|
Можно попробовать ускорить(?) dec2asc, убрав 'or eax,eax' способом:
1. Заменить 'add dl, "0"' на 'lea edx, ...' 2. Заменить 'inc eax' на 'lea eax, ...' |
Сообщ.
#4
,
|
|
|
Славян, а с чего вдруг lea edx,[edx+'0'] будет быстрее, чем add dl,'0', а lea eax,[eax+1] быстрее, чем inc eax ?
Она может быть медленнее иногда, но точно не быстрее в данном случае... |
Сообщ.
#5
,
|
|
|
Скорость не за счёт ускорение атомарной операции, а за счёт того, что:
1. lea edx, [edx+...] идёт параллельно с lea ecx, [ecx+1] 2. lea ecx, [ecx+1] идёт параллельно с jnz 3. убрана одна инструкция or, на которую завязан переход jnz |
Сообщ.
#6
,
|
|
|
Славян, как же ты хочешь избавиться от or ?
div не меняет значение флага ZF в зависимости от результата в Intel, только в AMD. Реальное ускорение будет тогда, когда div будет заменён mul'ом. А параллельность и так будет, надо только переставить местами какие-то операции. ; будем считать, что в 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. |
Сообщ.
#7
,
|
|
|
Благодарю за поддержку. С конвертацией я разобрался и арифмометр заработал, но...как-то странно:
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 Эта логика мне пока неподвластна. Что посоветуете? |
Сообщ.
#8
,
|
|
|
Цитата 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, а заканчивается нулём. |
Сообщ.
#9
,
|
|
|
[QUOTE=Jin X,1533208820,3775537][quote=cupoma58,1533201100,3775532] А что вот это за шифр вы приводите, я не понимаю[/QUOTE]
Благодарю за подсказку. С конвертацией, вроде-бы, разобрался, но результаты работы арифмометра - не радуют: 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) |
Сообщ.
#10
,
|
|
|
cupoma58, расшифруйте эти цифры, я не понимаю что они значат...
|
Сообщ.
#11
,
|
|
|
Цитата Jin X @ cupoma58, расшифруйте эти цифры, я не понимаю что они значат... Благодарю за подсказку. Приведённый "шифр" - это результаты работы на активированном арифмометре. Ответы правильные, но к ним добавляются "паровозы". Откуда они берутся - не могу понять. |
Сообщ.
#12
,
|
|
|
Цитата cupoma58 @ Цитата Jin X @ cupoma58, расшифруйте эти цифры, я не понимаю что они значат... Благодарю за подсказку. Приведённый "шифр" - это результаты работы на активированном арифмометре. Ответы правильные, но к ним добавляются "паровозы". Откуда они берутся - не могу понять. Кое-что я подправил, но правильный ответ только в операции "div". К итогу "сложение - вычитание" добавляется "0", а к итогу "умножение" - "00". В чём дело - не пойму. |
Сообщ.
#13
,
|
|
|
Цитата cupoma58 @ Цитата cupoma58 @ Цитата Jin X @ cupoma58, расшифруйте эти цифры, я не понимаю что они значат... Благодарю за подсказку. Приведённый "шифр" - это результаты работы на активированном арифмометре. Ответы правильные, но к ним добавляются "паровозы". Откуда они берутся - не могу понять. Кое-что я подправил, но правильный ответ только в операции "div". К итогу "сложение - вычитание" добавляется "0", а к итогу "умножение" - "00". В чём дело - не пойму. Всё, разобрался, тема закрыта. Кому интересно - арифмометр для целых, положительных чисел (cupoma58.ru/assembler.html) |