11e927c0c3
git-svn-id: svn://kolibrios.org@3675 a494cfbc-eb01-0410-851d-a64ba20cac60
404 lines
8.0 KiB
PHP
404 lines
8.0 KiB
PHP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 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
|
|
|