Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: конвертация типов - продолжение  (Прочитано 804 раз)
0 Пользователей и 1 Гость смотрят эту тему.
cupoma58
Интересующийся

ru
Offline Offline

« : 31-07-2018 09:54 » 

Простой арифмометр с целыми положительными числами, конвертация по Р.Мареку:
Код: (ASM)
...
data:
  stroka db 15 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  rezult,eax         ;сохраняем итог в rezult
  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  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,rezult         ;EAX = дес.число
  lea  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)...в скобочках - после перезагрузки арифмометра
Что интересно - при наборе с клавы - результат другой. Помогите люди добрые - кто чем может.

                                                                         Здесь была моя ладья...
Записан
darkelf
Молодой специалист

ua
Offline Offline

« Ответ #1 : 31-07-2018 11:00 » 

У Вас, как минимум, eax портится в asc2dec.
Код: (ASM)
asc2dec  proc                  
  mov  ecx,0Ah            ;ECX = основание системы счисления
  xor  ebx,ebx            ;ЕВХ = 0 <-- под десятичное число
  mov esi,[stroka]  
  cycl:                   ;после набора --> mov esi,eax и еах --> 0
    lodsb                 ;записываем байт из ES:ESI в AL  

Соответственно, когда Вы выполняете:
Код: (ASM)
  call asc2dec            ;преобразуем ASCII-символы во 2-е дес. число --> EBX
  add  eax,ebx            ;сумма-итог в ЕАХ
В eax оказывается не то, что Вы ожидали.

« Последнее редактирование: 01-08-2018 04:30 от Алексей++ » Записан
cupoma58
Интересующийся

ru
Offline Offline

« Ответ #2 : 02-08-2018 08:43 » 

Благодарю, со стеком я перемудрил. С конвертацией я разобрался, арифмометр заработал, но...как-то странно:

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            7+9=     16            9+1=        10             10+1=4    11
       1+12=4     13          7+73=4   80          9+12=4       21           10+12=0    22
     1+123=2 5   24        40+40=0   80        9+123=2 5    32         10+123=4   133
   1+1234=0 3 6 35       77+23=    100      9+1234=0 3 6 43       10+1234=2 5 244
                                   77+623=4  700       
                               777+1123=4 1900

для 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
Интересующийся

ru
Offline Offline

« Ответ #3 : 14-08-2018 08:47 » new

Арифмометр тута: cupoma58.ru/assembler_04.html, data.html, const.html
Предыдущая тема - закрыта.
« Последнее редактирование: 16-08-2018 07:24 от cupoma58 » Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines