forked from KolibriOS/kolibrios
e167e59b54
git-svn-id: svn://kolibrios.org@9459 a494cfbc-eb01-0410-851d-a64ba20cac60
2236 lines
43 KiB
PHP
2236 lines
43 KiB
PHP
|
|
; flat assembler core
|
|
; Copyright (c) 1999-2021, Tomasz Grysztar.
|
|
; All rights reserved.
|
|
|
|
assembler:
|
|
xor eax,eax
|
|
mov [stub_size],eax
|
|
mov [current_pass],ax
|
|
mov [resolver_flags],eax
|
|
mov [number_of_sections],eax
|
|
mov [actual_fixups_size],eax
|
|
assembler_loop:
|
|
mov eax,[labels_list]
|
|
mov [tagged_blocks],eax
|
|
mov eax,[additional_memory]
|
|
mov [free_additional_memory],eax
|
|
mov eax,[additional_memory_end]
|
|
mov [structures_buffer],eax
|
|
mov esi,[source_start]
|
|
mov edi,[code_start]
|
|
xor eax,eax
|
|
mov dword [adjustment],eax
|
|
mov dword [adjustment+4],eax
|
|
mov [addressing_space],eax
|
|
mov [error_line],eax
|
|
mov [counter],eax
|
|
mov [format_flags],eax
|
|
mov [number_of_relocations],eax
|
|
mov [undefined_data_end],eax
|
|
mov [file_extension],eax
|
|
mov [next_pass_needed],al
|
|
mov [output_format],al
|
|
mov [adjustment_sign],al
|
|
mov [evex_mode],al
|
|
mov [code_type],16
|
|
call init_addressing_space
|
|
pass_loop:
|
|
call assemble_line
|
|
jnc pass_loop
|
|
mov eax,[additional_memory_end]
|
|
cmp eax,[structures_buffer]
|
|
je pass_done
|
|
sub eax,18h
|
|
mov eax,[eax+4]
|
|
mov [current_line],eax
|
|
jmp missing_end_directive
|
|
pass_done:
|
|
call close_pass
|
|
mov eax,[labels_list]
|
|
check_symbols:
|
|
cmp eax,[memory_end]
|
|
jae symbols_checked
|
|
test byte [eax+8],8
|
|
jz symbol_defined_ok
|
|
mov cx,[current_pass]
|
|
cmp cx,[eax+18]
|
|
jne symbol_defined_ok
|
|
test byte [eax+8],1
|
|
jz symbol_defined_ok
|
|
sub cx,[eax+16]
|
|
cmp cx,1
|
|
jne symbol_defined_ok
|
|
and byte [eax+8],not 1
|
|
or [next_pass_needed],-1
|
|
symbol_defined_ok:
|
|
test byte [eax+8],10h
|
|
jz use_prediction_ok
|
|
mov cx,[current_pass]
|
|
and byte [eax+8],not 10h
|
|
test byte [eax+8],20h
|
|
jnz check_use_prediction
|
|
cmp cx,[eax+18]
|
|
jne use_prediction_ok
|
|
test byte [eax+8],8
|
|
jz use_prediction_ok
|
|
jmp use_misprediction
|
|
check_use_prediction:
|
|
test byte [eax+8],8
|
|
jz use_misprediction
|
|
cmp cx,[eax+18]
|
|
je use_prediction_ok
|
|
use_misprediction:
|
|
or [next_pass_needed],-1
|
|
use_prediction_ok:
|
|
test byte [eax+8],40h
|
|
jz check_next_symbol
|
|
and byte [eax+8],not 40h
|
|
test byte [eax+8],4
|
|
jnz define_misprediction
|
|
mov cx,[current_pass]
|
|
test byte [eax+8],80h
|
|
jnz check_define_prediction
|
|
cmp cx,[eax+16]
|
|
jne check_next_symbol
|
|
test byte [eax+8],1
|
|
jz check_next_symbol
|
|
jmp define_misprediction
|
|
check_define_prediction:
|
|
test byte [eax+8],1
|
|
jz define_misprediction
|
|
cmp cx,[eax+16]
|
|
je check_next_symbol
|
|
define_misprediction:
|
|
or [next_pass_needed],-1
|
|
check_next_symbol:
|
|
add eax,LABEL_STRUCTURE_SIZE
|
|
jmp check_symbols
|
|
symbols_checked:
|
|
cmp [next_pass_needed],0
|
|
jne next_pass
|
|
mov eax,[error_line]
|
|
or eax,eax
|
|
jz assemble_ok
|
|
mov [current_line],eax
|
|
cmp [error],undefined_symbol
|
|
jne error_confirmed
|
|
mov eax,[error_info]
|
|
or eax,eax
|
|
jz error_confirmed
|
|
test byte [eax+8],1
|
|
jnz next_pass
|
|
error_confirmed:
|
|
call error_handler
|
|
error_handler:
|
|
mov eax,[error]
|
|
sub eax,error_handler
|
|
add [esp],eax
|
|
ret
|
|
next_pass:
|
|
inc [current_pass]
|
|
mov ax,[current_pass]
|
|
cmp ax,[passes_limit]
|
|
je code_cannot_be_generated
|
|
jmp assembler_loop
|
|
assemble_ok:
|
|
ret
|
|
|
|
create_addressing_space:
|
|
mov ebx,[addressing_space]
|
|
test ebx,ebx
|
|
jz init_addressing_space
|
|
test byte [ebx+0Ah],1
|
|
jnz illegal_instruction
|
|
mov eax,edi
|
|
sub eax,[ebx+18h]
|
|
mov [ebx+1Ch],eax
|
|
init_addressing_space:
|
|
mov ebx,[tagged_blocks]
|
|
mov dword [ebx-4],10h
|
|
mov dword [ebx-8],24h
|
|
sub ebx,8+24h
|
|
cmp ebx,edi
|
|
jbe out_of_memory
|
|
mov [tagged_blocks],ebx
|
|
mov [addressing_space],ebx
|
|
xor eax,eax
|
|
mov [ebx],edi
|
|
mov [ebx+4],eax
|
|
mov [ebx+8],eax
|
|
mov [ebx+10h],eax
|
|
mov [ebx+14h],eax
|
|
mov [ebx+18h],edi
|
|
mov [ebx+1Ch],eax
|
|
mov [ebx+20h],eax
|
|
ret
|
|
|
|
assemble_line:
|
|
mov eax,[tagged_blocks]
|
|
sub eax,100h
|
|
cmp edi,eax
|
|
ja out_of_memory
|
|
lods byte [esi]
|
|
cmp al,1
|
|
je assemble_instruction
|
|
jb source_end
|
|
cmp al,3
|
|
jb define_label
|
|
je define_constant
|
|
cmp al,4
|
|
je label_addressing_space
|
|
cmp al,0Fh
|
|
je new_line
|
|
cmp al,13h
|
|
je code_type_setting
|
|
cmp al,10h
|
|
jne illegal_instruction
|
|
lods byte [esi]
|
|
jmp segment_prefix
|
|
code_type_setting:
|
|
lods byte [esi]
|
|
mov [code_type],al
|
|
jmp instruction_assembled
|
|
new_line:
|
|
lods dword [esi]
|
|
mov [current_line],eax
|
|
and [prefix_flags],0
|
|
cmp [symbols_file],0
|
|
je continue_line
|
|
cmp [next_pass_needed],0
|
|
jne continue_line
|
|
mov ebx,[tagged_blocks]
|
|
mov dword [ebx-4],1
|
|
mov dword [ebx-8],14h
|
|
sub ebx,8+14h
|
|
cmp ebx,edi
|
|
jbe out_of_memory
|
|
mov [tagged_blocks],ebx
|
|
mov [ebx],eax
|
|
mov [ebx+4],edi
|
|
mov eax,[addressing_space]
|
|
mov [ebx+8],eax
|
|
mov al,[code_type]
|
|
mov [ebx+10h],al
|
|
continue_line:
|
|
cmp byte [esi],0Fh
|
|
je line_assembled
|
|
jmp assemble_line
|
|
define_label:
|
|
lods dword [esi]
|
|
cmp eax,0Fh
|
|
jb invalid_use_of_symbol
|
|
je reserved_word_used_as_symbol
|
|
mov ebx,eax
|
|
lods byte [esi]
|
|
mov [label_size],al
|
|
call make_label
|
|
jmp continue_line
|
|
make_label:
|
|
mov eax,edi
|
|
xor edx,edx
|
|
xor cl,cl
|
|
mov ebp,[addressing_space]
|
|
sub eax,[ds:ebp]
|
|
sbb edx,[ds:ebp+4]
|
|
sbb cl,[ds:ebp+8]
|
|
jp label_value_ok
|
|
call recoverable_overflow
|
|
label_value_ok:
|
|
mov [address_sign],cl
|
|
test byte [ds:ebp+0Ah],1
|
|
jnz make_virtual_label
|
|
or byte [ebx+9],1
|
|
xchg eax,[ebx]
|
|
xchg edx,[ebx+4]
|
|
mov ch,[ebx+9]
|
|
shr ch,1
|
|
and ch,1
|
|
neg ch
|
|
sub eax,[ebx]
|
|
sbb edx,[ebx+4]
|
|
sbb ch,cl
|
|
mov dword [adjustment],eax
|
|
mov dword [adjustment+4],edx
|
|
mov [adjustment_sign],ch
|
|
or al,ch
|
|
or eax,edx
|
|
setnz ah
|
|
jmp finish_label
|
|
make_virtual_label:
|
|
and byte [ebx+9],not 1
|
|
cmp eax,[ebx]
|
|
mov [ebx],eax
|
|
setne ah
|
|
cmp edx,[ebx+4]
|
|
mov [ebx+4],edx
|
|
setne al
|
|
or ah,al
|
|
finish_label:
|
|
mov ebp,[addressing_space]
|
|
mov ch,[ds:ebp+9]
|
|
mov cl,[label_size]
|
|
mov edx,[ds:ebp+14h]
|
|
mov ebp,[ds:ebp+10h]
|
|
finish_label_symbol:
|
|
mov al,[address_sign]
|
|
xor al,[ebx+9]
|
|
and al,10b
|
|
or ah,al
|
|
xor [ebx+9],al
|
|
cmp cl,[ebx+10]
|
|
mov [ebx+10],cl
|
|
setne al
|
|
or ah,al
|
|
cmp ch,[ebx+11]
|
|
mov [ebx+11],ch
|
|
setne al
|
|
or ah,al
|
|
cmp ebp,[ebx+12]
|
|
mov [ebx+12],ebp
|
|
setne al
|
|
or ah,al
|
|
or ch,ch
|
|
jz label_symbol_ok
|
|
cmp edx,[ebx+20]
|
|
mov [ebx+20],edx
|
|
setne al
|
|
or ah,al
|
|
label_symbol_ok:
|
|
mov cx,[current_pass]
|
|
xchg [ebx+16],cx
|
|
mov edx,[current_line]
|
|
mov [ebx+28],edx
|
|
and byte [ebx+8],not 2
|
|
test byte [ebx+8],1
|
|
jz new_label
|
|
cmp cx,[ebx+16]
|
|
je symbol_already_defined
|
|
btr dword [ebx+8],10
|
|
jc requalified_label
|
|
inc cx
|
|
sub cx,[ebx+16]
|
|
setnz al
|
|
or ah,al
|
|
jz label_made
|
|
test byte [ebx+8],8
|
|
jz label_made
|
|
mov cx,[current_pass]
|
|
cmp cx,[ebx+18]
|
|
jne label_made
|
|
requalified_label:
|
|
or [next_pass_needed],-1
|
|
label_made:
|
|
ret
|
|
new_label:
|
|
or byte [ebx+8],1
|
|
ret
|
|
define_constant:
|
|
lods dword [esi]
|
|
inc esi
|
|
cmp eax,0Fh
|
|
jb invalid_use_of_symbol
|
|
je reserved_word_used_as_symbol
|
|
push eax
|
|
or [operand_flags],1
|
|
call get_value
|
|
pop ebx
|
|
xor cl,cl
|
|
mov ch,[value_type]
|
|
cmp ch,3
|
|
je invalid_use_of_symbol
|
|
make_constant:
|
|
and byte [ebx+9],not 1
|
|
cmp eax,[ebx]
|
|
mov [ebx],eax
|
|
setne ah
|
|
cmp edx,[ebx+4]
|
|
mov [ebx+4],edx
|
|
setne al
|
|
or ah,al
|
|
mov al,[value_sign]
|
|
xor al,[ebx+9]
|
|
and al,10b
|
|
or ah,al
|
|
xor [ebx+9],al
|
|
cmp cl,[ebx+10]
|
|
mov [ebx+10],cl
|
|
setne al
|
|
or ah,al
|
|
cmp ch,[ebx+11]
|
|
mov [ebx+11],ch
|
|
setne al
|
|
or ah,al
|
|
xor edx,edx
|
|
cmp edx,[ebx+12]
|
|
mov [ebx+12],edx
|
|
setne al
|
|
or ah,al
|
|
or ch,ch
|
|
jz constant_symbol_ok
|
|
mov edx,[symbol_identifier]
|
|
cmp edx,[ebx+20]
|
|
mov [ebx+20],edx
|
|
setne al
|
|
or ah,al
|
|
constant_symbol_ok:
|
|
mov cx,[current_pass]
|
|
xchg [ebx+16],cx
|
|
mov edx,[current_line]
|
|
mov [ebx+28],edx
|
|
test byte [ebx+8],1
|
|
jz new_constant
|
|
cmp cx,[ebx+16]
|
|
jne redeclare_constant
|
|
test byte [ebx+8],2
|
|
jz symbol_already_defined
|
|
or byte [ebx+8],4
|
|
and byte [ebx+9],not 4
|
|
jmp instruction_assembled
|
|
redeclare_constant:
|
|
btr dword [ebx+8],10
|
|
jc requalified_constant
|
|
inc cx
|
|
sub cx,[ebx+16]
|
|
setnz al
|
|
or ah,al
|
|
jz instruction_assembled
|
|
test byte [ebx+8],4
|
|
jnz instruction_assembled
|
|
test byte [ebx+8],8
|
|
jz instruction_assembled
|
|
mov cx,[current_pass]
|
|
cmp cx,[ebx+18]
|
|
jne instruction_assembled
|
|
requalified_constant:
|
|
or [next_pass_needed],-1
|
|
jmp instruction_assembled
|
|
new_constant:
|
|
or byte [ebx+8],1+2
|
|
jmp instruction_assembled
|
|
label_addressing_space:
|
|
lods dword [esi]
|
|
cmp eax,0Fh
|
|
jb invalid_use_of_symbol
|
|
je reserved_word_used_as_symbol
|
|
mov cx,[current_pass]
|
|
test byte [eax+8],1
|
|
jz make_addressing_space_label
|
|
cmp cx,[eax+16]
|
|
je symbol_already_defined
|
|
test byte [eax+9],4
|
|
jnz make_addressing_space_label
|
|
or [next_pass_needed],-1
|
|
make_addressing_space_label:
|
|
mov dx,[eax+8]
|
|
and dx,not (2 or 100h)
|
|
or dx,1 or 4 or 400h
|
|
mov [eax+8],dx
|
|
mov [eax+16],cx
|
|
mov edx,[current_line]
|
|
mov [eax+28],edx
|
|
mov ebx,[addressing_space]
|
|
mov [eax],ebx
|
|
or byte [ebx+0Ah],2
|
|
jmp continue_line
|
|
assemble_instruction:
|
|
; mov [operand_size],0
|
|
; mov [operand_flags],0
|
|
; mov [operand_prefix],0
|
|
; mov [rex_prefix],0
|
|
and dword [operand_size],0
|
|
; mov [opcode_prefix],0
|
|
; mov [vex_required],0
|
|
; mov [vex_register],0
|
|
; mov [immediate_size],0
|
|
and dword [opcode_prefix],0
|
|
call instruction_handler
|
|
instruction_handler:
|
|
movzx ebx,word [esi]
|
|
mov al,[esi+2]
|
|
add esi,3
|
|
add [esp],ebx
|
|
ret
|
|
instruction_assembled:
|
|
test [prefix_flags],not 1
|
|
jnz illegal_instruction
|
|
mov al,[esi]
|
|
cmp al,0Fh
|
|
je line_assembled
|
|
or al,al
|
|
jnz extra_characters_on_line
|
|
line_assembled:
|
|
clc
|
|
ret
|
|
source_end:
|
|
dec esi
|
|
stc
|
|
ret
|
|
|
|
org_directive:
|
|
lods byte [esi]
|
|
cmp al,'('
|
|
jne invalid_argument
|
|
cmp byte [esi],'.'
|
|
je invalid_value
|
|
call get_qword_value
|
|
mov cl,[value_type]
|
|
test cl,1
|
|
jnz invalid_use_of_symbol
|
|
push eax
|
|
mov ebx,[addressing_space]
|
|
mov eax,edi
|
|
sub eax,[ebx+18h]
|
|
mov [ebx+1Ch],eax
|
|
test byte [ebx+0Ah],1
|
|
jnz in_virtual
|
|
call init_addressing_space
|
|
jmp org_space_ok
|
|
in_virtual:
|
|
call close_virtual_addressing_space
|
|
call init_addressing_space
|
|
or byte [ebx+0Ah],1
|
|
org_space_ok:
|
|
pop eax
|
|
mov [ebx+9],cl
|
|
mov cl,[value_sign]
|
|
sub [ebx],eax
|
|
sbb [ebx+4],edx
|
|
sbb byte [ebx+8],cl
|
|
jp org_value_ok
|
|
call recoverable_overflow
|
|
org_value_ok:
|
|
mov edx,[symbol_identifier]
|
|
mov [ebx+14h],edx
|
|
cmp [output_format],1
|
|
ja instruction_assembled
|
|
cmp edi,[code_start]
|
|
jne instruction_assembled
|
|
cmp eax,100h
|
|
jne instruction_assembled
|
|
bts [format_flags],0
|
|
jmp instruction_assembled
|
|
label_directive:
|
|
lods byte [esi]
|
|
cmp al,2
|
|
jne invalid_argument
|
|
lods dword [esi]
|
|
cmp eax,0Fh
|
|
jb invalid_use_of_symbol
|
|
je reserved_word_used_as_symbol
|
|
inc esi
|
|
mov ebx,eax
|
|
mov [label_size],0
|
|
lods byte [esi]
|
|
cmp al,':'
|
|
je get_label_size
|
|
dec esi
|
|
cmp al,11h
|
|
jne label_size_ok
|
|
get_label_size:
|
|
lods word [esi]
|
|
cmp al,11h
|
|
jne invalid_argument
|
|
mov [label_size],ah
|
|
label_size_ok:
|
|
cmp byte [esi],80h
|
|
je get_free_label_value
|
|
call make_label
|
|
jmp instruction_assembled
|
|
get_free_label_value:
|
|
inc esi
|
|
lods byte [esi]
|
|
cmp al,'('
|
|
jne invalid_argument
|
|
push ebx ecx
|
|
or byte [ebx+8],4
|
|
cmp byte [esi],'.'
|
|
je invalid_value
|
|
call get_address_value
|
|
or bh,bh
|
|
setnz ch
|
|
xchg ch,cl
|
|
mov bp,cx
|
|
shl ebp,16
|
|
xchg bl,bh
|
|
mov bp,bx
|
|
pop ecx ebx
|
|
and byte [ebx+8],not 4
|
|
mov ch,[value_type]
|
|
test ch,1
|
|
jnz invalid_use_of_symbol
|
|
make_free_label:
|
|
and byte [ebx+9],not 1
|
|
cmp eax,[ebx]
|
|
mov [ebx],eax
|
|
setne ah
|
|
cmp edx,[ebx+4]
|
|
mov [ebx+4],edx
|
|
setne al
|
|
or ah,al
|
|
mov edx,[address_symbol]
|
|
mov cl,[label_size]
|
|
call finish_label_symbol
|
|
jmp instruction_assembled
|
|
load_directive:
|
|
lods byte [esi]
|
|
cmp al,2
|
|
jne invalid_argument
|
|
lods dword [esi]
|
|
cmp eax,0Fh
|
|
jb invalid_use_of_symbol
|
|
je reserved_word_used_as_symbol
|
|
inc esi
|
|
push eax
|
|
mov al,1
|
|
cmp byte [esi],11h
|
|
jne load_size_ok
|
|
lods byte [esi]
|
|
lods byte [esi]
|
|
load_size_ok:
|
|
cmp al,8
|
|
ja invalid_value
|
|
mov [operand_size],al
|
|
and dword [value],0
|
|
and dword [value+4],0
|
|
lods byte [esi]
|
|
cmp al,82h
|
|
jne invalid_argument
|
|
call get_data_point
|
|
jc value_loaded
|
|
push esi edi
|
|
mov esi,ebx
|
|
mov edi,value
|
|
rep movs byte [edi],[esi]
|
|
pop edi esi
|
|
value_loaded:
|
|
mov [value_sign],0
|
|
mov eax,dword [value]
|
|
mov edx,dword [value+4]
|
|
pop ebx
|
|
xor cx,cx
|
|
jmp make_constant
|
|
get_data_point:
|
|
lods byte [esi]
|
|
cmp al,':'
|
|
je get_data_offset
|
|
cmp al,'('
|
|
jne invalid_argument
|
|
mov ebx,[addressing_space]
|
|
mov ecx,edi
|
|
sub ecx,[ebx+18h]
|
|
mov [ebx+1Ch],ecx
|
|
cmp byte [esi],11h
|
|
jne get_data_address
|
|
cmp word [esi+1+4],'):'
|
|
jne get_data_address
|
|
inc esi
|
|
lods dword [esi]
|
|
add esi,2
|
|
cmp byte [esi],'('
|
|
jne invalid_argument
|
|
inc esi
|
|
cmp eax,0Fh
|
|
jbe reserved_word_used_as_symbol
|
|
mov edx,undefined_symbol
|
|
test byte [eax+8],1
|
|
jz addressing_space_unavailable
|
|
mov edx,symbol_out_of_scope
|
|
mov cx,[eax+16]
|
|
cmp cx,[current_pass]
|
|
jne addressing_space_unavailable
|
|
test byte [eax+9],4
|
|
jz invalid_use_of_symbol
|
|
mov ebx,eax
|
|
mov ax,[current_pass]
|
|
mov [ebx+18],ax
|
|
or byte [ebx+8],8
|
|
call store_label_reference
|
|
get_addressing_space:
|
|
mov ebx,[ebx]
|
|
get_data_address:
|
|
push ebx
|
|
cmp byte [esi],'.'
|
|
je invalid_value
|
|
or [operand_flags],1
|
|
call get_address_value
|
|
pop ebp
|
|
call calculate_relative_offset
|
|
cmp [next_pass_needed],0
|
|
jne data_address_type_ok
|
|
cmp [value_type],0
|
|
jne invalid_use_of_symbol
|
|
data_address_type_ok:
|
|
mov ebx,edi
|
|
xor ecx,ecx
|
|
add ebx,eax
|
|
adc edx,ecx
|
|
mov eax,ebx
|
|
sub eax,[ds:ebp+18h]
|
|
sbb edx,ecx
|
|
jnz bad_data_address
|
|
mov cl,[operand_size]
|
|
add eax,ecx
|
|
cmp eax,[ds:ebp+1Ch]
|
|
ja bad_data_address
|
|
clc
|
|
ret
|
|
addressing_space_unavailable:
|
|
cmp [error_line],0
|
|
jne get_data_address
|
|
push [current_line]
|
|
pop [error_line]
|
|
mov [error],edx
|
|
mov [error_info],eax
|
|
jmp get_data_address
|
|
bad_data_address:
|
|
call recoverable_overflow
|
|
stc
|
|
ret
|
|
get_data_offset:
|
|
cmp [output_format],2
|
|
jae invalid_operand
|
|
lods byte [esi]
|
|
cmp al,'('
|
|
jne invalid_argument
|
|
cmp byte [esi],'.'
|
|
je invalid_value
|
|
call get_dword_value
|
|
cmp [value_type],0
|
|
je data_offset_ok
|
|
call recoverable_invalid_address
|
|
data_offset_ok:
|
|
add eax,[code_start]
|
|
jc bad_data_address
|
|
mov ebx,eax
|
|
movzx ecx,[operand_size]
|
|
add eax,ecx
|
|
jc bad_data_address
|
|
mov edx,[addressing_space]
|
|
test byte [edx+0Ah],1
|
|
jnz data_offset_from_virtual
|
|
cmp eax,edi
|
|
ja bad_data_address
|
|
clc
|
|
ret
|
|
data_offset_from_virtual:
|
|
cmp eax,[undefined_data_end]
|
|
ja bad_data_address
|
|
clc
|
|
ret
|
|
|
|
store_directive:
|
|
cmp byte [esi],11h
|
|
je sized_store
|
|
lods byte [esi]
|
|
cmp al,'('
|
|
jne invalid_argument
|
|
call get_byte_value
|
|
xor edx,edx
|
|
movzx eax,al
|
|
mov [operand_size],1
|
|
jmp store_value_ok
|
|
sized_store:
|
|
or [operand_flags],1
|
|
call get_value
|
|
store_value_ok:
|
|
cmp [value_type],0
|
|
jne invalid_use_of_symbol
|
|
mov dword [value],eax
|
|
mov dword [value+4],edx
|
|
lods byte [esi]
|
|
cmp al,80h
|
|
jne invalid_argument
|
|
call get_data_point
|
|
jc instruction_assembled
|
|
push esi edi
|
|
mov esi,value
|
|
mov edi,ebx
|
|
rep movs byte [edi],[esi]
|
|
mov eax,edi
|
|
pop edi esi
|
|
cmp ebx,[undefined_data_end]
|
|
jae instruction_assembled
|
|
cmp eax,[undefined_data_start]
|
|
jbe instruction_assembled
|
|
mov [undefined_data_start],eax
|
|
jmp instruction_assembled
|
|
|
|
display_directive:
|
|
lods byte [esi]
|
|
cmp al,'('
|
|
jne invalid_argument
|
|
cmp byte [esi],0
|
|
jne display_byte
|
|
inc esi
|
|
lods dword [esi]
|
|
mov ecx,eax
|
|
push edi
|
|
mov edi,[tagged_blocks]
|
|
sub edi,8
|
|
sub edi,eax
|
|
cmp edi,[esp]
|
|
jbe out_of_memory
|
|
mov [tagged_blocks],edi
|
|
rep movs byte [edi],[esi]
|
|
stos dword [edi]
|
|
xor eax,eax
|
|
stos dword [edi]
|
|
pop edi
|
|
inc esi
|
|
jmp display_next
|
|
display_byte:
|
|
call get_byte_value
|
|
push edi
|
|
mov edi,[tagged_blocks]
|
|
sub edi,8+1
|
|
mov [tagged_blocks],edi
|
|
stos byte [edi]
|
|
mov eax,1
|
|
stos dword [edi]
|
|
dec eax
|
|
stos dword [edi]
|
|
pop edi
|
|
display_next:
|
|
cmp edi,[tagged_blocks]
|
|
ja out_of_memory
|
|
lods byte [esi]
|
|
cmp al,','
|
|
je display_directive
|
|
dec esi
|
|
jmp instruction_assembled
|
|
show_display_buffer:
|
|
mov eax,[tagged_blocks]
|
|
or eax,eax
|
|
jz display_done
|
|
mov esi,[labels_list]
|
|
cmp esi,eax
|
|
je display_done
|
|
display_messages:
|
|
sub esi,8
|
|
mov eax,[esi+4]
|
|
mov ecx,[esi]
|
|
sub esi,ecx
|
|
cmp eax,10h
|
|
je write_addressing_space
|
|
test eax,eax
|
|
jnz skip_block
|
|
push esi
|
|
call display_block
|
|
pop esi
|
|
skip_block:
|
|
cmp esi,[tagged_blocks]
|
|
jne display_messages
|
|
display_done:
|
|
ret
|
|
write_addressing_space:
|
|
mov ecx,[esi+20h]
|
|
jecxz skip_block
|
|
push esi
|
|
mov edi,[free_additional_memory]
|
|
mov esi,[output_file]
|
|
test esi,esi
|
|
jz addressing_space_written
|
|
xor ebx,ebx
|
|
copy_output_path:
|
|
lodsb
|
|
cmp edi,[structures_buffer]
|
|
jae out_of_memory
|
|
stosb
|
|
test al,al
|
|
jz output_path_copied
|
|
cmp al,'/'
|
|
je new_path_segment
|
|
cmp al,'\'
|
|
je new_path_segment
|
|
cmp al,'.'
|
|
jne copy_output_path
|
|
mov ebx,edi
|
|
jmp copy_output_path
|
|
new_path_segment:
|
|
xor ebx,ebx
|
|
jmp copy_output_path
|
|
output_path_copied:
|
|
test ebx,ebx
|
|
jnz append_extension
|
|
mov byte [edi-1],'.'
|
|
mov ebx,edi
|
|
append_extension:
|
|
mov edi,ebx
|
|
add ebx,ecx
|
|
inc ebx
|
|
cmp ebx,[structures_buffer]
|
|
jae out_of_memory
|
|
mov esi,[esp]
|
|
mov esi,[esi+18h]
|
|
sub esi,ecx
|
|
rep movs byte [edi],[esi]
|
|
xor al,al
|
|
stos byte [edi]
|
|
mov edx,[free_additional_memory]
|
|
call create
|
|
jc write_failed
|
|
mov esi,[esp]
|
|
mov edx,[esi+18h]
|
|
mov ecx,[esi+1Ch]
|
|
call write
|
|
jc write_failed
|
|
call close
|
|
addressing_space_written:
|
|
pop esi
|
|
jmp skip_block
|
|
|
|
times_directive:
|
|
lods byte [esi]
|
|
cmp al,'('
|
|
jne invalid_argument
|
|
cmp byte [esi],'.'
|
|
je invalid_value
|
|
call get_count_value
|
|
cmp eax,0
|
|
je zero_times
|
|
cmp byte [esi],':'
|
|
jne times_argument_ok
|
|
inc esi
|
|
times_argument_ok:
|
|
push [counter]
|
|
push [counter_limit]
|
|
mov [counter_limit],eax
|
|
mov [counter],1
|
|
times_loop:
|
|
mov eax,esp
|
|
sub eax,[stack_limit]
|
|
cmp eax,100h
|
|
jb stack_overflow
|
|
push esi
|
|
or [prefix_flags],1
|
|
call continue_line
|
|
mov eax,[counter_limit]
|
|
cmp [counter],eax
|
|
je times_done
|
|
inc [counter]
|
|
pop esi
|
|
jmp times_loop
|
|
times_done:
|
|
pop eax
|
|
pop [counter_limit]
|
|
pop [counter]
|
|
jmp instruction_assembled
|
|
zero_times:
|
|
call skip_symbol
|
|
jnc zero_times
|
|
jmp instruction_assembled
|
|
|
|
virtual_directive:
|
|
lods byte [esi]
|
|
cmp al,'('
|
|
je continue_virtual_area
|
|
cmp al,80h
|
|
jne virtual_at_current
|
|
lods byte [esi]
|
|
cmp al,'('
|
|
jne invalid_argument
|
|
cmp byte [esi],'.'
|
|
je invalid_value
|
|
call get_address_value
|
|
mov ebp,[address_symbol]
|
|
or bh,bh
|
|
setnz ch
|
|
jmp set_virtual
|
|
virtual_at_current:
|
|
dec esi
|
|
virtual_fallback:
|
|
mov ebp,[addressing_space]
|
|
mov al,[ds:ebp+9]
|
|
mov [value_type],al
|
|
mov eax,edi
|
|
xor edx,edx
|
|
xor cl,cl
|
|
sub eax,[ds:ebp]
|
|
sbb edx,[ds:ebp+4]
|
|
sbb cl,[ds:ebp+8]
|
|
mov [address_sign],cl
|
|
mov bx,[ds:ebp+10h]
|
|
mov cx,[ds:ebp+10h+2]
|
|
xchg bh,bl
|
|
xchg ch,cl
|
|
mov ebp,[ds:ebp+14h]
|
|
set_virtual:
|
|
xchg bl,bh
|
|
xchg cl,ch
|
|
shl ecx,16
|
|
mov cx,bx
|
|
push ecx eax
|
|
mov ebx,[addressing_space]
|
|
test byte [ebx+0Ah],1
|
|
jnz non_virtual_end_ok
|
|
mov eax,edi
|
|
xchg eax,[undefined_data_end]
|
|
cmp eax,edi
|
|
je non_virtual_end_ok
|
|
mov [undefined_data_start],edi
|
|
non_virtual_end_ok:
|
|
call allocate_virtual_structure_data
|
|
call init_addressing_space
|
|
or byte [ebx+0Ah],1
|
|
cmp byte [esi],86h
|
|
jne addressing_space_extension_ok
|
|
cmp word [esi+1],'('
|
|
jne invalid_argument
|
|
mov ecx,[esi+3]
|
|
add esi,3+4
|
|
add [ebx+18h],ecx
|
|
mov [ebx+20h],ecx
|
|
or byte [ebx+0Ah],2
|
|
push ebx
|
|
mov ebx,characters
|
|
get_extension:
|
|
lods byte [esi]
|
|
stos byte [edi]
|
|
xlat byte [ebx]
|
|
test al,al
|
|
jz invalid_argument
|
|
loop get_extension
|
|
inc esi
|
|
pop ebx
|
|
addressing_space_extension_ok:
|
|
pop eax
|
|
mov cl,[address_sign]
|
|
not eax
|
|
not edx
|
|
not cl
|
|
add eax,1
|
|
adc edx,0
|
|
adc cl,0
|
|
add eax,edi
|
|
adc edx,0
|
|
adc cl,0
|
|
mov [ebx],eax
|
|
mov [ebx+4],edx
|
|
mov [ebx+8],cl
|
|
pop dword [ebx+10h]
|
|
mov [ebx+14h],ebp
|
|
mov al,[value_type]
|
|
test al,1
|
|
jnz invalid_use_of_symbol
|
|
mov [ebx+9],al
|
|
jmp instruction_assembled
|
|
allocate_structure_data:
|
|
mov ebx,[structures_buffer]
|
|
sub ebx,18h
|
|
cmp ebx,[free_additional_memory]
|
|
jb out_of_memory
|
|
mov [structures_buffer],ebx
|
|
ret
|
|
find_structure_data:
|
|
mov ebx,[structures_buffer]
|
|
scan_structures:
|
|
cmp ebx,[additional_memory_end]
|
|
je no_such_structure
|
|
cmp ax,[ebx]
|
|
je structure_data_found
|
|
add ebx,18h
|
|
jmp scan_structures
|
|
structure_data_found:
|
|
ret
|
|
no_such_structure:
|
|
stc
|
|
ret
|
|
allocate_virtual_structure_data:
|
|
call allocate_structure_data
|
|
mov word [ebx],virtual_directive-instruction_handler
|
|
mov ecx,[addressing_space]
|
|
mov [ebx+12],ecx
|
|
mov [ebx+8],edi
|
|
mov ecx,[current_line]
|
|
mov [ebx+4],ecx
|
|
mov ebx,[addressing_space]
|
|
mov eax,edi
|
|
sub eax,[ebx+18h]
|
|
mov [ebx+1Ch],eax
|
|
ret
|
|
continue_virtual_area:
|
|
cmp byte [esi],11h
|
|
jne invalid_argument
|
|
cmp byte [esi+1+4],')'
|
|
jne invalid_argument
|
|
inc esi
|
|
lods dword [esi]
|
|
inc esi
|
|
cmp eax,0Fh
|
|
jbe reserved_word_used_as_symbol
|
|
mov edx,undefined_symbol
|
|
test byte [eax+8],1
|
|
jz virtual_area_unavailable
|
|
mov edx,symbol_out_of_scope
|
|
mov cx,[eax+16]
|
|
cmp cx,[current_pass]
|
|
jne virtual_area_unavailable
|
|
mov edx,invalid_use_of_symbol
|
|
test byte [eax+9],4
|
|
jz virtual_area_unavailable
|
|
mov ebx,eax
|
|
mov ax,[current_pass]
|
|
mov [ebx+18],ax
|
|
or byte [ebx+8],8
|
|
call store_label_reference
|
|
mov ebx,[ebx]
|
|
test byte [ebx+0Ah],4
|
|
jz virtual_area_unavailable
|
|
and byte [ebx+0Ah],not 4
|
|
mov edx,ebx
|
|
call allocate_virtual_structure_data
|
|
mov [addressing_space],edx
|
|
push esi
|
|
mov esi,[edx+18h]
|
|
mov ecx,[edx+1Ch]
|
|
mov eax,[edx+20h]
|
|
sub esi,eax
|
|
add ecx,eax
|
|
lea eax,[edi+ecx]
|
|
cmp eax,[tagged_blocks]
|
|
jae out_of_memory
|
|
mov eax,esi
|
|
sub eax,edi
|
|
sub [edx+18h],eax
|
|
sub [edx],eax
|
|
sbb dword [edx+4],0
|
|
sbb byte [edx+8],0
|
|
mov al,cl
|
|
shr ecx,2
|
|
rep movs dword [edi],[esi]
|
|
mov cl,al
|
|
and cl,11b
|
|
rep movs byte [edi],[esi]
|
|
pop esi
|
|
jmp instruction_assembled
|
|
virtual_area_unavailable:
|
|
cmp [error_line],0
|
|
jne virtual_fallback
|
|
push [current_line]
|
|
pop [error_line]
|
|
mov [error],edx
|
|
mov [error_info],eax
|
|
jmp virtual_fallback
|
|
end_virtual:
|
|
call find_structure_data
|
|
jc unexpected_instruction
|
|
push ebx
|
|
call close_virtual_addressing_space
|
|
pop ebx
|
|
mov eax,[ebx+12]
|
|
mov [addressing_space],eax
|
|
mov edi,[ebx+8]
|
|
remove_structure_data:
|
|
push esi edi
|
|
mov ecx,ebx
|
|
sub ecx,[structures_buffer]
|
|
shr ecx,2
|
|
lea esi,[ebx-4]
|
|
lea edi,[esi+18h]
|
|
std
|
|
rep movs dword [edi],[esi]
|
|
cld
|
|
add [structures_buffer],18h
|
|
pop edi esi
|
|
ret
|
|
close_virtual_addressing_space:
|
|
mov ebx,[addressing_space]
|
|
mov eax,edi
|
|
sub eax,[ebx+18h]
|
|
mov [ebx+1Ch],eax
|
|
add eax,[ebx+20h]
|
|
test byte [ebx+0Ah],2
|
|
jz addressing_space_closed
|
|
or byte [ebx+0Ah],4
|
|
push esi edi ecx edx
|
|
mov ecx,eax
|
|
mov eax,[tagged_blocks]
|
|
mov dword [eax-4],11h
|
|
mov dword [eax-8],ecx
|
|
sub eax,8
|
|
sub eax,ecx
|
|
mov [tagged_blocks],eax
|
|
lea edi,[eax+ecx-1]
|
|
add eax,[ebx+20h]
|
|
xchg eax,[ebx+18h]
|
|
sub eax,[ebx+20h]
|
|
lea esi,[eax+ecx-1]
|
|
mov eax,edi
|
|
sub eax,esi
|
|
std
|
|
shr ecx,1
|
|
jnc virtual_byte_ok
|
|
movs byte [edi],[esi]
|
|
virtual_byte_ok:
|
|
dec esi
|
|
dec edi
|
|
shr ecx,1
|
|
jnc virtual_word_ok
|
|
movs word [edi],[esi]
|
|
virtual_word_ok:
|
|
sub esi,2
|
|
sub edi,2
|
|
rep movs dword [edi],[esi]
|
|
cld
|
|
xor edx,edx
|
|
add [ebx],eax
|
|
adc dword [ebx+4],edx
|
|
adc byte [ebx+8],dl
|
|
pop edx ecx edi esi
|
|
addressing_space_closed:
|
|
ret
|
|
repeat_directive:
|
|
test [prefix_flags],1
|
|
jnz unexpected_instruction
|
|
lods byte [esi]
|
|
cmp al,'('
|
|
jne invalid_argument
|
|
cmp byte [esi],'.'
|
|
je invalid_value
|
|
call get_count_value
|
|
cmp eax,0
|
|
je zero_repeat
|
|
call allocate_structure_data
|
|
mov word [ebx],repeat_directive-instruction_handler
|
|
xchg eax,[counter_limit]
|
|
mov [ebx+10h],eax
|
|
mov eax,1
|
|
xchg eax,[counter]
|
|
mov [ebx+14h],eax
|
|
mov [ebx+8],esi
|
|
mov eax,[current_line]
|
|
mov [ebx+4],eax
|
|
jmp instruction_assembled
|
|
end_repeat:
|
|
test [prefix_flags],1
|
|
jnz unexpected_instruction
|
|
call find_structure_data
|
|
jc unexpected_instruction
|
|
mov eax,[counter_limit]
|
|
inc [counter]
|
|
cmp [counter],eax
|
|
jbe continue_repeating
|
|
stop_repeat:
|
|
mov eax,[ebx+10h]
|
|
mov [counter_limit],eax
|
|
mov eax,[ebx+14h]
|
|
mov [counter],eax
|
|
call remove_structure_data
|
|
jmp instruction_assembled
|
|
continue_repeating:
|
|
mov esi,[ebx+8]
|
|
jmp instruction_assembled
|
|
zero_repeat:
|
|
mov al,[esi]
|
|
or al,al
|
|
jz missing_end_directive
|
|
cmp al,0Fh
|
|
jne extra_characters_on_line
|
|
call find_end_repeat
|
|
jmp instruction_assembled
|
|
find_end_repeat:
|
|
call find_structure_end
|
|
cmp ax,repeat_directive-instruction_handler
|
|
jne unexpected_instruction
|
|
ret
|
|
while_directive:
|
|
test [prefix_flags],1
|
|
jnz unexpected_instruction
|
|
call allocate_structure_data
|
|
mov word [ebx],while_directive-instruction_handler
|
|
mov eax,1
|
|
xchg eax,[counter]
|
|
mov [ebx+10h],eax
|
|
mov [ebx+8],esi
|
|
mov eax,[current_line]
|
|
mov [ebx+4],eax
|
|
do_while:
|
|
push ebx
|
|
call calculate_logical_expression
|
|
or al,al
|
|
jnz while_true
|
|
mov al,[esi]
|
|
or al,al
|
|
jz missing_end_directive
|
|
cmp al,0Fh
|
|
jne extra_characters_on_line
|
|
stop_while:
|
|
call find_end_while
|
|
pop ebx
|
|
mov eax,[ebx+10h]
|
|
mov [counter],eax
|
|
call remove_structure_data
|
|
jmp instruction_assembled
|
|
while_true:
|
|
pop ebx
|
|
jmp instruction_assembled
|
|
end_while:
|
|
test [prefix_flags],1
|
|
jnz unexpected_instruction
|
|
call find_structure_data
|
|
jc unexpected_instruction
|
|
mov eax,[ebx+4]
|
|
mov [current_line],eax
|
|
inc [counter]
|
|
jz too_many_repeats
|
|
mov esi,[ebx+8]
|
|
jmp do_while
|
|
find_end_while:
|
|
call find_structure_end
|
|
cmp ax,while_directive-instruction_handler
|
|
jne unexpected_instruction
|
|
ret
|
|
if_directive:
|
|
test [prefix_flags],1
|
|
jnz unexpected_instruction
|
|
call calculate_logical_expression
|
|
mov dl,al
|
|
mov al,[esi]
|
|
or al,al
|
|
jz missing_end_directive
|
|
cmp al,0Fh
|
|
jne extra_characters_on_line
|
|
or dl,dl
|
|
jnz if_true
|
|
call find_else
|
|
jc instruction_assembled
|
|
mov al,[esi]
|
|
cmp al,1
|
|
jne else_true
|
|
cmp word [esi+1],if_directive-instruction_handler
|
|
jne else_true
|
|
add esi,4
|
|
jmp if_directive
|
|
if_true:
|
|
xor al,al
|
|
make_if_structure:
|
|
call allocate_structure_data
|
|
mov word [ebx],if_directive-instruction_handler
|
|
mov byte [ebx+2],al
|
|
mov eax,[current_line]
|
|
mov [ebx+4],eax
|
|
jmp instruction_assembled
|
|
else_true:
|
|
or al,al
|
|
jz missing_end_directive
|
|
cmp al,0Fh
|
|
jne extra_characters_on_line
|
|
or al,-1
|
|
jmp make_if_structure
|
|
else_directive:
|
|
test [prefix_flags],1
|
|
jnz unexpected_instruction
|
|
mov ax,if_directive-instruction_handler
|
|
call find_structure_data
|
|
jc unexpected_instruction
|
|
cmp byte [ebx+2],0
|
|
jne unexpected_instruction
|
|
found_else:
|
|
mov al,[esi]
|
|
cmp al,1
|
|
jne skip_else
|
|
cmp word [esi+1],if_directive-instruction_handler
|
|
jne skip_else
|
|
add esi,4
|
|
call find_else
|
|
jnc found_else
|
|
call remove_structure_data
|
|
jmp instruction_assembled
|
|
skip_else:
|
|
or al,al
|
|
jz missing_end_directive
|
|
cmp al,0Fh
|
|
jne extra_characters_on_line
|
|
call find_end_if
|
|
call remove_structure_data
|
|
jmp instruction_assembled
|
|
end_if:
|
|
test [prefix_flags],1
|
|
jnz unexpected_instruction
|
|
call find_structure_data
|
|
jc unexpected_instruction
|
|
call remove_structure_data
|
|
jmp instruction_assembled
|
|
find_else:
|
|
call find_structure_end
|
|
cmp ax,else_directive-instruction_handler
|
|
je else_found
|
|
cmp ax,if_directive-instruction_handler
|
|
jne unexpected_instruction
|
|
stc
|
|
ret
|
|
else_found:
|
|
clc
|
|
ret
|
|
find_end_if:
|
|
call find_structure_end
|
|
cmp ax,if_directive-instruction_handler
|
|
jne unexpected_instruction
|
|
ret
|
|
find_structure_end:
|
|
push [error_line]
|
|
mov eax,[current_line]
|
|
mov [error_line],eax
|
|
find_end_directive:
|
|
call skip_symbol
|
|
jnc find_end_directive
|
|
lods byte [esi]
|
|
cmp al,0Fh
|
|
jne no_end_directive
|
|
lods dword [esi]
|
|
mov [current_line],eax
|
|
skip_labels:
|
|
cmp byte [esi],2
|
|
jne labels_ok
|
|
add esi,6
|
|
jmp skip_labels
|
|
labels_ok:
|
|
cmp byte [esi],1
|
|
jne find_end_directive
|
|
mov ax,[esi+1]
|
|
cmp ax,prefix_instruction-instruction_handler
|
|
je find_end_directive
|
|
add esi,4
|
|
cmp ax,repeat_directive-instruction_handler
|
|
je skip_repeat
|
|
cmp ax,while_directive-instruction_handler
|
|
je skip_while
|
|
cmp ax,if_directive-instruction_handler
|
|
je skip_if
|
|
cmp ax,else_directive-instruction_handler
|
|
je structure_end
|
|
cmp ax,end_directive-instruction_handler
|
|
jne find_end_directive
|
|
cmp byte [esi],1
|
|
jne find_end_directive
|
|
mov ax,[esi+1]
|
|
add esi,4
|
|
cmp ax,repeat_directive-instruction_handler
|
|
je structure_end
|
|
cmp ax,while_directive-instruction_handler
|
|
je structure_end
|
|
cmp ax,if_directive-instruction_handler
|
|
jne find_end_directive
|
|
structure_end:
|
|
pop [error_line]
|
|
ret
|
|
no_end_directive:
|
|
mov eax,[error_line]
|
|
mov [current_line],eax
|
|
jmp missing_end_directive
|
|
skip_repeat:
|
|
call find_end_repeat
|
|
jmp find_end_directive
|
|
skip_while:
|
|
call find_end_while
|
|
jmp find_end_directive
|
|
skip_if:
|
|
call skip_if_block
|
|
jmp find_end_directive
|
|
skip_if_block:
|
|
call find_else
|
|
jc if_block_skipped
|
|
cmp byte [esi],1
|
|
jne skip_after_else
|
|
cmp word [esi+1],if_directive-instruction_handler
|
|
jne skip_after_else
|
|
add esi,4
|
|
jmp skip_if_block
|
|
skip_after_else:
|
|
call find_end_if
|
|
if_block_skipped:
|
|
ret
|
|
end_directive:
|
|
lods byte [esi]
|
|
cmp al,1
|
|
jne invalid_argument
|
|
lods word [esi]
|
|
inc esi
|
|
cmp ax,virtual_directive-instruction_handler
|
|
je end_virtual
|
|
cmp ax,repeat_directive-instruction_handler
|
|
je end_repeat
|
|
cmp ax,while_directive-instruction_handler
|
|
je end_while
|
|
cmp ax,if_directive-instruction_handler
|
|
je end_if
|
|
cmp ax,data_directive-instruction_handler
|
|
je end_data
|
|
jmp invalid_argument
|
|
break_directive:
|
|
mov ebx,[structures_buffer]
|
|
mov al,[esi]
|
|
or al,al
|
|
jz find_breakable_structure
|
|
cmp al,0Fh
|
|
jne extra_characters_on_line
|
|
find_breakable_structure:
|
|
cmp ebx,[additional_memory_end]
|
|
je unexpected_instruction
|
|
mov ax,[ebx]
|
|
cmp ax,repeat_directive-instruction_handler
|
|
je break_repeat
|
|
cmp ax,while_directive-instruction_handler
|
|
je break_while
|
|
cmp ax,if_directive-instruction_handler
|
|
je break_if
|
|
add ebx,18h
|
|
jmp find_breakable_structure
|
|
break_if:
|
|
push [current_line]
|
|
mov eax,[ebx+4]
|
|
mov [current_line],eax
|
|
call remove_structure_data
|
|
call skip_if_block
|
|
pop [current_line]
|
|
mov ebx,[structures_buffer]
|
|
jmp find_breakable_structure
|
|
break_repeat:
|
|
push ebx
|
|
call find_end_repeat
|
|
pop ebx
|
|
jmp stop_repeat
|
|
break_while:
|
|
push ebx
|
|
jmp stop_while
|
|
|
|
define_data:
|
|
cmp edi,[tagged_blocks]
|
|
jae out_of_memory
|
|
cmp byte [esi],'('
|
|
jne simple_data_value
|
|
mov ebx,esi
|
|
inc esi
|
|
call skip_expression
|
|
xchg esi,ebx
|
|
cmp byte [ebx],81h
|
|
jne simple_data_value
|
|
inc esi
|
|
call get_count_value
|
|
inc esi
|
|
or eax,eax
|
|
jz duplicate_zero_times
|
|
cmp byte [esi],91h
|
|
jne duplicate_single_data_value
|
|
inc esi
|
|
duplicate_data:
|
|
push eax esi
|
|
duplicated_values:
|
|
cmp edi,[tagged_blocks]
|
|
jae out_of_memory
|
|
clc
|
|
call near dword [esp+8]
|
|
lods byte [esi]
|
|
cmp al,','
|
|
je duplicated_values
|
|
cmp al,92h
|
|
jne invalid_argument
|
|
pop ebx eax
|
|
dec eax
|
|
jz data_defined
|
|
mov esi,ebx
|
|
jmp duplicate_data
|
|
duplicate_single_data_value:
|
|
cmp edi,[tagged_blocks]
|
|
jae out_of_memory
|
|
push eax esi
|
|
clc
|
|
call near dword [esp+8]
|
|
pop ebx eax
|
|
dec eax
|
|
jz data_defined
|
|
mov esi,ebx
|
|
jmp duplicate_single_data_value
|
|
duplicate_zero_times:
|
|
cmp byte [esi],91h
|
|
jne skip_single_data_value
|
|
inc esi
|
|
skip_data_value:
|
|
call skip_symbol
|
|
jc invalid_argument
|
|
cmp byte [esi],92h
|
|
jne skip_data_value
|
|
inc esi
|
|
jmp data_defined
|
|
skip_single_data_value:
|
|
call skip_symbol
|
|
jmp data_defined
|
|
simple_data_value:
|
|
cmp edi,[tagged_blocks]
|
|
jae out_of_memory
|
|
clc
|
|
call near dword [esp]
|
|
data_defined:
|
|
lods byte [esi]
|
|
cmp al,','
|
|
je define_data
|
|
dec esi
|
|
stc
|
|
ret
|
|
data_bytes:
|
|
call define_data
|
|
jc instruction_assembled
|
|
lods byte [esi]
|
|
cmp al,'('
|
|
je get_byte
|
|
cmp al,'?'
|
|
jne invalid_argument
|
|
mov eax,edi
|
|
mov byte [edi],0
|
|
inc edi
|
|
jmp undefined_data
|
|
get_byte:
|
|
cmp byte [esi],0
|
|
je get_string
|
|
call get_byte_value
|
|
stos byte [edi]
|
|
ret
|
|
get_string:
|
|
inc esi
|
|
lods dword [esi]
|
|
mov ecx,eax
|
|
lea eax,[edi+ecx]
|
|
cmp eax,[tagged_blocks]
|
|
ja out_of_memory
|
|
rep movs byte [edi],[esi]
|
|
inc esi
|
|
ret
|
|
undefined_data:
|
|
mov ebp,[addressing_space]
|
|
test byte [ds:ebp+0Ah],1
|
|
jz mark_undefined_data
|
|
ret
|
|
mark_undefined_data:
|
|
cmp eax,[undefined_data_end]
|
|
je undefined_data_ok
|
|
mov [undefined_data_start],eax
|
|
undefined_data_ok:
|
|
mov [undefined_data_end],edi
|
|
ret
|
|
data_unicode:
|
|
or [base_code],-1
|
|
jmp define_words
|
|
data_words:
|
|
mov [base_code],0
|
|
define_words:
|
|
call define_data
|
|
jc instruction_assembled
|
|
lods byte [esi]
|
|
cmp al,'('
|
|
je get_word
|
|
cmp al,'?'
|
|
jne invalid_argument
|
|
mov eax,edi
|
|
and word [edi],0
|
|
scas word [edi]
|
|
jmp undefined_data
|
|
ret
|
|
get_word:
|
|
cmp [base_code],0
|
|
je word_data_value
|
|
cmp byte [esi],0
|
|
je word_string
|
|
word_data_value:
|
|
call get_word_value
|
|
call mark_relocation
|
|
stos word [edi]
|
|
ret
|
|
word_string:
|
|
inc esi
|
|
lods dword [esi]
|
|
mov ecx,eax
|
|
jecxz word_string_ok
|
|
lea eax,[edi+ecx*2]
|
|
cmp eax,[tagged_blocks]
|
|
ja out_of_memory
|
|
xor ah,ah
|
|
copy_word_string:
|
|
lods byte [esi]
|
|
stos word [edi]
|
|
loop copy_word_string
|
|
word_string_ok:
|
|
inc esi
|
|
ret
|
|
data_dwords:
|
|
call define_data
|
|
jc instruction_assembled
|
|
lods byte [esi]
|
|
cmp al,'('
|
|
je get_dword
|
|
cmp al,'?'
|
|
jne invalid_argument
|
|
mov eax,edi
|
|
and dword [edi],0
|
|
scas dword [edi]
|
|
jmp undefined_data
|
|
get_dword:
|
|
push esi
|
|
call get_dword_value
|
|
pop ebx
|
|
cmp byte [esi],':'
|
|
je complex_dword
|
|
call mark_relocation
|
|
stos dword [edi]
|
|
ret
|
|
complex_dword:
|
|
mov esi,ebx
|
|
cmp byte [esi],'.'
|
|
je invalid_value
|
|
call get_word_value
|
|
push eax
|
|
inc esi
|
|
lods byte [esi]
|
|
cmp al,'('
|
|
jne invalid_operand
|
|
mov al,[value_type]
|
|
push eax
|
|
cmp byte [esi],'.'
|
|
je invalid_value
|
|
call get_word_value
|
|
call mark_relocation
|
|
stos word [edi]
|
|
pop eax
|
|
mov [value_type],al
|
|
pop eax
|
|
call mark_relocation
|
|
stos word [edi]
|
|
ret
|
|
data_pwords:
|
|
call define_data
|
|
jc instruction_assembled
|
|
lods byte [esi]
|
|
cmp al,'('
|
|
je get_pword
|
|
cmp al,'?'
|
|
jne invalid_argument
|
|
mov eax,edi
|
|
and dword [edi],0
|
|
scas dword [edi]
|
|
and word [edi],0
|
|
scas word [edi]
|
|
jmp undefined_data
|
|
get_pword:
|
|
push esi
|
|
call get_pword_value
|
|
pop ebx
|
|
cmp byte [esi],':'
|
|
je complex_pword
|
|
call mark_relocation
|
|
stos dword [edi]
|
|
mov ax,dx
|
|
stos word [edi]
|
|
ret
|
|
complex_pword:
|
|
mov esi,ebx
|
|
cmp byte [esi],'.'
|
|
je invalid_value
|
|
call get_word_value
|
|
push eax
|
|
inc esi
|
|
lods byte [esi]
|
|
cmp al,'('
|
|
jne invalid_operand
|
|
mov al,[value_type]
|
|
push eax
|
|
cmp byte [esi],'.'
|
|
je invalid_value
|
|
call get_dword_value
|
|
call mark_relocation
|
|
stos dword [edi]
|
|
pop eax
|
|
mov [value_type],al
|
|
pop eax
|
|
call mark_relocation
|
|
stos word [edi]
|
|
ret
|
|
data_qwords:
|
|
call define_data
|
|
jc instruction_assembled
|
|
lods byte [esi]
|
|
cmp al,'('
|
|
je get_qword
|
|
cmp al,'?'
|
|
jne invalid_argument
|
|
mov eax,edi
|
|
and dword [edi],0
|
|
scas dword [edi]
|
|
and dword [edi],0
|
|
scas dword [edi]
|
|
jmp undefined_data
|
|
get_qword:
|
|
call get_qword_value
|
|
call mark_relocation
|
|
stos dword [edi]
|
|
mov eax,edx
|
|
stos dword [edi]
|
|
ret
|
|
data_twords:
|
|
call define_data
|
|
jc instruction_assembled
|
|
lods byte [esi]
|
|
cmp al,'('
|
|
je get_tword
|
|
cmp al,'?'
|
|
jne invalid_argument
|
|
mov eax,edi
|
|
and dword [edi],0
|
|
scas dword [edi]
|
|
and dword [edi],0
|
|
scas dword [edi]
|
|
and word [edi],0
|
|
scas word [edi]
|
|
jmp undefined_data
|
|
get_tword:
|
|
cmp byte [esi],'.'
|
|
jne complex_tword
|
|
inc esi
|
|
cmp word [esi+8],8000h
|
|
je fp_zero_tword
|
|
mov eax,[esi]
|
|
stos dword [edi]
|
|
mov eax,[esi+4]
|
|
stos dword [edi]
|
|
mov ax,[esi+8]
|
|
add ax,3FFFh
|
|
jo value_out_of_range
|
|
cmp ax,7FFFh
|
|
jge value_out_of_range
|
|
cmp ax,0
|
|
jg tword_exp_ok
|
|
mov cx,ax
|
|
neg cx
|
|
inc cx
|
|
cmp cx,64
|
|
jae value_out_of_range
|
|
cmp cx,32
|
|
ja large_shift
|
|
mov eax,[esi]
|
|
mov edx,[esi+4]
|
|
mov ebx,edx
|
|
shr edx,cl
|
|
shrd eax,ebx,cl
|
|
jmp tword_mantissa_shift_done
|
|
large_shift:
|
|
sub cx,32
|
|
xor edx,edx
|
|
mov eax,[esi+4]
|
|
shr eax,cl
|
|
tword_mantissa_shift_done:
|
|
jnc store_shifted_mantissa
|
|
add eax,1
|
|
adc edx,0
|
|
store_shifted_mantissa:
|
|
mov [edi-8],eax
|
|
mov [edi-4],edx
|
|
xor ax,ax
|
|
test edx,1 shl 31
|
|
jz tword_exp_ok
|
|
inc ax
|
|
tword_exp_ok:
|
|
mov bl,[esi+11]
|
|
shl bx,15
|
|
or ax,bx
|
|
stos word [edi]
|
|
add esi,13
|
|
ret
|
|
fp_zero_tword:
|
|
xor eax,eax
|
|
stos dword [edi]
|
|
stos dword [edi]
|
|
mov al,[esi+11]
|
|
shl ax,15
|
|
stos word [edi]
|
|
add esi,13
|
|
ret
|
|
complex_tword:
|
|
call get_word_value
|
|
push eax
|
|
cmp byte [esi],':'
|
|
jne invalid_operand
|
|
inc esi
|
|
lods byte [esi]
|
|
cmp al,'('
|
|
jne invalid_operand
|
|
mov al,[value_type]
|
|
push eax
|
|
cmp byte [esi],'.'
|
|
je invalid_value
|
|
call get_qword_value
|
|
call mark_relocation
|
|
stos dword [edi]
|
|
mov eax,edx
|
|
stos dword [edi]
|
|
pop eax
|
|
mov [value_type],al
|
|
pop eax
|
|
call mark_relocation
|
|
stos word [edi]
|
|
ret
|
|
data_file:
|
|
lods word [esi]
|
|
cmp ax,'('
|
|
jne invalid_argument
|
|
add esi,4
|
|
call open_binary_file
|
|
mov eax,[esi-4]
|
|
lea esi,[esi+eax+1]
|
|
mov al,2
|
|
xor edx,edx
|
|
call lseek
|
|
push eax
|
|
xor edx,edx
|
|
cmp byte [esi],':'
|
|
jne position_ok
|
|
inc esi
|
|
cmp byte [esi],'('
|
|
jne invalid_argument
|
|
inc esi
|
|
cmp byte [esi],'.'
|
|
je invalid_value
|
|
push ebx
|
|
call get_count_value
|
|
pop ebx
|
|
mov edx,eax
|
|
sub [esp],edx
|
|
jc value_out_of_range
|
|
position_ok:
|
|
cmp byte [esi],','
|
|
jne size_ok
|
|
inc esi
|
|
cmp byte [esi],'('
|
|
jne invalid_argument
|
|
inc esi
|
|
cmp byte [esi],'.'
|
|
je invalid_value
|
|
push ebx edx
|
|
call get_count_value
|
|
pop edx ebx
|
|
cmp eax,[esp]
|
|
ja value_out_of_range
|
|
mov [esp],eax
|
|
size_ok:
|
|
xor al,al
|
|
call lseek
|
|
pop ecx
|
|
mov edx,edi
|
|
add edi,ecx
|
|
jc out_of_memory
|
|
cmp edi,[tagged_blocks]
|
|
ja out_of_memory
|
|
call read
|
|
jc error_reading_file
|
|
call close
|
|
lods byte [esi]
|
|
cmp al,','
|
|
je data_file
|
|
dec esi
|
|
jmp instruction_assembled
|
|
open_binary_file:
|
|
push esi
|
|
push edi
|
|
mov eax,[current_line]
|
|
find_current_source_path:
|
|
mov esi,[eax]
|
|
test byte [eax+7],80h
|
|
jz get_current_path
|
|
mov eax,[eax+8]
|
|
jmp find_current_source_path
|
|
get_current_path:
|
|
lodsb
|
|
stosb
|
|
or al,al
|
|
jnz get_current_path
|
|
cut_current_path:
|
|
cmp edi,[esp]
|
|
je current_path_ok
|
|
cmp byte [edi-1],'\'
|
|
je current_path_ok
|
|
cmp byte [edi-1],'/'
|
|
je current_path_ok
|
|
dec edi
|
|
jmp cut_current_path
|
|
current_path_ok:
|
|
mov esi,[esp+4]
|
|
call expand_path
|
|
pop edx
|
|
mov esi,edx
|
|
call open
|
|
jnc file_opened
|
|
mov edx,[include_paths]
|
|
search_in_include_paths:
|
|
push edx esi
|
|
mov edi,esi
|
|
mov esi,[esp+4]
|
|
call get_include_directory
|
|
mov [esp+4],esi
|
|
mov esi,[esp+8]
|
|
call expand_path
|
|
pop edx
|
|
mov esi,edx
|
|
call open
|
|
pop edx
|
|
jnc file_opened
|
|
cmp byte [edx],0
|
|
jne search_in_include_paths
|
|
mov edi,esi
|
|
mov esi,[esp]
|
|
push edi
|
|
call expand_path
|
|
pop edx
|
|
mov esi,edx
|
|
call open
|
|
jc file_not_found
|
|
file_opened:
|
|
mov edi,esi
|
|
pop esi
|
|
ret
|
|
reserve_bytes:
|
|
lods byte [esi]
|
|
cmp al,'('
|
|
jne invalid_argument
|
|
cmp byte [esi],'.'
|
|
je invalid_value
|
|
call get_count_value
|
|
mov ecx,eax
|
|
mov edx,ecx
|
|
add edx,edi
|
|
jc out_of_memory
|
|
cmp edx,[tagged_blocks]
|
|
ja out_of_memory
|
|
push edi
|
|
cmp [next_pass_needed],0
|
|
je zero_bytes
|
|
add edi,ecx
|
|
jmp reserved_data
|
|
zero_bytes:
|
|
xor eax,eax
|
|
shr ecx,1
|
|
jnc bytes_stosb_ok
|
|
stos byte [edi]
|
|
bytes_stosb_ok:
|
|
shr ecx,1
|
|
jnc bytes_stosw_ok
|
|
stos word [edi]
|
|
bytes_stosw_ok:
|
|
rep stos dword [edi]
|
|
reserved_data:
|
|
pop eax
|
|
call undefined_data
|
|
jmp instruction_assembled
|
|
reserve_words:
|
|
lods byte [esi]
|
|
cmp al,'('
|
|
jne invalid_argument
|
|
cmp byte [esi],'.'
|
|
je invalid_value
|
|
call get_count_value
|
|
mov ecx,eax
|
|
mov edx,ecx
|
|
shl edx,1
|
|
jc out_of_memory
|
|
add edx,edi
|
|
jc out_of_memory
|
|
cmp edx,[tagged_blocks]
|
|
ja out_of_memory
|
|
push edi
|
|
cmp [next_pass_needed],0
|
|
je zero_words
|
|
lea edi,[edi+ecx*2]
|
|
jmp reserved_data
|
|
zero_words:
|
|
xor eax,eax
|
|
shr ecx,1
|
|
jnc words_stosw_ok
|
|
stos word [edi]
|
|
words_stosw_ok:
|
|
rep stos dword [edi]
|
|
jmp reserved_data
|
|
reserve_dwords:
|
|
lods byte [esi]
|
|
cmp al,'('
|
|
jne invalid_argument
|
|
cmp byte [esi],'.'
|
|
je invalid_value
|
|
call get_count_value
|
|
mov ecx,eax
|
|
mov edx,ecx
|
|
shl edx,1
|
|
jc out_of_memory
|
|
shl edx,1
|
|
jc out_of_memory
|
|
add edx,edi
|
|
jc out_of_memory
|
|
cmp edx,[tagged_blocks]
|
|
ja out_of_memory
|
|
push edi
|
|
cmp [next_pass_needed],0
|
|
je zero_dwords
|
|
lea edi,[edi+ecx*4]
|
|
jmp reserved_data
|
|
zero_dwords:
|
|
xor eax,eax
|
|
rep stos dword [edi]
|
|
jmp reserved_data
|
|
reserve_pwords:
|
|
lods byte [esi]
|
|
cmp al,'('
|
|
jne invalid_argument
|
|
cmp byte [esi],'.'
|
|
je invalid_value
|
|
call get_count_value
|
|
mov ecx,eax
|
|
shl ecx,1
|
|
jc out_of_memory
|
|
add ecx,eax
|
|
mov edx,ecx
|
|
shl edx,1
|
|
jc out_of_memory
|
|
add edx,edi
|
|
jc out_of_memory
|
|
cmp edx,[tagged_blocks]
|
|
ja out_of_memory
|
|
push edi
|
|
cmp [next_pass_needed],0
|
|
je zero_words
|
|
lea edi,[edi+ecx*2]
|
|
jmp reserved_data
|
|
reserve_qwords:
|
|
lods byte [esi]
|
|
cmp al,'('
|
|
jne invalid_argument
|
|
cmp byte [esi],'.'
|
|
je invalid_value
|
|
call get_count_value
|
|
mov ecx,eax
|
|
shl ecx,1
|
|
jc out_of_memory
|
|
mov edx,ecx
|
|
shl edx,1
|
|
jc out_of_memory
|
|
shl edx,1
|
|
jc out_of_memory
|
|
add edx,edi
|
|
jc out_of_memory
|
|
cmp edx,[tagged_blocks]
|
|
ja out_of_memory
|
|
push edi
|
|
cmp [next_pass_needed],0
|
|
je zero_dwords
|
|
lea edi,[edi+ecx*4]
|
|
jmp reserved_data
|
|
reserve_twords:
|
|
lods byte [esi]
|
|
cmp al,'('
|
|
jne invalid_argument
|
|
cmp byte [esi],'.'
|
|
je invalid_value
|
|
call get_count_value
|
|
mov ecx,eax
|
|
shl ecx,2
|
|
jc out_of_memory
|
|
add ecx,eax
|
|
mov edx,ecx
|
|
shl edx,1
|
|
jc out_of_memory
|
|
add edx,edi
|
|
jc out_of_memory
|
|
cmp edx,[tagged_blocks]
|
|
ja out_of_memory
|
|
push edi
|
|
cmp [next_pass_needed],0
|
|
je zero_words
|
|
lea edi,[edi+ecx*2]
|
|
jmp reserved_data
|
|
align_directive:
|
|
lods byte [esi]
|
|
cmp al,'('
|
|
jne invalid_argument
|
|
cmp byte [esi],'.'
|
|
je invalid_value
|
|
call get_count_value
|
|
mov edx,eax
|
|
dec edx
|
|
test eax,edx
|
|
jnz invalid_align_value
|
|
or eax,eax
|
|
jz invalid_align_value
|
|
cmp eax,1
|
|
je instruction_assembled
|
|
mov ecx,edi
|
|
mov ebp,[addressing_space]
|
|
sub ecx,[ds:ebp]
|
|
cmp dword [ds:ebp+10h],0
|
|
jne section_not_aligned_enough
|
|
cmp byte [ds:ebp+9],0
|
|
je make_alignment
|
|
cmp [output_format],3
|
|
je pe_alignment
|
|
cmp [output_format],5
|
|
jne object_alignment
|
|
test [format_flags],1
|
|
jnz pe_alignment
|
|
object_alignment:
|
|
mov ebx,[ds:ebp+14h]
|
|
cmp byte [ebx],0
|
|
jne section_not_aligned_enough
|
|
cmp eax,[ebx+10h]
|
|
jbe make_alignment
|
|
jmp section_not_aligned_enough
|
|
pe_alignment:
|
|
cmp eax,1000h
|
|
ja section_not_aligned_enough
|
|
make_alignment:
|
|
dec eax
|
|
and ecx,eax
|
|
jz instruction_assembled
|
|
neg ecx
|
|
add ecx,eax
|
|
inc ecx
|
|
mov edx,ecx
|
|
add edx,edi
|
|
jc out_of_memory
|
|
cmp edx,[tagged_blocks]
|
|
ja out_of_memory
|
|
push edi
|
|
cmp [next_pass_needed],0
|
|
je nops
|
|
add edi,ecx
|
|
jmp reserved_data
|
|
invalid_align_value:
|
|
cmp [error_line],0
|
|
jne instruction_assembled
|
|
mov eax,[current_line]
|
|
mov [error_line],eax
|
|
mov [error],invalid_value
|
|
jmp instruction_assembled
|
|
nops:
|
|
mov eax,90909090h
|
|
shr ecx,1
|
|
jnc nops_stosb_ok
|
|
stos byte [edi]
|
|
nops_stosb_ok:
|
|
shr ecx,1
|
|
jnc nops_stosw_ok
|
|
stos word [edi]
|
|
nops_stosw_ok:
|
|
rep stos dword [edi]
|
|
jmp reserved_data
|
|
err_directive:
|
|
mov al,[esi]
|
|
cmp al,0Fh
|
|
je invoked_error
|
|
or al,al
|
|
jz invoked_error
|
|
jmp extra_characters_on_line
|
|
assert_directive:
|
|
call calculate_logical_expression
|
|
or al,al
|
|
jnz instruction_assembled
|
|
cmp [error_line],0
|
|
jne instruction_assembled
|
|
mov eax,[current_line]
|
|
mov [error_line],eax
|
|
mov [error],assertion_failed
|
|
jmp instruction_assembled
|