арифмометр - 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