kolibrios-fun/programs/develop/fasm/trunk/assemble.inc
heavyiron 53cca077c5 fasm 1.71.13, proc32.inc and struct.inc from fasm 1.71.13
git-svn-id: svn://kolibrios.org@4039 a494cfbc-eb01-0410-851d-a64ba20cac60
2013-10-16 08:12:09 +00:00

2049 lines
38 KiB
PHP

; flat assembler core
; Copyright (c) 1999-2013, 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 [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],20h
sub ebx,8+20h
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
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
mov [prefixed_instruction],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
mov edx,[eax+8]
push edx
cmp [current_pass],0
je get_constant_value
test dl,4
jnz get_constant_value
mov cx,[current_pass]
cmp cx,[eax+16]
je get_constant_value
or dl,4
mov [eax+8],dl
get_constant_value:
push eax
mov al,byte [esi-1]
push eax
or [size_override],-1
call get_value
pop ebx
mov ch,bl
pop ebx
pop ecx
test cl,4
jnz constant_referencing_mode_ok
and byte [ebx+8],not 4
constant_referencing_mode_ok:
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 [size_override],0
; mov [operand_prefix],0
; mov [opcode_prefix],0
and dword [operand_size],0
; mov [rex_prefix],0
; mov [vex_required],0
; mov [vex_register],0
; mov [immediate_size],0
and dword [rex_prefix],0
call instruction_handler
instruction_handler:
movzx ebx,word [esi]
mov al,[esi+2]
add esi,3
add [esp],ebx
ret
instruction_assembled:
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:
mov ebx,[addressing_space]
mov ecx,edi
sub ecx,[ebx+18h]
mov [ebx+1Ch],ecx
lods byte [esi]
cmp al,'('
jne invalid_argument
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
cmp [symbols_file],0
je get_addressing_space
cmp [next_pass_needed],0
jne get_addressing_space
call store_label_reference
get_addressing_space:
mov ebx,[ebx]
get_data_address:
push ebx
cmp byte [esi],'.'
je invalid_value
or [size_override],-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
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 [size_override],-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
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
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,100h
jc stack_overflow
cmp eax,[stack_limit]
jb stack_overflow
push esi
or [prefixed_instruction],-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,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
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
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
call init_addressing_space
or byte [ebx+0Ah],1
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
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
test byte [ebx+0Ah],2
jz addressing_space_closed
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]
xchg eax,[ebx+18h]
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:
cmp [prefixed_instruction],0
jne 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:
cmp [prefixed_instruction],0
jne 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:
cmp [prefixed_instruction],0
jne 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:
cmp [prefixed_instruction],0
jne 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:
cmp [prefixed_instruction],0
jne 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:
cmp [prefixed_instruction],0
jne 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:
cmp [prefixed_instruction],0
jne 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
data_bytes:
call define_data
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
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],'{'
jne duplicate_single_data_value
inc esi
duplicate_data:
push eax esi
duplicated_values:
cmp edi,[tagged_blocks]
jae out_of_memory
call near dword [esp+8]
lods byte [esi]
cmp al,','
je duplicated_values
cmp al,'}'
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
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],'{'
jne skip_single_data_value
inc esi
skip_data_value:
call skip_symbol
jc invalid_argument
cmp byte [esi],'}'
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
call near dword [esp]
data_defined:
lods byte [esi]
cmp al,','
je define_data
dec esi
add esp,4
jmp instruction_assembled
data_unicode:
or [base_code],-1
jmp define_words
data_words:
mov [base_code],0
define_words:
call define_data
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
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
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
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
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
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