Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.226.93.207] |
|
Сообщ.
#1
,
|
|
|
Это арифмометр в "готовом" виде:
;арифметика под coпроцессор .686 .model flat, stdcall include сonst.inc .data include data.inc .code main: push 0 call GetModuleHandleA@4 mov [hInst],eax winmain proc mov [wc.CLSSTYLE],STYLE mov [wc.CLWNDPROC],offset winproc mov [wc.CLSCBCLSEX],0 mov [wc.CLSCBWNDEX],0 mov eax,[hInst] mov [wc.CLSHINST],eax push IDI_APPLICATION push 0 call LoadIconA@8 mov [wc.CLSHICON],eax push IDC_ARROW push 0 call LoadCursorA@8 mov [wc.CLSHCURSOR],eax mov [wc.CLBKGROUND],18 mov DWORD ptr [wc.CLMENNAME],0 mov DWORD ptr [wc.CLNAME],offset CLASSNAME push offset wc call RegisterClassA@4 ;окно арифмометра: push 0 push [hInst] push 0 push 0 push 225 ;y-высота окна push 215 ;x-ширина окна push 200 push 200 push WS_OVERLAPPEDWINDOW push offset titleName push offset className push 0 call CreateWindowExA@48 cmp eax,0 jz _err mov [hWnd],eax push SW_SHOWNORMAL push [hWnd] call ShowWindow@8 push [hWnd] call UpdateWindow@4 msg_loop: push 0 push 0 push 0 push offset msg call GetMessageA@16 cmp eax,0 je end_loop push offset msg call TranslateMessage@4 push offset msg call DispatchMessageA@4 jmp msg_loop end_loop: push [msg.MSWPARAM] call ExitProcess@4 _err: jmp end_loop winmain endp ;создали окно арифмометра winproc proc ;процедура окна push ebp mov ebp,esp push ebx push esi push edi cmp dword ptr [ebp+0Ch],WM_CREATE je wmcreate cmp dword ptr [ebp+0Ch],WM_COMMAND je wmcommand cmp dword ptr [ebp+0Ch],WM_DESTROY je wmdestroy jmp defwndproc wmcreate: ;начинаем обработку WM_CREATE ;-------------------------- C (y=)---------------------------------- push 0 push [hInst] push 0 push [ebp+08h] push 150 ;высота push 30 ;ширина push 40 ;y-сверху push 10 ;x-слева push STYLBUT push offset butC push offset clsBut push 0 call CreateWindowExA@48 mov hbutC,eax ;-------------------------- 1 (y=40)---------------------------------- push 0 push [hInst] push 0 push [ebp+08h] push 30 push 30 push 40 push 50 push STYLBUT push offset but1 push offset clsBut push 0 call CreateWindowExA@48 mov hbut1,eax ;-------------------------- 2 (y=40)---------------------------------- push 0 push [hInst] push 0 push [ebp+08h] push 30 push 30 push 40 push 90 push STYLBUT push offset but2 push offset clsBut push 0 call CreateWindowExA@48 mov hbut2,eax ;-------------------------- 3 (y=40)---------------------------------- push 0 push [hInst] push 0 push [ebp+08h] push 30 push 30 push 40 push 130 push STYLBUT push offset but3 push offset clsBut push 0 call CreateWindowExA@48 mov hbut3,eax ;-------------------------- 4 (y=80)---------------------------------- push 0 push [hInst] push 0 push [ebp+08h] push 30 push 30 push 80 push 50 push STYLBUT push offset but4 push offset clsBut push 0 call CreateWindowExA@48 mov hbut4,eax ;----------------------------------5(y=80)------------------------------------ push 0 push [hInst] push 0 push [ebp+08h] push 30 push 30 push 80 push 90 push STYLBUT push offset but5 push offset clsBut push 0 call CreateWindowExA@48 mov hbut5,eax ;-------------------------- 6 (y=)---------------------------------- push 0 push [hInst] push 0 push [ebp+08h] push 30 push 30 push 80 push 130 push STYLBUT push offset but6 push offset clsBut push 0 call CreateWindowExA@48 mov hbut6,eax ;------------------------------------7(y=50)----------------------------------- push 0 push [hInst] push 0 push [ebp+08h] push 30 push 30 push 120 push 50 push STYLBUT push offset but7 push offset clsBut push 0 call CreateWindowExA@48 mov hbut7,eax ;-------------------------- 8 (y=80)---------------------------------- push 0 push [hInst] push 0 push [ebp+08h] push 30 push 30 push 120 push 90 push STYLBUT push offset but8 push offset clsBut push 0 call CreateWindowExA@48 mov hbut8,eax ;-------------------------- 9 (y=120)---------------------------------- push 0 push [hInst] push 0 push [ebp+08h] push 30 push 30 push 120 push 130 push STYLBUT push offset but9 push offset clsBut push 0 call CreateWindowExA@48 mov hbut9,eax ;-------------------------- . (y=120)---------------------------------- push 0 push [hInst] push 0 push [ebp+08h] push 30 push 30 push 160 push 90 push STYLBUT push offset butP push offset clsBut push 0 call CreateWindowExA@48 mov hbutP,eax ;------------------------------------0(y=50)----------------------------------- push 0 push [hInst] push 0 push [ebp+08h] push 30 push 30 push 160 push 50 push STYLBUT push offset but0 push offset clsBut push 0 call CreateWindowExA@48 mov hbut0,eax ;------------------------------------+(y=40)----------------------------------- push 0 push [hInst] push 0 push [ebp+08h] push 30 push 30 push 40 push 170 push STYLBUT push offset butS push offset clsBut push 0 call CreateWindowExA@48 mov hbutS,eax ;----------------------------------- - (y=80)----------------------------------- push 0 push [hInst] push 0 push [ebp+08h] push 30 push 30 push 80 push 170 push STYLBUT push offset butM push offset clsBut push 0 call CreateWindowExA@48 mov hbutM,eax ;----------------------------------- * (y=120)----------------------------------- push 0 push [hInst] push 0 push [ebp+08h] push 30 push 30 push 120 push 170 push STYLBUT push offset butU push offset clsBut push 0 call CreateWindowExA@48 mov hbutU,eax ;----------------------------------- : (y=160)----------------------------------- push 0 push [hInst] push 0 push [ebp+08h] push 30 push 30 push 160 push 170 push STYLBUT push offset butD push offset clsBut push 0 call CreateWindowExA@48 mov hbutD,eax ;------------------------------------=(y=160)----------------------------------- push 0 push [hInst] push 0 push [ebp+08h] push 30 push 30 push 160 push 130 push STYLBUT push offset butI push offset clsBut push 0 call CreateWindowExA@48 mov hbutI,eax ;----------------------окно редактирования---------------------------- push 0 push [hInst] push 0 push [ebp+08h] push 20 push 190 push 10 push 10 push STYLEDT push offset Edt push offset clsEdt push 0 call CreateWindowExA@48 mov hedt,eax jmp exit ;закончили обработку WM_CREATE - это была графика wmcommand: ;начинаем обработку WM_COMMAND mov eax,[hbut1] cmp [ebp+14h],eax ;нажали "1"? je nabor ;переходим сюда mov eax,[hbut2] cmp [ebp+14h],eax je nabor mov eax,[hbut3] cmp [ebp+14h],eax je nabor mov eax,[hbut4] cmp [ebp+14h],eax je nabor mov eax,[hbut5] cmp [ebp+14h],eax je nabor mov eax,[hbut6] cmp [ebp+14h],eax je nabor mov eax,hbut7 cmp [ebp+14h],eax je nabor mov eax,[hbut8] cmp [ebp+14h],eax je nabor mov eax,[hbut9] cmp [ebp+14h],eax je nabor je nabor mov eax,[hbut0] cmp [ebp+14h],eax je nabor mov eax,[hbutP] cmp [ebp+14h],eax je nabor mov eax,hbutS cmp [ebp+14h],eax je plus mov eax,[hbutM] cmp [ebp+14h],eax je minus mov eax,[hbutU] cmp [ebp+14h],eax je umno mov eax,hbutD cmp [ebp+14h],eax je deli mov eax,[hbutC] cmp [ebp+14h],eax je clear mov eax,[hbutI] cmp [ebp+14h],eax je itog jmp defwndproc ;возвращаемся в процедуру ;всё, что ниже, обрабатывается только после непосредственного обращения nabor: ;набираем число push 16 ;ёмкость буфера stroka push offset stroka push [hedt] ;куда добавляем call GetWindowTextA@12 add eax,offset stroka push 16 push eax push [EBP+14h] ;кнопкa call GetWindowTextA@12 call settext jmp exit plus: ;жмём "+"...одна из 4-х кнопок операций, начало цикла call plu jmp exit minus: call min jmp exit umno: call umn jmp exit deli: call del jmp exit clear: ;кнопка полного цикла call clproc jmp exit itog: ;набрали 2-е число, нажимаем "=" mov edi,char cmp edi,hbutS je plus_ex cmp edi,hbutM je minus_ex cmp edi,hbutU je umno_ex cmp edi,hbutD je deli_ex plus_ex: call pluex jmp exit minus_ex: call minex jmp exit umno_ex: call umnex jmp exit deli_ex: call delex jmp exit exit: ;заканчиваем работу программы xor eax,eax xor ebx,ebx jmp finish wmdestroy: ;обрабатываем WM_DESTROY, если... push 0 call PostQuitMessage@4 defwndproc: ;обрабатываем msg-и push [ebp+14h] ;lParam push [ebp+10h] ;wParam push [ebp+0Ch] ;Msg push [ebp+ 8h] ;hWnd call DefWindowProcA@16 finish: pop edi pop esi pop ebx pop ebp ret 16 winproc endp clproc proc ;процедура очистки дисплея push offset Edt push [hedt] call SetWindowTextA@8 ret clproc endp settext proc ;роцедура вывода результата на дисплей push offset stroka push [hedt] call SetWindowTextA@8 ret settext endp ;------------------------- арифметика ----------------------------------------- ;операция сложения: plu proc ;набрали 1-е число и нажали "+" pushad mov ebx,hbutS ;запоминаем mov char,ebx ;тип операции (аналог->select = "+") call slen ;длина целой и дробной части 1-го числа mov edx,point ;дробность mov point1,edx ;1-го числа call asc2float ;преобразуем 1-ю строку в дв.код mov esi,float mov float1,esi ;float1=1-й дв.код call clproc ;очищаем дисплей popad ret plu endp pluex proc ;набрали 2-е число и нажали "=" call clproc ;очищаем дисплей call slen ;длина целой и дробной части 2-го числа call asc2float ;преобразуем 2-е число в дв.код=>float call add_32 call float2asc ;преобразуем итог в строку call settext ;добавляем итог на дисплей ret pluex endp add_32 proc finit cmp point1,1 ;1-е число дробное? je a1 ;да->a1 fild float1 ;нет jmp a2 a1: fld float1 a2: cmp point,1 ;2-е число дробное? je a3 ;да->a3 fild float ;нет jmp a4 a3: fld float a4: fadd fstp res ret add_32 endp ;операция вычитания: min proc pushad mov ebx,hbutM ;запоминаем mov char,ebx ;тип операции (аналог->select = "-") call slen ;длина целой и дробной части mov edx,point ;дробность mov point1,edx ;1-го числа call asc2float ;преобразуем 1-ю строку в дв.код mov esi,float mov float1,esi call clproc ;очищаем дисплей popad ret min endp minex proc call clproc ;очищаем дисплей call slen call asc2float ;преобразуем 2-е число в дв.код=>float call sub_32 call float2asc ;преобразуем итог в строку call settext ;добавляем итог на дисплей ret minex endp sub_32 proc finit cmp point,1 ;2-е число дробное? je s1 ;да->s1 fild float ;нет jmp s2 s1: fld float s2: cmp point1,1 ;1-е число дробное? je s3 ;да->s3 fild float1 ;нет jmp s4 s3: fld float1 s4: fsub fstp res ret sub_32 endp ;операция умножения: umn proc pushad mov ebx,hbutU ;запоминаем mov char,ebx ;тип операции (аналог->select = "*") call slen ;длина целой и дробной части mov edx,point ;дробность mov point1,edx ;1-го числа call asc2float ;преобразуем 1-ю строку в дв.код mov esi,float mov float1,esi ;float1=1-й дв.код call clproc ;очищаем дисплей popad ret umn endp umnex proc call clproc ;очищаем дисплей call slen call asc2float ;преобразуем 2-е число в дв.код call mul_32 call float2asc ;преобразуем итог в строку call settext ;добавляем итог на дисплей ret umnex endp mul_32 proc finit cmp point1,1 ;1-е число дробное? je u1 ;да->u1 fild float1 ;нет jmp u2 u1: fld float1 u2: cmp point,1 ;2-е число дробное? je u3 ;да->u3 fild float ;нет jmp u4 u3: fld float u4: fmul fstp res ret mul_32 endp ;операция деления: del proc pushad mov ebx,hbutD ;запоминаем mov char,ebx ;тип операции (аналог->select = "/") call slen ;длина целой и дробной части mov edx,point ;дробность mov point1,edx ;1-го числа call asc2float ;преобразуем 1-ю строку в дв.код mov esi,float mov float1,esi ;float1=1-й дв.код call clproc ;очищаем дисплей popad ret del endp delex proc call clproc ;очищаем дисплей call slen call asc2float call div_32 call float2asc ;преобразуем итог в строку call settext ;добавляем итог на дисплей ret delex endp div_32 proc finit cmp point,1 ;2-е число дробное? je d1 ;да->d1 fild float ;нет jmp d2 d1: fld float d2: cmp point1,1 ;1-е число дробное? je d3 ;да->d3 fild float1 ;нет jmp d4 d3: fld float1 d4: fdiv fstp res ret div_32 endp ;--------------------- конвертация ----------------------------------------------- ;к-во символов целой и дробной части введённого числа: slen proc pushad xor eax,eax xor edx,edx lea eax,stroka ;адрес начала stroka db 16 dup (0) mov point,0 ;инициируем... (point dd ?) mov cel,0 ;целая часть числа (cel dd ?) mov dro,0 ;дробная часть числа (drob dd ?) s1: mov bl,[eax] ;берём ASCII-символ or bl,bl ;есть символ? jz s4 ;нет->s4 cmp point,0 ;была точка? jne s3 ;да->s3 cmp bl,"." ;это точка? je s2 ;да->s2 inc edx ;фиксируем символ целой части inc eax ;смещаемся вправо, к следующему символу jmp s1 ;повторяем s2: mov cel,edx ;сохраняем к-во символов целой части stroka xor edx,edx ;EDX=0 inc eax ;пропускаем точку mov point,1 ;фиксируем её наличие jmp s1 s3: inc edx ;фиксируем символ дробной части inc eax ;смещаемся вправо, к следующему символу jmp s1 mov dro,edx ;сохраняем к-во символов дробной части stroka s4: popad ret slen endp ;преобразуем символы в двоичный код: asc2float proc pushad xor eax,eax ;EAX=0 xor ebx,ebx ;EBX=0 mov bcel,0 ;инициируем (bcel dd ?) mov ecx,cel ;счётчик = к-во символов целой части mov edx,ten ;EDX=(ten dd 10.0) lea esi,stroka ;адрес левого ASCII-символа целой части cel_cycl: ;((((0*10)+1)*10+2)*10+3)*10+4 = 1234 mov bl,[esi] ;добавим в EBX ASCII-символ or bl,bl ;есть символ? jz fin ;нет->fin cmp bl,"0" ;это "0"? je d1 ;да->d1 (без целой части) and bl,0Fh ;убираем 3-ку mul edx ;учитываем множитель add eax,ebx ;формируем дв.код целой части jc err ;если переполнение inc esi ;смещаемся вправо loop cel_cycl ;повторяем mov bcel,eax ;сохраняем целую часть xor eax,eax ;EАX=0 d1: mov ecx,dro ;счётчик=к-во символов дробной части mov edx,aten ;EDX=(aten dd 1/10) xor ebx,ebx ;EBX=0 lea esi,stroka ;адрес правого ASCII-символа add esi,cel ;дробной add esi,dro ;части dro_cycl: ;((((4)*0.1+3)*0.1+2)*0.1+1)*0.1+0 = 0.1234 mov bl,[esi] ;добавим в EBX ASCII-символ or bl,bl ;есть символ? jz d2 ;нет->d2 and bl,0Fh ;есть->убираем 3-ку mul edx ;учитываем множитель add eax,ebx ;формируем дв.код дробной части dec esi ;смещаемся влево loop dro_cycl ;повторяем mul edx ;коррекция дробной части d2: add eax,bcel ;ЕАХ=дробная+целая части mov float,eax jc err ;если переполнение err: fin: popad ret asc2float endp ;преобразуем двоичный код в символы: float2asc proc pushad xor eax,eax xor esi,esi lea esi,stroka lea eax,res mov edx,5 ;5 цифр в дробной части finit fld dword ptr [eax] ;st = res fldz ;st=0, st(1)=res fcomip st,st(1) ;st = res jz zero ;if res = 0 -> zero jb n1 ;if res < 0 -> n1 xor ebx,ebx ;EBX=0 dec ebx ;EBX=(-1) push ebx ;вершина стека -> ESP fild dword ptr [esp] ;st = [esp], st(1) = res pop ebx fxch ;st<->st(1) --> st = res, st(1) = [esp] fmul st,st(1) ;st = st * st(1) --> res * [esp] mov byte ptr [esi],"-" ;добавляем в stroka минус inc esi ;смещаемся n1: fld1 ;st=1, st(1)=res fcomip st,st(1) ;st=res jz one ;st-st(1) = 0 -> one jb norm ;st-st(1) < 0 -> norm jmp trans norm: xor ecx,ecx mov eax,1 ;EAX=1 push eax fld1 ;st=1, st(1)=res fxch ;st=res, st(1)=1 rep1: fmul dword ptr [esp] ;st=st*[esp]=st*1 inc ecx ;счётчик целой части fcomi st,st(1) jb n2 jmp rep1 n2: pop eax trans: xchg edx,ecx ;ECX = число после точки, EDX = до add ecx,edx ;ECX = число цифр до + после точки mov eax,10 ;EAX=10 push eax ;[esp]->10 fild dword ptr [esp] ;st = 10 fxch ;st = res, st(1) = 10 rep2: fmul st,st(1) ;st = res * 10 fld1 ;st = 1, st(1) = res * 10 fcmovne st,st(1) ;копируем, если не равно fistp dword ptr [esp] ;округляем st и выталкиваем в [ESP] mov al,byte ptr [esp] fild dword ptr [esp] ;st = текущее значение fsubp st(1),st add al,30h ;AL: BCD->ASCII mov byte ptr [esi],al ;добавляем в stroka inc esi ;смещаемся dec edx ;EDX-1 cmp edx,0 ;закончилась дробная часть? jnz n3 ;нет -> n3 mov byte ptr [esi],"." ;если EDX = 0 -> добавляем в stroka точку inc esi n3: loop rep2 pop eax jmp fin zero: mov byte ptr [esi],"0" jmp fin one: mov byte ptr [esi],"1" jmp fin error: fin: popad ret float2asc endp end main Результатом ЛЮБОЙ арифметической операции является ВТОРОЕ набранное число, предваряемое "0". Помогите разобратся. |