0,0 → 1,403 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 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 |
|