;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; EXPRESSION PARSER ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; token_end equ 1 token_reg equ 2 token_hex equ 3 token_add equ 4 token_sub equ 5 token_mul equ 6 token_div equ 7 token_lp equ 8 token_rp equ 9 token_err equ -1 ;----------------------------------------------------------------------------- ; Check if byte - some kind of instruction prefix is_prefix: cmp al, 0x64 ; fs: jz .ret cmp al, 0x65 ; gs: jz .ret cmp al, 0x66 ; use16/32 jz .ret cmp al, 0x67 ; addr16/32 jz .ret cmp al, 0xF0 ; lock jz .ret cmp al, 0xF2 ; repnz jz .ret cmp al, 0xF3 ; rep(z) jz .ret cmp al, 0x2E ; cs: jz .ret cmp al, 0x36 ; ss: jz .ret cmp al, 0x3E ; ds: jz .ret cmp al, 0x26 ; es: .ret: ret ;----------------------------------------------------------------------------- ; Check if byte is hex digit is_hex_digit: cmp al, '0' jb .no cmp al, '9' jbe .09 cmp al, 'A' jb .no cmp al, 'F' jbe .AF cmp al, 'a' jb .no cmp al, 'f' jbe .af .no: stc ret .09: sub al, '0' ; clc ret .AF: sub al, 'A'-10 ; clc ret .af: sub al, 'a'-10 ; clc ret ;----------------------------------------------------------------------------- ; Find register in the table find_reg: mov edi, reg_table .findreg: movzx ecx, byte [edi] stc jecxz .regnotfound inc edi push esi edi ecx @@: lodsb or al, 20h scasb loopz @b pop ecx edi esi lea edi, [edi+ecx+1] jnz .findreg movzx edi, byte [edi-1] add esi, ecx .regnotfound: ret ;----------------------------------------------------------------------------- ; Tokenize expressions expr_get_token: lodsb cmp al, 0 jz .end_token cmp al, ' ' jbe expr_get_token cmp al, '+' jz .add cmp al, '-' jz .sub cmp al, '*' jz .mul cmp al, '/' jz .div cmp al, '(' jz .lp cmp al, ')' jnz .notsign .rp: mov al, token_rp ret .div: mov al, token_div ret .end_token: mov al, token_end ret .add: mov al, token_add ret .sub: mov al, token_sub ret .mul: mov al, token_mul ret .lp: mov al, token_lp ret .notsign: dec esi call find_reg jc .regnotfound mov al, token_reg ret .regnotfound: ; test for symbol push esi @@: lodsb cmp al, ' ' ja @b push eax mov byte [esi], 0 xchg esi, [esp+4] call find_symbol_name mov edi, eax pop eax xchg esi, [esp] mov byte [esi], al jc @f add esp, 4 mov al, token_hex ret @@: pop esi ; test for hex number xor ecx, ecx xor edi, edi xor eax, eax @@: lodsb call is_hex_digit jc @f shl edi, 4 or edi, eax inc ecx jmp @b @@: dec esi jecxz .err cmp ecx, 8 ja .err mov al, token_hex ret .err: mov al, token_err mov esi, aParseError ret ;----------------------------------------------------------------------------- expr_read2: cmp al, token_hex jz .hex cmp al, token_reg jz .reg cmp al, token_lp jz .lp mov al, token_err mov esi, aParseError ret .hex: mov ebp, edi .ret: jmp expr_get_token .reg: cmp edi, 24 jz .eip sub edi, 4 jb .8lo sub edi, 4 jb .8hi sub edi, 8 jb .16 mov ebp, [_eax+edi*4] jmp .ret .16: movzx ebp, word [_eax+(edi+8)*4] jmp .ret .8lo: movzx ebp, byte [_eax+(edi+4)*4] jmp .ret .8hi: movzx ebp, byte [_eax+(edi+4)*4+1] jmp .ret .eip: mov ebp, [_eip] jmp .ret .lp: call expr_get_token call expr_read0 cmp al, token_err jz @f cmp al, token_rp jz expr_get_token mov al, token_err mov esi, aParseError @@: ret ;----------------------------------------------------------------------------- expr_read1: call expr_read2 .1: cmp al, token_mul jz .mul cmp al, token_div jz .div ret .mul: push ebp call expr_get_token call expr_read2 pop edx ; ebp := edx*ebp imul ebp, edx jmp .1 .div: push ebp call expr_get_token call expr_read2 pop edx ; ebp := edx/ebp test ebp, ebp jz .div0 push eax xor eax, eax xchg eax, edx div ebp xchg eax, ebp pop eax jmp .1 .div0: mov al, token_err mov esi, aDivByZero ret ;----------------------------------------------------------------------------- expr_read0: xor ebp, ebp cmp al, token_add jz .add cmp al, token_sub jz .sub call expr_read1 .1: cmp al, token_add jz .add cmp al, token_sub jz .sub ret .add: push ebp call expr_get_token call expr_read1 pop edx ; ebp := edx+ebp add ebp, edx jmp .1 .sub: push ebp call expr_get_token call expr_read1 pop edx ; ebp := edx-ebp xchg edx, ebp sub ebp, edx jmp .1 ;----------------------------------------------------------------------------- ; in: esi->expression ; out: CF=1 if error ; CF=0 and ebp=value if ok calc_expression: call expr_get_token call expr_read0 cmp al, token_end jz .end cmp al, token_err jz @f mov esi, aParseError @@: call put_message stc ret .end: clc ret ;----------------------------------------------------------------------------- get_arg: lodsb cmp al, ' ' ja get_arg mov byte [esi-1], 0 cmp al, 0 jnz .skip_spaces dec esi .skip_spaces: lodsb cmp al, 0 jz @f cmp al, ' ' jbe .skip_spaces @@: dec esi ret ; vim: ft=fasm tabstop=4