арифмометр - masm32

Есть арифмометр, на masm32, для 4-х арифметических операций, который игнорирует числа меньше единицы. Хотя, не должен. Не могу понять - в чём дело? Поскольку здесь нельзя прицепить архив, добавлю наиболее сомнительную часть кода, преобразование string-float:

  pushad                ;сохраняем значения регистров
  mov  dot,0            ;инициируем dot
  lea  esi,stroka       ;строка символов
  lea  edi,float        ;вещественный результат
  finit                 ;обрабатываем необработанные исключения 
  cld                   ;устанавливаем направление переноса - от начала к концу цепочки
  fldz                  ;st=0=>float
cycl:
  xor  eax,eax          ;чистим регистр
  lodsb                 ;копируем байт/символ из DS:ESI в AL
  cmp  al,0             ;если нет символа
  je   fini             ;на выход
  cmp  dot,0            ;была точка?
  jg   drob             ;если да (dot > 0)
  cmp  al,"."           ;это точка?
  je   c_dot            ;если да
  and  al,0Fh           ;преобразуем символ
  movzx eax,al          ;расширяем его
  mov  [edi],eax        ;и сохраняем 
c_int:                  ;работаем с целой частью числа
  fimul ten             ;st=0*10...
  fiadd dword ptr [edi] ;st=0*10+float, накапливаем дв.код целой части 
  jmp  cycl             ;повторяем с целой частью
c_dot:                  ;встретили точку
  mov  dot,1h           ;фиксируем наличие точки и преобразуем множитель
  fld1                  ;st=1                st(1)=float<-в начале=0
  fidiv ten             ;st=1:10=0.1         st(1)=float
  fstp aten             ;st=float            aten=0.1                    
  jmp  cycl             ;к след.символу 
drob:                   ;например [.123 equ 0.123]
  fld  aten             ;st=0.1              st(1)<-в начале float=0
  fimul dword ptr [edi] ;st=0.1*1            st(1)=float
  faddp st(1),st        ;st=0.1*1+0...накапливаем дв.код дробной части        
  fld   aten            ;st=0.1              st(1)=float
  fidiv ten             ;st=0.1/10           st(1)=float
  fstp  aten            ;st=float            aten=0.01...
  jmp  cycl             ;повторяем с дробной частью               
fini:
  fstp dword ptr [edi]  ;сохраняем двоичный код во float
  popad

Ответы (1 шт):

Автор решения: Виктор

У меня так получилось (на базе Вашего кода):

locals @@
.386 
.model flat, stdcall 

.data 
string  db  "43.99",0
float   dd  0

.code
start:

    call    str_to_float, offset string, offset float
    or      eax, eax
    jz      error_convert

    ...

str_to_float    proc    in_string: dword, out_float: dword
    uses    esi, edi, ecx    ;сохраняем значения регистров

.data
@@_ten  dd  10
@@_aten real4   0.1

.code
    xor ecx, ecx            ;инициируем dot
    mov esi, in_string  ;строка символов
    mov edi, out_float  ;вещественный результат

    cld         ;устанавливаем направление переноса - от начала к концу цепочки
    finit           ;обрабатываем необработанные исключения 
    fldz            ;st=0=>float

@@_loop:
    lodsb           ;копируем байт/символ из DS:ESI в AL

    or  al, al      ; коней строки
    jz  @@_exit_ok  ;на выход

    cmp al,"."      ;это точка?
    jz  @@_c_dot    ;если да

    and al, 0Fh     ;преобразуем символ
    movzx   eax, al     ;расширяем его
    mov [edi], eax  ;и сохраняем 

    or  cx, cx      ;была точка?
    jnz @@_after_dot    ;если да (dot > 0)

    ;работаем с целой частью числа
    fimul   @@_ten      ;st=0*10...
    fiadd   dword ptr [edi] ;st=0*10+float, накапливаем дв.код целой части 
    jmp @@_loop     ;повторяем с целой частью

@@_c_dot:           ;встретили точку
    inc cx      ;фиксируем наличие точки и преобразуем множитель
    cmp cx,1
    jz  @@_ok_one_dot
        xor eax, eax ; Error: Более одной точки в строке eax = 0
        jmp @@_exit_error

@@_ok_one_dot:
    fld1            ;st=1                st(1)=float<-в начале=0
    fidiv   @@_ten      ;st=1:10=0.1         st(1)=float
    fstp    @@_aten     ;st=float            aten=0.1                    
    jmp @@_loop     ;к след.символу 

@@_after_dot:                   ;например [.123 equ 0.123]
    fld @@_aten         ;st=0.1              st(1)<-в начале float=0
    fimul   dword ptr [edi] ;st=0.1*1            st(1)=float
    faddp   st(1),st        ;st=0.1*1+0...накапливаем дв.код дробной части        
    fld @@_aten         ;st=0.1              st(1)=float
    fidiv   @@_ten          ;st=0.1/10           st(1)=float
    fstp    @@_aten         ;st=float            aten=0.01...
    jmp @@_loop         ;повторяем с дробной частью               

@@_exit_ok:
    xor eax, eax
    inc eax

    fstp dword ptr [edi]    ;сохраняем float

@@_exit_error:
    ret
    endp
→ Ссылка