macro test_err { local ..not_error cmp [error_n], 0 je ..not_error ret ..not_error: } macro set_err err { mov [error_n], err ret } ; --------------------------- proc parse mov [exp_pos], 0 stdcall skip_spaces mov ebx, exp add ebx, [exp_pos] cmp [ebx], byte 0 je .null_exp mov [exp_lvl], 0 mov [error_n], 0 stdcall parse_lvl0 ret .null_exp: mov eax, 0 ret endp ; --------------------------- proc parse_lvl0 uses ebx ecx test_err stdcall parse_lvl1 test_err @@: mov ebx, exp add ebx, [exp_pos] cmp [ebx], byte 0 je .end cmp [ebx], byte ")" je .brk_end cmp [ebx], byte "|" je .abs_end inc [exp_pos] cmp [ebx], byte "+" jne .not_add mov ecx, eax stdcall parse_lvl1 test_err add eax, ecx jmp @b .not_add: cmp [ebx], byte "-" jne .unexp_char mov ecx, eax stdcall parse_lvl1 test_err sub ecx, eax mov eax, ecx jmp @b .brk_end: cmp [exp_lvl], 0 jne @f set_err 3 @@: dec [exp_lvl] jmp .end .abs_end: cmp [abs_lvl], 0 jne @f set_err 5 @@: dec [abs_lvl] .end: ret .unexp_char: set_err 4 endp ; --------------------------- proc parse_lvl1 uses ebx ecx edx test_err stdcall parse_lvl2 test_err @@: mov ebx, exp add ebx, [exp_pos] cmp [ebx], byte 0 je .end cmp [ebx], byte "*" jne .not_mul inc [exp_pos] mov ecx, eax stdcall parse_lvl2 test_err imul ecx, eax mov eax, ecx jmp @b .not_mul: cmp [ebx], byte "/" je .div_or_mod cmp [ebx], byte "%" je .div_or_mod jmp .end .div_or_mod: inc [exp_pos] mov ecx, eax stdcall parse_lvl2 test_err cmp eax, 0 jne .not_null set_err 1 .not_null: xchg ecx, eax cdq div ecx cmp [ebx], byte "%" je .mod jmp @b .mod: mov eax, edx jmp @b .end: ret endp ; --------------------------- proc parse_lvl2 uses ebx ecx edx test_err stdcall parse_lvl3 test_err @@: mov ebx, exp add ebx, [exp_pos] cmp [ebx], byte 0 je .end cmp [ebx], byte "^" jne .end inc [exp_pos] mov ecx, eax stdcall parse_lvl2 test_err stdcall c_power jmp @b .end: ret endp ; --------------------------- proc parse_lvl3 uses ebx ecx edx test_err stdcall skip_spaces mov ebx, exp add ebx, [exp_pos] cmp [ebx], byte 48 jl @f cmp [ebx], byte 57 jg @f stdcall parse_lvl4 jmp .end @@: cmp [ebx], byte 97 jl @f cmp [ebx], byte 122 jg @f jmp .parse_func @@: inc [exp_pos] cmp [ebx], byte "(" jne @f inc [exp_lvl] stdcall parse_lvl0 test_err mov ebx, exp add ebx, [exp_pos] cmp [ebx], byte ")" je .brk_ok set_err 2 .brk_ok: inc [exp_pos] jmp .end @@: cmp [ebx], byte "|" jne @f inc [abs_lvl] stdcall parse_lvl0 test_err mov ebx, exp add ebx, [exp_pos] cmp [ebx], byte "|" je .abs_ok set_err 5 .abs_ok: inc [exp_pos] cmp eax, 0 jge .end not eax inc eax jmp .end @@: cmp [ebx], byte "+" jne @f stdcall parse_lvl3 test_err jmp .end @@: cmp [ebx], byte "-" jne .unexp_char stdcall parse_lvl3 test_err neg eax .end: stdcall skip_spaces ret .unexp_char: set_err 4 .parse_func: mov ecx, 0 mov dl, 0 @@: cmp [ebx], byte 97 jl @f cmp [ebx], byte 122 jg @f cmp dl, 4 je .unexp_char shl ecx, 8 mov cl, [ebx] inc dl inc ebx inc [exp_pos] jmp @b @@: cmp ecx, "cni" je @f cmp ecx, "ced" je @f cmp ecx, "sba" je @f cmp ecx, "rqs" je @f jmp .unexp_char @@: stdcall skip_spaces mov ebx, exp add ebx, [exp_pos] cmp [ebx], byte "(" jne .unexp_char inc [exp_lvl] inc [exp_pos] stdcall parse_lvl0 test_err mov ebx, exp add ebx, [exp_pos] cmp [ebx], byte ")" je @f set_err 2 @@: inc [exp_pos] stdcall skip_spaces cmp ecx, "cni" jne @f inc eax jmp .f_end @@: cmp ecx, "ced" jne @f dec eax jmp .f_end @@: cmp ecx, "sba" jne @f mov ecx, eax shr ecx, 31 cmp cl, 1 jne .f_end not eax inc eax jmp .f_end @@: cmp ecx, "rqs" jne @f imul eax, eax jmp .f_end @@: jmp .unexp_char .f_end: ret endp ; --------------------------- proc parse_lvl4 uses ebx ecx stdcall skip_spaces stdcall parse_lvl5 stdcall skip_spaces @@: mov ebx, exp add ebx, [exp_pos] cmp [ebx], byte 0 je .end cmp [ebx], byte "^" jne .end inc [exp_pos] stdcall skip_spaces mov ecx, eax mov ebx, exp add ebx, [exp_pos] cmp [ebx], byte 48 jl .unexp_char cmp [ebx], byte 57 jg .unexp_char stdcall parse_lvl4 stdcall c_power jmp @b .end: ret .unexp_char: set_err 4 endp ; --------------------------- proc parse_lvl5 uses ebx ecx sub eax, eax sub ecx, ecx mov ebx, exp add ebx, [exp_pos] @@: cmp [ebx], byte 0 je @f cmp [ebx], byte 48 jl @f cmp [ebx], byte 57 jg @f imul eax, 10 mov cl, [ebx] add eax, ecx sub eax, 48 inc ebx inc [exp_pos] jmp @b @@: ret endp ; --------------------------- proc skip_spaces uses ebx mov ebx, exp add ebx, [exp_pos] @@: cmp [ebx], byte " " jne @f inc ebx inc [exp_pos] jmp @b @@: ret endp ; --------------------------- proc c_power uses ebx mov ebx, eax mov eax, 1 @@: cmp ebx, 0 je @f imul eax, ecx dec ebx jmp @b @@: ret endp ; --------------------------- proc convert_to_str uses ebx ecx edx esi edi, _num, _str mov eax, [_num] mov esi, [_str] mov edi, 0 mov ecx, eax and ecx, 1 shl 31 cmp ecx, 0 je @f mov [esi], byte "-" inc esi inc edi not eax inc eax @@: mov ebx, 10 xor ecx, ecx @@: xor edx, edx div ebx push edx inc ecx inc edi cmp eax, 0 jne @b @@: pop eax add al, "0" mov [esi], al inc esi loop @b mov [esi], byte 0 mov eax, edi ret endp