add flat assembler toolchain
This commit is contained in:
3383
toolchain/fasmg.kl0e/source/assembler.inc
Normal file
3383
toolchain/fasmg.kl0e/source/assembler.inc
Normal file
File diff suppressed because it is too large
Load Diff
3293
toolchain/fasmg.kl0e/source/calm.inc
Normal file
3293
toolchain/fasmg.kl0e/source/calm.inc
Normal file
File diff suppressed because it is too large
Load Diff
669
toolchain/fasmg.kl0e/source/conditions.inc
Normal file
669
toolchain/fasmg.kl0e/source/conditions.inc
Normal file
@ -0,0 +1,669 @@
|
||||
|
||||
COND_NEGATED = 1 ; only with COND_EVALUATE
|
||||
COND_TRUE = 1 ; only with COND_DETERMINED
|
||||
COND_EVALUATE = 2
|
||||
COND_DETERMINED = 4
|
||||
|
||||
get_condition_value:
|
||||
; in:
|
||||
; esi = pointer into preprocessed line or the last embedded line
|
||||
; out:
|
||||
; esi = pointer advanced past the processed line
|
||||
; al = logical value
|
||||
mov ebx,[condition_stack_base]
|
||||
mov [condition_stack],ebx
|
||||
mov byte [ebx],COND_EVALUATE
|
||||
get_logical_value:
|
||||
call peek_at_constituent_value
|
||||
cmp al,'~'
|
||||
jne negation_registered
|
||||
and [current_constituent],0
|
||||
mov ebx,[condition_stack]
|
||||
mov al,[ebx]
|
||||
test byte [ebx],COND_EVALUATE
|
||||
jz get_logical_value
|
||||
xor byte [ebx],COND_NEGATED
|
||||
jmp get_logical_value
|
||||
negation_registered:
|
||||
call parse_logical_value
|
||||
setnc dh
|
||||
mov dl,al
|
||||
jecxz get_logical_operator
|
||||
mov ebx,[condition_stack]
|
||||
lea eax,[ebx+ecx+1]
|
||||
cmp eax,[condition_stack_end]
|
||||
jbe condition_stack_ready
|
||||
push ecx edx
|
||||
mov ecx,eax
|
||||
mov eax,[condition_stack_base]
|
||||
sub ecx,eax
|
||||
sub ebx,eax
|
||||
call grow_stack
|
||||
mov [condition_stack_base],eax
|
||||
add ebx,eax
|
||||
mov [condition_stack],ebx
|
||||
add eax,ecx
|
||||
mov [condition_stack_end],eax
|
||||
pop edx ecx
|
||||
condition_stack_ready:
|
||||
xor al,al
|
||||
test byte [ebx],COND_EVALUATE
|
||||
jz store_opening_parentheses
|
||||
or al,COND_EVALUATE
|
||||
store_opening_parentheses:
|
||||
inc ebx
|
||||
mov [ebx],al
|
||||
loop store_opening_parentheses
|
||||
mov [condition_stack],ebx
|
||||
cmp dx,'~'
|
||||
je get_logical_value
|
||||
get_logical_operator:
|
||||
call peek_at_constituent_value
|
||||
jc end_of_logical_expression
|
||||
cmp al,')'
|
||||
je close_logical_subexpression
|
||||
cmp al,'|'
|
||||
je logical_or
|
||||
cmp al,'&'
|
||||
jne end_of_logical_expression
|
||||
logical_and:
|
||||
and [current_constituent],0
|
||||
mov ebx,[condition_stack]
|
||||
mov al,[ebx]
|
||||
test al,COND_EVALUATE
|
||||
jnz evaluate_logical_and
|
||||
test al,COND_DETERMINED
|
||||
jz get_logical_value
|
||||
test al,COND_TRUE
|
||||
jz determined_false
|
||||
jmp continue_evaluation
|
||||
evaluate_logical_and:
|
||||
test al,COND_NEGATED
|
||||
jnz evaluate_negated_logical_and
|
||||
call evaluate_logical_value
|
||||
mov ebx,[condition_stack]
|
||||
test al,al
|
||||
jnz continue_evaluation
|
||||
determined_false:
|
||||
mov byte [ebx],COND_DETERMINED
|
||||
jmp get_logical_value
|
||||
evaluate_negated_logical_and:
|
||||
call evaluate_logical_value
|
||||
mov ebx,[condition_stack]
|
||||
test al,al
|
||||
jnz determined_false
|
||||
continue_evaluation:
|
||||
mov byte [ebx],COND_EVALUATE
|
||||
jmp get_logical_value
|
||||
logical_or:
|
||||
and [current_constituent],0
|
||||
mov ebx,[condition_stack]
|
||||
mov al,[ebx]
|
||||
test al,COND_EVALUATE
|
||||
jnz evaluate_logical_or
|
||||
test al,COND_DETERMINED
|
||||
jz get_logical_value
|
||||
test al,COND_TRUE
|
||||
jnz determined_true
|
||||
jmp continue_evaluation
|
||||
evaluate_logical_or:
|
||||
test al,COND_NEGATED
|
||||
jnz evaluate_negated_logical_or
|
||||
call evaluate_logical_value
|
||||
mov ebx,[condition_stack]
|
||||
test al,al
|
||||
jnz determined_true
|
||||
jmp continue_evaluation
|
||||
evaluate_negated_logical_or:
|
||||
call evaluate_logical_value
|
||||
mov ebx,[condition_stack]
|
||||
test al,al
|
||||
jnz continue_evaluation
|
||||
determined_true:
|
||||
mov byte [ebx],COND_DETERMINED + COND_TRUE
|
||||
jmp get_logical_value
|
||||
close_logical_subexpression:
|
||||
and [current_constituent],0
|
||||
mov ebx,[condition_stack]
|
||||
cmp ebx,[condition_stack_base]
|
||||
je excess_parenthesis
|
||||
mov al,[ebx]
|
||||
dec ebx
|
||||
mov [condition_stack],ebx
|
||||
test al,COND_DETERMINED
|
||||
jnz subexpression_determined
|
||||
cmp al,COND_EVALUATE + COND_NEGATED
|
||||
jne get_logical_operator
|
||||
test byte [ebx],COND_EVALUATE
|
||||
jz get_logical_operator
|
||||
xor byte [ebx],COND_NEGATED
|
||||
jmp get_logical_operator
|
||||
subexpression_determined:
|
||||
test al,COND_TRUE
|
||||
jnz subexpression_determined_true
|
||||
mov [comparator],evaluated_false
|
||||
jmp get_logical_operator
|
||||
subexpression_determined_true:
|
||||
mov [comparator],evaluated_true
|
||||
jmp get_logical_operator
|
||||
end_of_logical_expression:
|
||||
mov ebx,[condition_stack]
|
||||
cmp ebx,[condition_stack_base]
|
||||
jne missing_parenthesis
|
||||
mov al,[ebx]
|
||||
test al,COND_DETERMINED
|
||||
jnz condition_determined
|
||||
test al,COND_NEGATED
|
||||
jz evaluate_logical_value
|
||||
call evaluate_logical_value
|
||||
test al,al
|
||||
setz al
|
||||
retn
|
||||
condition_determined:
|
||||
and al,COND_TRUE
|
||||
retn
|
||||
excess_parenthesis:
|
||||
mov edx,_excess_closing_parenthesis
|
||||
call register_error
|
||||
jmp unknown_condition
|
||||
missing_parenthesis:
|
||||
mov edx,_missing_closing_parenthesis
|
||||
call register_error
|
||||
unknown_condition:
|
||||
xor al,al
|
||||
retn
|
||||
|
||||
parse_logical_value:
|
||||
; in:
|
||||
; esi = pointer into preprocessed line or the last embedded line
|
||||
; out:
|
||||
; [comparator] - evaluating routine
|
||||
; [expression_workspace.memory_start] - parsed argument sequences
|
||||
; [expression_end] - end of the parsed argument sequences
|
||||
; esi = pointer advanced past the parsed value
|
||||
; al = special character that follows parsed value, zero if no more symbols in line
|
||||
; ecx = number of parentheses opened before the value that did not get closed
|
||||
; cf set if value was empty
|
||||
mov edi,[expression_workspace.memory_start]
|
||||
xor eax,eax
|
||||
mov [comparator],eax
|
||||
or [leave_opening_parentheses],1
|
||||
call parse_expression
|
||||
mov [initial_parentheses],ecx
|
||||
mov [expression_end],edi
|
||||
call peek_at_constituent_value
|
||||
jc end_of_line
|
||||
cmp al,'&'
|
||||
je end_of_logical_value
|
||||
cmp al,'|'
|
||||
je end_of_logical_value
|
||||
cmp al,'~'
|
||||
je end_of_logical_value
|
||||
cmp al,')'
|
||||
je end_of_logical_value
|
||||
cmp al,1Ah
|
||||
je identify_comparator
|
||||
cmp al,'='
|
||||
je parse_equal
|
||||
cmp al,'<'
|
||||
je parse_less
|
||||
cmp al,'>'
|
||||
je parse_greater
|
||||
jmp end_of_logical_value
|
||||
identify_comparator:
|
||||
test edx,edx
|
||||
jz end_of_logical_value
|
||||
cmp [edx+ValueDefinition.type],VALTYPE_NATIVE_COMPARATOR
|
||||
jne end_of_logical_value
|
||||
and [current_constituent],0
|
||||
mov eax,[edx+ValueDefinition.value]
|
||||
jmp set_comparator
|
||||
parse_less:
|
||||
and [current_constituent],0
|
||||
call warp_to_next_symbol
|
||||
jc parse_less_than
|
||||
test ecx,ecx
|
||||
jnz parse_less_than
|
||||
call peek_at_constituent_value
|
||||
jc parse_less_than
|
||||
cmp al,'='
|
||||
je parse_less_or_equal
|
||||
cmp al,'>'
|
||||
je parse_not_equal
|
||||
parse_less_than:
|
||||
mov eax,check_if_less
|
||||
jmp set_comparator
|
||||
parse_less_or_equal:
|
||||
and [current_constituent],0
|
||||
mov eax,check_if_not_greater
|
||||
jmp set_comparator
|
||||
parse_not_equal:
|
||||
and [current_constituent],0
|
||||
mov eax,check_if_not_equal
|
||||
jmp set_comparator
|
||||
parse_greater:
|
||||
and [current_constituent],0
|
||||
call warp_to_next_symbol
|
||||
jc parse_greater_than
|
||||
test ecx,ecx
|
||||
jnz parse_greater_than
|
||||
call peek_at_constituent_value
|
||||
jc parse_greater_than
|
||||
cmp al,'='
|
||||
je parse_greater_or_equal
|
||||
parse_greater_than:
|
||||
mov eax,check_if_greater
|
||||
jmp set_comparator
|
||||
parse_greater_or_equal:
|
||||
and [current_constituent],0
|
||||
mov eax,check_if_not_less
|
||||
jmp set_comparator
|
||||
parse_equal:
|
||||
and [current_constituent],0
|
||||
mov eax,check_if_equal
|
||||
set_comparator:
|
||||
mov edi,[expression_end]
|
||||
mov [comparator],eax
|
||||
and [leave_opening_parentheses],0
|
||||
call parse_expression
|
||||
mov [expression_end],edi
|
||||
call peek_at_constituent_value
|
||||
jnc end_of_logical_value
|
||||
end_of_line:
|
||||
xor al,al
|
||||
end_of_logical_value:
|
||||
mov ecx,[initial_parentheses]
|
||||
cmp [comparator],0
|
||||
jnz logical_value_not_empty
|
||||
mov [comparator],check_if_not_zero
|
||||
mov ebx,[expression_workspace.memory_start]
|
||||
cmp dword [ebx],0
|
||||
jne logical_value_not_empty
|
||||
stc
|
||||
retn
|
||||
logical_value_not_empty:
|
||||
clc
|
||||
retn
|
||||
|
||||
evaluate_logical_value:
|
||||
; in:
|
||||
; [comparator] - evaluating routine
|
||||
; [expression_workspace.memory_start] - parsed argument sequences
|
||||
; out: al = logical value
|
||||
; note: evaluates value prepared by previous call to parse_logical_value
|
||||
; preserves: esi
|
||||
push esi
|
||||
mov esi,[expression_workspace.memory_start]
|
||||
jmp [comparator]
|
||||
evaluated_false:
|
||||
pop esi
|
||||
xor al,al
|
||||
retn
|
||||
evaluated_true:
|
||||
pop esi
|
||||
mov al,1
|
||||
retn
|
||||
|
||||
evaluate_stored_logical_value:
|
||||
; in: esi - pointer to evaluating routine followed by parsed argument sequences
|
||||
; out: al = logical value
|
||||
; preserves: esi
|
||||
push esi
|
||||
lodsd
|
||||
jmp eax
|
||||
|
||||
invalid_logical_value:
|
||||
mov edx,_invalid_expression
|
||||
call register_error
|
||||
jmp evaluated_false
|
||||
|
||||
check_if_equal:
|
||||
call get_difference_signum
|
||||
test al,al
|
||||
jz evaluated_true
|
||||
jmp evaluated_false
|
||||
check_if_not_equal:
|
||||
call get_difference_signum
|
||||
test al,al
|
||||
jnz evaluated_true
|
||||
jmp evaluated_false
|
||||
check_if_less:
|
||||
call get_difference_signum
|
||||
cmp al,0
|
||||
jl evaluated_true
|
||||
jmp evaluated_false
|
||||
check_if_not_less:
|
||||
call get_difference_signum
|
||||
cmp al,0
|
||||
jnl evaluated_true
|
||||
jmp evaluated_false
|
||||
check_if_greater:
|
||||
call get_difference_signum
|
||||
cmp al,0
|
||||
jg evaluated_true
|
||||
jmp evaluated_false
|
||||
check_if_not_greater:
|
||||
call get_difference_signum
|
||||
cmp al,0
|
||||
jng evaluated_true
|
||||
jmp evaluated_false
|
||||
get_difference_signum:
|
||||
mov edi,[calculation_workspace.memory_start]
|
||||
call calculate_parsed_expression
|
||||
jc signum_error
|
||||
call calculate_parsed_expression
|
||||
jc signum_error
|
||||
mov esi,subtraction_operator
|
||||
call calculate_parsed_expression
|
||||
call pop_terms
|
||||
mov eax,edi
|
||||
jnc check_difference_for_variable_terms
|
||||
signum_error:
|
||||
xor al,al
|
||||
retn
|
||||
check_difference_for_variable_terms:
|
||||
add eax,sizeof.ExpressionTerm
|
||||
cmp [eax+ExpressionTerm.attributes],0
|
||||
je difference_terms_ok
|
||||
cmp [eax+ExpressionTerm.metadata],0
|
||||
je check_difference_for_variable_terms
|
||||
mov edx,_values_not_comparable
|
||||
call register_error
|
||||
difference_terms_ok:
|
||||
cmp byte [edi+ExpressionTerm.attributes],EXPR_FLOAT
|
||||
je get_float_signum
|
||||
call get_numeric_term_value
|
||||
mov ecx,1
|
||||
call fit_value
|
||||
js signum_negative
|
||||
jc signum_positive
|
||||
xor al,al
|
||||
cmp [edi],al
|
||||
jne signum_positive
|
||||
retn
|
||||
get_float_signum:
|
||||
call get_term_value
|
||||
mov esi,edx
|
||||
call get_float_exponent
|
||||
jz signum_zero
|
||||
test [esi+FloatData.attributes],FLOAT_NEGATIVE
|
||||
jnz signum_negative
|
||||
signum_positive:
|
||||
mov al,1
|
||||
retn
|
||||
signum_negative:
|
||||
or al,-1
|
||||
retn
|
||||
signum_zero:
|
||||
xor al,al
|
||||
retn
|
||||
|
||||
check_if_not_zero:
|
||||
mov edi,[calculation_workspace.memory_start]
|
||||
call calculate_parsed_expression
|
||||
jc evaluated_false
|
||||
call pop_terms
|
||||
jc evaluated_false
|
||||
cmp byte [edi+ExpressionTerm.attributes],EXPR_FLOAT
|
||||
je check_if_not_zero_float
|
||||
call get_numeric_term_value
|
||||
mov ecx,1
|
||||
call fit_value
|
||||
js evaluated_true
|
||||
jc evaluated_true
|
||||
cmp byte [edi],0
|
||||
jne evaluated_true
|
||||
check_if_has_variable_terms:
|
||||
add edi,sizeof.ExpressionTerm
|
||||
cmp [edi+ExpressionTerm.attributes],0
|
||||
je evaluated_false
|
||||
cmp [edi+ExpressionTerm.metadata],0
|
||||
je check_if_has_variable_terms
|
||||
jmp evaluated_true
|
||||
check_if_not_zero_float:
|
||||
call get_term_value
|
||||
mov esi,edx
|
||||
call get_float_exponent
|
||||
jz check_if_has_variable_terms
|
||||
jmp evaluated_true
|
||||
|
||||
check_if_relative:
|
||||
mov edi,[calculation_workspace.memory_start]
|
||||
call calculate_parsed_expression
|
||||
jc evaluated_false
|
||||
call calculate_parsed_expression
|
||||
jc evaluated_false
|
||||
mov ebx,edi
|
||||
call pop_terms
|
||||
jc evaluated_false
|
||||
mov edx,edi
|
||||
call pop_terms
|
||||
jc evaluated_false
|
||||
cmp [edx+sizeof.ExpressionTerm+ExpressionTerm.attributes],0
|
||||
je check_difference_terms
|
||||
xchg edi,edx
|
||||
cmp [edx+sizeof.ExpressionTerm+ExpressionTerm.attributes],0
|
||||
je check_difference_terms
|
||||
mov esi,subtraction_operator
|
||||
mov edi,ebx
|
||||
call calculate_parsed_expression
|
||||
call pop_terms
|
||||
jc evaluated_false
|
||||
check_difference_terms:
|
||||
add edi,sizeof.ExpressionTerm
|
||||
cmp [edi+ExpressionTerm.attributes],0
|
||||
je evaluated_true
|
||||
cmp [edi+ExpressionTerm.metadata],0
|
||||
je check_difference_terms
|
||||
jmp evaluated_false
|
||||
undefined_condition:
|
||||
mov edx,_invalid_value
|
||||
call register_error
|
||||
jmp evaluated_false
|
||||
|
||||
check_if_type_equal:
|
||||
mov edi,[calculation_workspace.memory_start]
|
||||
call calculate_parsed_expression
|
||||
jc evaluated_false
|
||||
call pop_terms
|
||||
jc evaluated_false
|
||||
mov eax,[edi+ExpressionTerm.attributes]
|
||||
mov [result_type],al
|
||||
call calculate_parsed_expression
|
||||
jc evaluated_false
|
||||
call pop_terms
|
||||
jc evaluated_false
|
||||
mov eax,[edi+ExpressionTerm.attributes]
|
||||
cmp al,[result_type]
|
||||
je evaluated_true
|
||||
jmp evaluated_false
|
||||
|
||||
check_if_value_equal:
|
||||
mov edi,[calculation_workspace.memory_start]
|
||||
call calculate_parsed_expression
|
||||
jc evaluated_false
|
||||
mov ebx,edi
|
||||
call pop_terms
|
||||
jc evaluated_false
|
||||
mov eax,[edi+ExpressionTerm.attributes]
|
||||
mov [result_type],al
|
||||
mov edi,ebx
|
||||
call calculate_parsed_expression
|
||||
jc evaluated_false
|
||||
mov ebx,edi
|
||||
call pop_terms
|
||||
jc evaluated_false
|
||||
mov eax,[edi+ExpressionTerm.attributes]
|
||||
cmp al,[result_type]
|
||||
jne evaluated_false
|
||||
cmp al,EXPR_STRING
|
||||
jne compare_values_numerically
|
||||
call get_term_value
|
||||
mov ecx,[edx]
|
||||
call pop_terms
|
||||
call get_term_value
|
||||
cmp ecx,[edx]
|
||||
jne evaluated_false
|
||||
compare_values_numerically:
|
||||
mov esi,subtraction_operator
|
||||
mov edi,ebx
|
||||
call calculate_parsed_expression
|
||||
call pop_terms
|
||||
jc evaluated_false
|
||||
mov eax,edi
|
||||
check_if_terms_equal:
|
||||
add eax,sizeof.ExpressionTerm
|
||||
cmp [eax+ExpressionTerm.attributes],0
|
||||
je check_if_constant_term_equal
|
||||
cmp [eax+ExpressionTerm.metadata],0
|
||||
je check_if_terms_equal
|
||||
jmp evaluated_false
|
||||
check_if_constant_term_equal:
|
||||
cmp byte [edi+ExpressionTerm.attributes],EXPR_FLOAT
|
||||
je check_if_float_equal
|
||||
call get_numeric_term_value
|
||||
xor ecx,ecx
|
||||
xor edi,edi
|
||||
call fit_value
|
||||
jc evaluated_false
|
||||
jmp evaluated_true
|
||||
check_if_float_equal:
|
||||
call get_term_value
|
||||
mov esi,edx
|
||||
call get_float_exponent
|
||||
jnz evaluated_false
|
||||
jmp evaluated_true
|
||||
|
||||
check_if_defined:
|
||||
xor ecx,ecx
|
||||
jmp check_if_expression_defined
|
||||
check_if_defined_earlier:
|
||||
mov ecx,[current_pass]
|
||||
check_if_expression_defined:
|
||||
and [outer_expression],0
|
||||
and [defined_element],0
|
||||
lodsd
|
||||
test eax,eax
|
||||
jnz checked_expression_invalid
|
||||
check_expression_element:
|
||||
lodsd
|
||||
test eax,eax
|
||||
jz check_expression_end
|
||||
cmp al,EXPR_SYMBOL
|
||||
je check_if_subexpression_defined
|
||||
cmp al,EXPR_SYMBOL_VALUE
|
||||
je check_if_symbol_defined
|
||||
or [defined_element],1
|
||||
add esi,4
|
||||
cmp al,EXPR_NUMBER
|
||||
je check_expression_element
|
||||
cmp al,EXPR_STRING
|
||||
je check_expression_element
|
||||
cmp al,EXPR_FLOAT
|
||||
je check_expression_element
|
||||
cmp al,EXPR_OPERATOR
|
||||
je check_expression_element
|
||||
cmp al,EXPR_POLYNOMIAL
|
||||
je check_expression_element
|
||||
checked_expression_invalid:
|
||||
jmp invalid_logical_value
|
||||
check_expression_end:
|
||||
xor esi,esi
|
||||
xchg esi,[outer_expression]
|
||||
test esi,esi
|
||||
jnz check_expression_element
|
||||
jecxz checked_expression_defined
|
||||
cmp [defined_element],0
|
||||
je checked_expression_invalid
|
||||
checked_expression_defined:
|
||||
jmp evaluated_true
|
||||
check_if_symbol_defined:
|
||||
lodsd
|
||||
test eax,eax
|
||||
jz evaluated_false
|
||||
lodsd
|
||||
test eax,eax
|
||||
jz evaluated_false
|
||||
check_symbol_value:
|
||||
or [defined_element],1
|
||||
jecxz check_expression_element
|
||||
test [eax+ValueDefinition.flags],VAL_INTERNAL
|
||||
jnz check_expression_element
|
||||
cmp [eax+ValueDefinition.pass],ecx
|
||||
jne evaluated_false
|
||||
jmp check_expression_element
|
||||
check_if_subexpression_defined:
|
||||
mov ebx,[esi]
|
||||
test ebx,ebx
|
||||
jz evaluated_false
|
||||
add esi,4
|
||||
call get_available_value
|
||||
mov eax,edx
|
||||
test eax,eax
|
||||
jz evaluated_false
|
||||
cmp [eax+ValueDefinition.type],VALTYPE_SYMBOLIC
|
||||
jne check_symbol_value
|
||||
mov [outer_expression],esi
|
||||
push ecx
|
||||
call get_subexpression
|
||||
pop ecx
|
||||
jnc invalid_logical_value
|
||||
jmp check_expression_element
|
||||
get_subexpression:
|
||||
call clear_line_embeddings
|
||||
xor esi,esi
|
||||
xor ecx,ecx
|
||||
call embed_symbolic_value
|
||||
mov edi,[expression_workspace.memory_start]
|
||||
and [leave_opening_parentheses],0
|
||||
call parse_expression
|
||||
call get_constituent_value
|
||||
mov esi,[expression_workspace.memory_start]
|
||||
retn
|
||||
|
||||
check_if_used:
|
||||
lodsd
|
||||
test eax,eax
|
||||
jnz invalid_logical_value
|
||||
check_if_expression_is_used_symbol:
|
||||
lodsd
|
||||
cmp al,EXPR_SYMBOL
|
||||
je check_for_indirect_symbol
|
||||
cmp al,EXPR_SYMBOL_VALUE
|
||||
jne invalid_logical_value
|
||||
lodsd
|
||||
mov ebx,eax
|
||||
lodsd
|
||||
check_if_used_symbol:
|
||||
lodsd
|
||||
test eax,eax
|
||||
jnz invalid_logical_value
|
||||
test ebx,ebx
|
||||
jz evaluated_false
|
||||
mov ecx,[ebx+SymbolTree_Leaf.last_use_pass]
|
||||
jecxz symbol_predicted_unused
|
||||
mov eax,[current_pass]
|
||||
sub eax,ecx
|
||||
jz evaluated_true
|
||||
cmp eax,1
|
||||
ja symbol_predicted_unused
|
||||
symbol_predicted_used:
|
||||
or [ebx+SymbolTree_Leaf.flags],SYM_USAGE_PREDICTED + SYM_PREDICTED_USED
|
||||
jmp evaluated_true
|
||||
symbol_predicted_unused:
|
||||
mov al,[ebx+SymbolTree_Leaf.flags]
|
||||
or al,SYM_USAGE_PREDICTED
|
||||
and al,not SYM_PREDICTED_USED
|
||||
mov [ebx+SymbolTree_Leaf.flags],al
|
||||
jmp evaluated_false
|
||||
check_for_indirect_symbol:
|
||||
lodsd
|
||||
mov ebx,eax
|
||||
call get_available_value
|
||||
test edx,edx
|
||||
jz check_if_used_symbol
|
||||
cmp [edx+ValueDefinition.type],VALTYPE_SYMBOLIC
|
||||
jne check_if_used_symbol
|
||||
call get_subexpression
|
||||
jnc invalid_logical_value
|
||||
jmp check_if_expression_is_used_symbol
|
560
toolchain/fasmg.kl0e/source/console.inc
Normal file
560
toolchain/fasmg.kl0e/source/console.inc
Normal file
@ -0,0 +1,560 @@
|
||||
|
||||
display_string_data:
|
||||
; in:
|
||||
; edx - 32-bit length followed by string data
|
||||
; preserves: esi
|
||||
test [trace_mode],TRACE_DISPLAY
|
||||
jnz bypass_display_buffer
|
||||
cmp [next_pass_needed],0
|
||||
jne display_ok
|
||||
mov ecx,[edx]
|
||||
call reserve_display_buffer
|
||||
mov ebx,esi
|
||||
mov esi,edx
|
||||
lodsd
|
||||
mov ecx,eax
|
||||
rep movsb
|
||||
string_displayed:
|
||||
mov esi,ebx
|
||||
display_ok:
|
||||
retn
|
||||
bypass_display_buffer:
|
||||
mov ebx,esi
|
||||
mov esi,edx
|
||||
lodsd
|
||||
mov ecx,eax
|
||||
jecxz string_displayed
|
||||
call display_string
|
||||
jmp string_displayed
|
||||
reserve_display_buffer:
|
||||
mov edi,[display_data_length]
|
||||
add ecx,edi
|
||||
add edi,[display_buffer]
|
||||
mov [display_data_length],ecx
|
||||
cmp ecx,[display_buffer_length]
|
||||
jbe display_buffer_reserve_ok
|
||||
mov eax,[display_buffer]
|
||||
sub edi,eax
|
||||
push edx
|
||||
call grow_stack
|
||||
pop edx
|
||||
add edi,eax
|
||||
mov [display_buffer],eax
|
||||
mov [display_buffer_length],ecx
|
||||
display_buffer_reserve_ok:
|
||||
retn
|
||||
|
||||
display_single_byte_data:
|
||||
; in:
|
||||
; edx - 32-bit length followed by numeric data
|
||||
; preserves: esi
|
||||
test [trace_mode],TRACE_DISPLAY
|
||||
jnz byte_bypassing_display_buffer
|
||||
cmp [next_pass_needed],0
|
||||
jne display_ok
|
||||
mov ecx,1
|
||||
call reserve_display_buffer
|
||||
mov ecx,1
|
||||
call fit_value
|
||||
jc byte_out_of_range
|
||||
retn
|
||||
byte_bypassing_display_buffer:
|
||||
mov edi,displayed_byte
|
||||
mov ecx,1
|
||||
call fit_value
|
||||
jc byte_out_of_range
|
||||
mov ebx,esi
|
||||
mov esi,edi
|
||||
mov ecx,1
|
||||
call display_string
|
||||
jmp string_displayed
|
||||
byte_out_of_range:
|
||||
mov edx,_value_out_of_range
|
||||
call register_error
|
||||
retn
|
||||
|
||||
show_display_data:
|
||||
test [trace_mode],TRACE_DISPLAY
|
||||
jnz display_line_feed
|
||||
mov ecx,[display_data_length]
|
||||
jecxz display_data_shown
|
||||
mov esi,[display_buffer]
|
||||
call display_string
|
||||
display_line_feed:
|
||||
mov esi,_new_line
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
display_data_shown:
|
||||
retn
|
||||
|
||||
show_errors:
|
||||
mov esi,[first_error]
|
||||
display_error:
|
||||
test esi,esi
|
||||
jz display_data_shown
|
||||
push esi
|
||||
mov eax,[esi+sizeof.Error+SourceContext.number_of_entries]
|
||||
test eax,eax
|
||||
jz display_error_message
|
||||
lea ebx,[esi+sizeof.Error+sizeof.SourceContext]
|
||||
dec eax
|
||||
imul eax,sizeof.SourceEntry
|
||||
lea eax,[ebx+eax]
|
||||
mov [last_source_entry],eax
|
||||
test [trace_mode],TRACE_ERROR_STACK
|
||||
jnz show_source_context
|
||||
and [last_file_source_entry],0
|
||||
find_last_file_entry:
|
||||
cmp [eax+SourceEntry.type],SOURCE_FILE
|
||||
je last_file_entry_found
|
||||
cmp eax,ebx
|
||||
je show_source_context
|
||||
sub eax,sizeof.SourceEntry
|
||||
jmp find_last_file_entry
|
||||
last_file_entry_found:
|
||||
mov [last_file_source_entry],eax
|
||||
show_source_context:
|
||||
push ebx
|
||||
cmp [ebx+SourceEntry.type],SOURCE_MEMORY
|
||||
je display_memory_source
|
||||
cmp [ebx+SourceEntry.type],SOURCE_MACRO
|
||||
jne display_source_name
|
||||
mov esi,_macro_source
|
||||
test [ebx+SourceEntry.flags],SRCF_PREPROCESSED
|
||||
jz display_source_type
|
||||
mov esi,_preprocessed_source
|
||||
display_source_type:
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
display_source_name:
|
||||
mov esi,[ebx+SourceEntry.name]
|
||||
test esi,esi
|
||||
jz unnamed_source
|
||||
mov ecx,[ebx+SourceEntry.name_length]
|
||||
cmp ecx,-1
|
||||
je display_source_symbol
|
||||
call display_error_string
|
||||
jmp display_line_number
|
||||
display_source_symbol:
|
||||
xchg ebx,esi
|
||||
call show_symbol_name
|
||||
mov ebx,esi
|
||||
jmp display_line_number
|
||||
unnamed_source:
|
||||
mov esi,_unnamed_source
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
jmp display_line_number
|
||||
display_memory_source:
|
||||
mov esi,_memory_source
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
display_line_number:
|
||||
mov esi,_line_number_prefix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov eax,[ebx+SourceEntry.line_number]
|
||||
xor edx,edx
|
||||
call itoa
|
||||
call display_error_string
|
||||
mov esi,_line_number_suffix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
pop ebx
|
||||
mov esi,[esp]
|
||||
push ebx
|
||||
cmp [ebx+SourceEntry.line_number],0
|
||||
je skip_line_content
|
||||
test [trace_mode],TRACE_ERROR_STACK
|
||||
jnz show_source_line
|
||||
cmp ebx,[last_source_entry]
|
||||
je last_source_entry_line_content
|
||||
cmp ebx,[last_file_source_entry]
|
||||
je show_source_line
|
||||
skip_line_content:
|
||||
mov esi,_space
|
||||
next_source_entry:
|
||||
pop ebx
|
||||
find_next_source_entry:
|
||||
cmp ebx,[last_source_entry]
|
||||
je source_context_shown
|
||||
add ebx,sizeof.SourceEntry
|
||||
test [trace_mode],TRACE_ERROR_STACK
|
||||
jnz show_source_entry
|
||||
test [ebx+SourceEntry.flags],SRCF_PREPROCESSED
|
||||
jnz find_next_source_entry
|
||||
show_source_entry:
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
jmp show_source_context
|
||||
last_source_entry_line_content:
|
||||
test [esi+Error.flags],ERR_CUSTOM
|
||||
jnz skip_line_content
|
||||
show_source_line:
|
||||
cmp [ebx+SourceEntry.type],SOURCE_CALM
|
||||
je show_calm_source
|
||||
mov esi,_line_content_prefix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
call show_line_content
|
||||
mov esi,_new_line
|
||||
jmp next_source_entry
|
||||
show_calm_source:
|
||||
mov esi,_calm_source
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,_new_line
|
||||
jmp next_source_entry
|
||||
source_context_shown:
|
||||
mov esi,_new_line
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov ebx,[esp]
|
||||
test [ebx+Error.flags],ERR_CUSTOM
|
||||
jnz display_error_message
|
||||
cmp [ebx+Error.preprocessed_length],0
|
||||
je display_error_message
|
||||
mov esi,_preprocessed_text_prefix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,[ebx+Error.preprocessed_data]
|
||||
mov ecx,[ebx+Error.preprocessed_length]
|
||||
call show_preprocessed_line
|
||||
mov esi,_new_line
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
display_error_message:
|
||||
pop ebx
|
||||
call show_error_message
|
||||
mov esi,ebx
|
||||
next_error:
|
||||
mov esi,[esi+Error.next]
|
||||
jmp display_error
|
||||
|
||||
show_error_message:
|
||||
; in:
|
||||
; ebx - Error
|
||||
; preserves: ebx
|
||||
mov esi,_error_prefix
|
||||
test [ebx+Error.flags],ERR_CUSTOM
|
||||
jz display_error_prefix
|
||||
mov esi,_custom_error_prefix
|
||||
display_error_prefix:
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,[ebx+Error.message]
|
||||
test [ebx+Error.flags],ERR_CUSTOM
|
||||
jz format_error_message
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
finish_error_message:
|
||||
mov esi,_message_suffix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
retn
|
||||
format_error_message:
|
||||
mov edx,esi
|
||||
cut_error_message:
|
||||
lodsb
|
||||
test al,al
|
||||
jz show_error_message_segment
|
||||
cmp al,'%'
|
||||
jne cut_error_message
|
||||
show_error_message_segment:
|
||||
dec esi
|
||||
push esi
|
||||
xchg ecx,esi
|
||||
sub ecx,edx
|
||||
mov esi,edx
|
||||
call display_error_string
|
||||
pop esi
|
||||
lodsb
|
||||
test al,al
|
||||
jz finish_error_message
|
||||
lodsb
|
||||
cmp al,'s'
|
||||
je insert_string_into_error_message
|
||||
cmp al,'i'
|
||||
jne format_error_message
|
||||
push ebx
|
||||
mov ebx,[ebx+Error.symbol]
|
||||
mov ebx,[ebx+SymbolTree_Leaf.branch]
|
||||
call show_symbol_name
|
||||
pop ebx
|
||||
jmp format_error_message
|
||||
insert_string_into_error_message:
|
||||
push esi
|
||||
mov esi,[ebx+Error.symbol]
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
pop esi
|
||||
jmp format_error_message
|
||||
|
||||
show_symbol_name:
|
||||
; in:
|
||||
; ebx - SymbolTree_Foliage, may be null
|
||||
; preserves: esi
|
||||
test ebx,ebx
|
||||
jz symbol_name_shown
|
||||
mov edi,[identifier_workspace.memory_start]
|
||||
cmp [ebx+SymbolTree_Foliage.name_kind],NAME_NUMERIC
|
||||
je next_name_segment
|
||||
compose_symbol_name:
|
||||
mov ecx,[ebx+SymbolTree_Foliage.name_length]
|
||||
mov edx,identifier_workspace
|
||||
mov al,[ebx+SymbolTree_Foliage.name_kind]
|
||||
cmp al,NAME_CASESENSITIVE
|
||||
je name_segment_to_copy
|
||||
cmp al,NAME_ABSTRACT
|
||||
je name_segment_copied
|
||||
cmp al,NAME_NUMERIC
|
||||
je dot_label_name
|
||||
mov al,'?'
|
||||
stosb
|
||||
name_segment_to_copy:
|
||||
push ecx
|
||||
add ecx,2
|
||||
call reserve_workspace
|
||||
pop ecx
|
||||
mov edx,[ebx+SymbolTree_Foliage.name_data]
|
||||
copy_name_segment:
|
||||
jecxz name_segment_copied
|
||||
dec ecx
|
||||
mov al,[edx+ecx]
|
||||
stosb
|
||||
jmp copy_name_segment
|
||||
dot_label_name:
|
||||
push esi
|
||||
mov esi,[ebx+SymbolTree_Foliage.name_data]
|
||||
xor eax,eax
|
||||
read_dot_count:
|
||||
jecxz dot_count_read
|
||||
dec ecx
|
||||
shl eax,8
|
||||
mov al,[esi+ecx]
|
||||
jmp read_dot_count
|
||||
dot_count_read:
|
||||
pop esi
|
||||
push eax
|
||||
lea ecx,[eax+2]
|
||||
call reserve_workspace
|
||||
pop ecx
|
||||
mov al,'.'
|
||||
rep stosb
|
||||
name_segment_copied:
|
||||
mov edx,[ebx+SymbolTree_Foliage.root]
|
||||
mov ebx,[edx+SymbolTree_Root.parent_branch]
|
||||
test [edx+SymbolTree_Root.flags],NAMESPACE_LOCAL or NAMESPACE_CALM
|
||||
jnz mark_local_symbol_name
|
||||
test ebx,ebx
|
||||
jz symbol_name_ready
|
||||
next_name_segment:
|
||||
mov al,'.'
|
||||
stosb
|
||||
jmp compose_symbol_name
|
||||
mark_local_symbol_name:
|
||||
mov al,':'
|
||||
stosb
|
||||
test [edx+SymbolTree_Root.flags],NAMESPACE_CALM
|
||||
jz symbol_name_ready
|
||||
mov eax,[ebx+SymbolTree_Foliage.name_data]
|
||||
mov ebx,[eax+SymbolTree_Leaf.branch]
|
||||
test ebx,ebx
|
||||
jnz compose_symbol_name
|
||||
symbol_name_ready:
|
||||
mov ebx,[identifier_workspace.memory_start]
|
||||
mov ecx,edi
|
||||
sub ecx,ebx
|
||||
jz symbol_name_shown
|
||||
push esi
|
||||
mov esi,ebx
|
||||
reverse_composed_name:
|
||||
dec edi
|
||||
cmp ebx,edi
|
||||
jae show_composed_name
|
||||
mov al,[ebx]
|
||||
xchg al,[edi]
|
||||
mov [ebx],al
|
||||
inc ebx
|
||||
jmp reverse_composed_name
|
||||
show_composed_name:
|
||||
call display_error_string
|
||||
pop esi
|
||||
symbol_name_shown:
|
||||
retn
|
||||
|
||||
show_line_content:
|
||||
; in:
|
||||
; ebx - SourceEntry
|
||||
cmp [ebx+SourceEntry.type],SOURCE_MACRO
|
||||
je show_line_from_macro
|
||||
mov esi,[ebx+SourceEntry.text]
|
||||
add esi,[ebx+SourceEntry.line_offset]
|
||||
mov ecx,[ebx+SourceEntry.number_of_attached_lines]
|
||||
inc ecx
|
||||
mov [number_of_lines],ecx
|
||||
show_token:
|
||||
mov al,[esi]
|
||||
test al,al
|
||||
jz line_content_shown
|
||||
cmp al,0Ah
|
||||
je line_content_shown
|
||||
cmp al,1Ah
|
||||
je show_name_token
|
||||
cmp al,22h
|
||||
je show_string_token
|
||||
cmp al,27h
|
||||
je show_string_token
|
||||
cmp al,'\'
|
||||
jne show_basic_token
|
||||
cmp byte [esi+1],0Ah
|
||||
jne show_basic_token
|
||||
dec [number_of_lines]
|
||||
jnz show_attached_line
|
||||
show_basic_token:
|
||||
mov ecx,1
|
||||
call display_error_string
|
||||
inc esi
|
||||
jmp show_token
|
||||
show_name_token:
|
||||
add esi,1+4
|
||||
mov ecx,[esi-4]
|
||||
call display_error_string
|
||||
add esi,[esi-4]
|
||||
add esi,12
|
||||
jmp show_token
|
||||
show_string_token:
|
||||
mov ebx,esi
|
||||
inc esi
|
||||
call show_string_token_content
|
||||
lea esi,[ebx+1]
|
||||
lodsd
|
||||
add esi,eax
|
||||
jmp show_token
|
||||
show_string_token_content:
|
||||
lea edi,[esi+4]
|
||||
mov ecx,[esi]
|
||||
show_string_segment:
|
||||
push ecx edi
|
||||
mov esi,_single_quote
|
||||
mov ecx,1
|
||||
call display_error_string
|
||||
pop edi ecx
|
||||
jecxz show_end_quote
|
||||
mov edx,ecx
|
||||
mov al,27h
|
||||
repne scasb
|
||||
sub edx,ecx
|
||||
mov esi,edi
|
||||
sub esi,edx
|
||||
push ecx edi
|
||||
mov ecx,edx
|
||||
call display_error_string
|
||||
pop edi ecx
|
||||
test ecx,ecx
|
||||
jnz show_string_segment
|
||||
show_end_quote:
|
||||
cmp byte [ebx],27h
|
||||
je string_token_shown
|
||||
mov esi,_single_quote
|
||||
mov ecx,1
|
||||
call display_error_string
|
||||
string_token_shown:
|
||||
retn
|
||||
show_attached_line:
|
||||
mov ecx,1
|
||||
call display_error_string
|
||||
lea ebx,[esi+2]
|
||||
mov esi,_line_segment_prefix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,ebx
|
||||
jmp show_token
|
||||
show_line_from_macro:
|
||||
mov edx,[ebx+SourceEntry.text]
|
||||
mov esi,[edx+ValueDefinition.value]
|
||||
mov ecx,[edx+ValueDefinition.value_length]
|
||||
mov eax,[ebx+SourceEntry.line_offset]
|
||||
add esi,eax
|
||||
sub ecx,eax
|
||||
jbe line_content_shown
|
||||
call show_preprocessed_line
|
||||
line_content_shown:
|
||||
retn
|
||||
|
||||
show_preprocessed_line:
|
||||
; in:
|
||||
; esi - preprocessed tokens
|
||||
; ecx = total length of preprocessed tokens
|
||||
lea eax,[esi+ecx]
|
||||
mov [preprocessed_text_end],eax
|
||||
show_preprocessed_token:
|
||||
cmp esi,[preprocessed_text_end]
|
||||
jae preprocessed_line_shown
|
||||
mov al,[esi]
|
||||
test al,al
|
||||
jz preprocessed_line_shown
|
||||
cmp al,1Ah
|
||||
je show_preprocessed_name_token
|
||||
cmp al,22h
|
||||
je show_preprocessed_string_token
|
||||
cmp al,27h
|
||||
je show_preprocessed_string_token
|
||||
cmp al,30h
|
||||
je show_internal_number
|
||||
cmp al,40h
|
||||
je show_context_token
|
||||
mov ecx,1
|
||||
call display_error_string
|
||||
inc esi
|
||||
jmp show_preprocessed_token
|
||||
show_preprocessed_name_token:
|
||||
inc esi
|
||||
lodsd
|
||||
mov ebx,esi
|
||||
mov esi,eax
|
||||
lodsd
|
||||
mov ecx,eax
|
||||
call display_error_string
|
||||
mov esi,ebx
|
||||
jmp show_preprocessed_token
|
||||
show_preprocessed_string_token:
|
||||
mov ebx,esi
|
||||
mov esi,[esi+1]
|
||||
call show_string_token_content
|
||||
lea esi,[ebx+1+4]
|
||||
jmp show_preprocessed_token
|
||||
show_internal_number:
|
||||
inc esi
|
||||
mov edx,esi
|
||||
push esi
|
||||
call convert_number_back
|
||||
lea esi,[edx+4]
|
||||
mov ecx,[edx]
|
||||
call display_error_string
|
||||
pop esi
|
||||
add esi,[esi]
|
||||
add esi,4
|
||||
jmp show_preprocessed_token
|
||||
show_context_token:
|
||||
add esi,1+sizeof.RecognitionContext
|
||||
jmp show_preprocessed_token
|
||||
preprocessed_line_shown:
|
||||
retn
|
||||
|
||||
itoa:
|
||||
; in:
|
||||
; edx:eax = unsigned number
|
||||
; out:
|
||||
; esi - temporary buffer containing decimal digits
|
||||
; ecx = length of string (number of digits)
|
||||
mov edi,temporary_value+4
|
||||
stosd
|
||||
mov eax,edx
|
||||
stosd
|
||||
mov edx,temporary_value
|
||||
mov dword [edx],8
|
||||
call convert_number_back
|
||||
lea esi,[edx+4]
|
||||
mov ecx,[edx]
|
||||
retn
|
4852
toolchain/fasmg.kl0e/source/directives.inc
Normal file
4852
toolchain/fasmg.kl0e/source/directives.inc
Normal file
File diff suppressed because it is too large
Load Diff
651
toolchain/fasmg.kl0e/source/dos/fasmg.asm
Normal file
651
toolchain/fasmg.kl0e/source/dos/fasmg.asm
Normal file
@ -0,0 +1,651 @@
|
||||
|
||||
match ,{
|
||||
|
||||
include '../libc/struct.inc'
|
||||
|
||||
} match -,{
|
||||
else
|
||||
|
||||
include 'selfhost.inc'
|
||||
|
||||
end match
|
||||
_ equ }
|
||||
|
||||
include '../version.inc'
|
||||
|
||||
BUFFER_SIZE = 4000h
|
||||
STACK_SIZE = 4000h
|
||||
|
||||
format MZ
|
||||
heap 0
|
||||
stack stack_segment:stack_top-stack_bottom
|
||||
entry loader:startup
|
||||
|
||||
segment loader use16
|
||||
|
||||
startup:
|
||||
|
||||
mov ax,1687h
|
||||
int 2Fh
|
||||
or ax,ax ; DPMI installed?
|
||||
jnz short no_dpmi
|
||||
test bl,1 ; 32-bit programs supported?
|
||||
jz short no_dpmi
|
||||
mov word [cs:mode_switch],di
|
||||
mov word [cs:mode_switch+2],es
|
||||
mov bx,si ; allocate memory for DPMI data
|
||||
mov ah,48h
|
||||
int 21h
|
||||
jnc switch_to_protected_mode
|
||||
init_failed:
|
||||
call startup_error
|
||||
db 'DPMI initialization failed.',0Dh,0Ah,0
|
||||
no_dpmi:
|
||||
call startup_error
|
||||
db '32-bit DPMI services are not available.',0Dh,0Ah,0
|
||||
startup_error:
|
||||
pop si
|
||||
push cs
|
||||
pop ds
|
||||
show_message:
|
||||
lodsb
|
||||
test al,al
|
||||
jz message_shown
|
||||
mov dl,al
|
||||
mov ah,2
|
||||
int 21h
|
||||
jmp show_message
|
||||
message_shown:
|
||||
mov ax,4CFFh
|
||||
int 21h
|
||||
switch_to_protected_mode:
|
||||
mov es,ax
|
||||
mov ds,[ds:2Ch]
|
||||
mov ax,1
|
||||
call far [cs:mode_switch] ; switch to protected mode
|
||||
jc init_failed
|
||||
mov cx,1
|
||||
xor ax,ax
|
||||
int 31h ; allocate descriptor for code
|
||||
jc init_failed
|
||||
mov si,ax
|
||||
xor ax,ax
|
||||
int 31h ; allocate descriptor for data
|
||||
jc init_failed
|
||||
mov di,ax
|
||||
mov dx,cs
|
||||
lar cx,dx
|
||||
shr cx,8
|
||||
or cx,0C000h
|
||||
mov bx,si
|
||||
mov ax,9
|
||||
int 31h ; set code descriptor access rights
|
||||
jc init_failed
|
||||
mov dx,ds
|
||||
lar cx,dx
|
||||
shr cx,8
|
||||
or cx,0C000h
|
||||
mov bx,di
|
||||
int 31h ; set data descriptor access rights
|
||||
jc init_failed
|
||||
mov ecx,main
|
||||
shl ecx,4
|
||||
mov dx,cx
|
||||
shr ecx,16
|
||||
mov ax,7
|
||||
int 31h ; set data descriptor base address
|
||||
jc init_failed
|
||||
mov bx,si
|
||||
int 31h ; set code descriptor base address
|
||||
jc init_failed
|
||||
mov cx,0FFFFh
|
||||
mov dx,0FFFFh
|
||||
mov ax,8 ; set segment limit to 4 GB
|
||||
int 31h
|
||||
jc init_failed
|
||||
mov bx,di
|
||||
int 31h
|
||||
jc init_failed
|
||||
mov ax,ds
|
||||
mov ds,di
|
||||
mov [main_selector],di
|
||||
mov [psp_selector],es
|
||||
mov gs,ax ; environment selector in GS
|
||||
cli
|
||||
mov ss,di
|
||||
mov esp,stack_top
|
||||
sti
|
||||
mov es,di
|
||||
mov cx,1
|
||||
xor ax,ax
|
||||
int 31h ; allocate descriptor for BIOS data segment
|
||||
jc init_failed
|
||||
mov bx,ax
|
||||
mov ax,gs
|
||||
lar cx,ax
|
||||
shr cx,8
|
||||
mov ax,9
|
||||
int 31h ; set descriptor access rights
|
||||
jc init_failed
|
||||
xor cx,cx
|
||||
mov dx,400h
|
||||
mov ax,7
|
||||
int 31h ; set base address of BIOS data segment
|
||||
jc init_failed
|
||||
xor cx,cx
|
||||
mov dx,0FFh
|
||||
mov ax,8
|
||||
int 31h ; set limit of BIOS data segment
|
||||
jc init_failed
|
||||
mov fs,bx ; BIOS data selector in FS
|
||||
push si
|
||||
push start
|
||||
retf
|
||||
|
||||
mode_switch dd ?
|
||||
|
||||
segment main use32
|
||||
|
||||
start:
|
||||
|
||||
call system_init
|
||||
|
||||
call get_arguments
|
||||
mov bl,al
|
||||
cmp [no_logo],0
|
||||
jne logo_ok
|
||||
mov esi,_logo
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
logo_ok:
|
||||
test bl,bl
|
||||
jnz display_usage_information
|
||||
|
||||
xor al,al
|
||||
mov ecx,[verbosity_level]
|
||||
jecxz init
|
||||
or al,TRACE_ERROR_STACK
|
||||
dec ecx
|
||||
jz init
|
||||
or al,TRACE_DISPLAY
|
||||
init:
|
||||
|
||||
call assembly_init
|
||||
|
||||
mov eax,[fs:6Ch]
|
||||
mov [timer],eax
|
||||
|
||||
assemble:
|
||||
mov esi,[initial_commands]
|
||||
mov edx,[source_path]
|
||||
call assembly_pass
|
||||
jc assembly_done
|
||||
|
||||
mov eax,[current_pass]
|
||||
cmp eax,[maximum_number_of_passes]
|
||||
jb assemble
|
||||
|
||||
call show_display_data
|
||||
|
||||
mov esi,_error_prefix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,_code_cannot_be_generated
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,_message_suffix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
|
||||
jmp assembly_failed
|
||||
|
||||
assembly_done:
|
||||
|
||||
call show_display_data
|
||||
|
||||
cmp [first_error],0
|
||||
jne assembly_failed
|
||||
|
||||
cmp [no_logo],0
|
||||
jne summary_done
|
||||
mov eax,[current_pass]
|
||||
xor edx,edx
|
||||
call itoa
|
||||
call display_string
|
||||
mov esi,_passes
|
||||
cmp [current_pass],1
|
||||
jne display_passes_suffix
|
||||
mov esi,_pass
|
||||
display_passes_suffix:
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
mov eax,[fs:6Ch]
|
||||
sub eax,[timer]
|
||||
mov ecx,36000
|
||||
mul ecx
|
||||
shrd eax,edx,16
|
||||
shr edx,16
|
||||
mov ecx,10
|
||||
div ecx
|
||||
mov [timer],edx
|
||||
or edx,eax
|
||||
jz display_output_length
|
||||
xor edx,edx
|
||||
call itoa
|
||||
call display_string
|
||||
mov esi,_message_suffix
|
||||
mov ecx,1
|
||||
call display_string
|
||||
mov eax,[timer]
|
||||
xor edx,edx
|
||||
call itoa
|
||||
call display_string
|
||||
mov esi,_seconds
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
display_output_length:
|
||||
call get_output_length
|
||||
push eax edx
|
||||
call itoa
|
||||
call display_string
|
||||
pop edx eax
|
||||
mov esi,_bytes
|
||||
cmp eax,1
|
||||
jne display_bytes_suffix
|
||||
test edx,edx
|
||||
jnz display_bytes_suffix
|
||||
mov esi,_byte
|
||||
display_bytes_suffix:
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
mov esi,_new_line
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
summary_done:
|
||||
|
||||
mov ebx,[source_path]
|
||||
mov edi,[output_path]
|
||||
call write_output_file
|
||||
jc write_failed
|
||||
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
|
||||
mov ax,4C00h
|
||||
int 21h
|
||||
|
||||
assembly_failed:
|
||||
|
||||
call show_errors
|
||||
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
|
||||
mov ax,4C02h
|
||||
int 21h
|
||||
|
||||
write_failed:
|
||||
mov ebx,_write_failed
|
||||
jmp fatal_error
|
||||
|
||||
out_of_memory:
|
||||
mov ebx,_out_of_memory
|
||||
jmp fatal_error
|
||||
|
||||
fatal_error:
|
||||
|
||||
mov esi,_error_prefix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,ebx
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,_message_suffix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
|
||||
mov ax,4C03h
|
||||
int 21h
|
||||
|
||||
display_usage_information:
|
||||
|
||||
mov esi,_usage
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
|
||||
call system_shutdown
|
||||
|
||||
mov ax,4C01h
|
||||
int 21h
|
||||
|
||||
get_arguments:
|
||||
push ds
|
||||
mov ds,[psp_selector]
|
||||
mov esi,81h
|
||||
mov edi,command_line
|
||||
mov ecx,7Fh
|
||||
move_command_line:
|
||||
lodsb
|
||||
cmp al,0Dh
|
||||
je command_line_moved
|
||||
stosb
|
||||
loop move_command_line
|
||||
command_line_moved:
|
||||
pop ds
|
||||
xor eax,eax
|
||||
stosb
|
||||
mov [initial_commands],eax
|
||||
mov [source_path],eax
|
||||
mov [output_path],eax
|
||||
mov [no_logo],al
|
||||
mov [verbosity_level],eax
|
||||
mov [maximum_number_of_passes],100
|
||||
mov [maximum_number_of_errors],1
|
||||
mov [maximum_depth_of_stack],10000
|
||||
mov esi,command_line
|
||||
mov edi,parameters
|
||||
get_argument:
|
||||
xor ah,ah
|
||||
read_character:
|
||||
lodsb
|
||||
test al,al
|
||||
jz no_more_arguments
|
||||
cmp al,22h
|
||||
je switch_quote
|
||||
cmp ax,20h
|
||||
je end_argument
|
||||
stosb
|
||||
jmp read_character
|
||||
end_argument:
|
||||
xor al,al
|
||||
stosb
|
||||
find_next_argument:
|
||||
mov al,[esi]
|
||||
test al,al
|
||||
jz no_more_arguments
|
||||
cmp al,20h
|
||||
jne next_argument_found
|
||||
inc esi
|
||||
jmp find_next_argument
|
||||
switch_quote:
|
||||
xor ah,1
|
||||
jmp read_character
|
||||
next_argument_found:
|
||||
cmp al,'-'
|
||||
je get_option
|
||||
cmp al,'/'
|
||||
je get_option
|
||||
cmp [source_path],0
|
||||
je get_source_path
|
||||
cmp [output_path],0
|
||||
je get_output_path
|
||||
error_in_arguments:
|
||||
or al,-1
|
||||
retn
|
||||
get_source_path:
|
||||
mov [source_path],edi
|
||||
jmp get_argument
|
||||
get_output_path:
|
||||
mov [output_path],edi
|
||||
jmp get_argument
|
||||
no_more_arguments:
|
||||
cmp [source_path],0
|
||||
je error_in_arguments
|
||||
xor al,al
|
||||
stosb
|
||||
retn
|
||||
get_option:
|
||||
inc esi
|
||||
lodsb
|
||||
cmp al,'e'
|
||||
je set_errors_limit
|
||||
cmp al,'E'
|
||||
je set_errors_limit
|
||||
cmp al,'i'
|
||||
je insert_initial_command
|
||||
cmp al,'I'
|
||||
je insert_initial_command
|
||||
cmp al,'p'
|
||||
je set_passes_limit
|
||||
cmp al,'P'
|
||||
je set_passes_limit
|
||||
cmp al,'r'
|
||||
je set_recursion_limit
|
||||
cmp al,'R'
|
||||
je set_recursion_limit
|
||||
cmp al,'v'
|
||||
je set_verbose_mode
|
||||
cmp al,'V'
|
||||
je set_verbose_mode
|
||||
cmp al,'n'
|
||||
je set_no_logo
|
||||
cmp al,'N'
|
||||
jne error_in_arguments
|
||||
set_no_logo:
|
||||
or [no_logo],-1
|
||||
mov al,[esi]
|
||||
cmp al,20h
|
||||
je find_next_argument
|
||||
test al,al
|
||||
jnz error_in_arguments
|
||||
jmp find_next_argument
|
||||
set_verbose_mode:
|
||||
call get_option_value
|
||||
jc error_in_arguments
|
||||
cmp edx,2
|
||||
ja error_in_arguments
|
||||
mov [verbosity_level],edx
|
||||
jmp find_next_argument
|
||||
set_errors_limit:
|
||||
call get_option_value
|
||||
jc error_in_arguments
|
||||
test edx,edx
|
||||
jz error_in_arguments
|
||||
mov [maximum_number_of_errors],edx
|
||||
jmp find_next_argument
|
||||
set_recursion_limit:
|
||||
call get_option_value
|
||||
jc error_in_arguments
|
||||
test edx,edx
|
||||
jz error_in_arguments
|
||||
mov [maximum_depth_of_stack],edx
|
||||
jmp find_next_argument
|
||||
set_passes_limit:
|
||||
call get_option_value
|
||||
jc error_in_arguments
|
||||
test edx,edx
|
||||
jz error_in_arguments
|
||||
mov [maximum_number_of_passes],edx
|
||||
jmp find_next_argument
|
||||
get_option_value:
|
||||
xor eax,eax
|
||||
mov edx,eax
|
||||
find_option_value:
|
||||
cmp byte [esi],20h
|
||||
jne get_option_digit
|
||||
inc esi
|
||||
jmp find_option_value
|
||||
get_option_digit:
|
||||
lodsb
|
||||
cmp al,20h
|
||||
je option_value_ok
|
||||
test al,al
|
||||
jz option_value_ok
|
||||
sub al,30h
|
||||
jc invalid_option_value
|
||||
cmp al,9
|
||||
ja invalid_option_value
|
||||
imul edx,10
|
||||
jo invalid_option_value
|
||||
add edx,eax
|
||||
jc invalid_option_value
|
||||
jmp get_option_digit
|
||||
option_value_ok:
|
||||
dec esi
|
||||
clc
|
||||
ret
|
||||
invalid_option_value:
|
||||
stc
|
||||
ret
|
||||
insert_initial_command:
|
||||
push edi
|
||||
find_command_segment:
|
||||
cmp byte [esi],20h
|
||||
jne command_segment_found
|
||||
inc esi
|
||||
jmp find_command_segment
|
||||
command_segment_found:
|
||||
xor ah,ah
|
||||
cmp byte [esi],22h
|
||||
jne measure_command_segment
|
||||
inc esi
|
||||
inc ah
|
||||
measure_command_segment:
|
||||
mov ebx,esi
|
||||
scan_command_segment:
|
||||
mov ecx,esi
|
||||
mov al,[esi]
|
||||
test al,al
|
||||
jz command_segment_measured
|
||||
cmp ax,20h
|
||||
je command_segment_measured
|
||||
cmp ax,22h
|
||||
je command_segment_measured
|
||||
inc esi
|
||||
cmp al,22h
|
||||
jne scan_command_segment
|
||||
command_segment_measured:
|
||||
sub ecx,ebx
|
||||
mov edi,[initial_commands]
|
||||
lea eax,[ecx+2]
|
||||
test edi,edi
|
||||
jz allocate_initial_commands_buffer
|
||||
mov edx,[initial_commands_length]
|
||||
add edi,edx
|
||||
add eax,edx
|
||||
cmp eax,[initial_commands_maximum_length]
|
||||
ja grow_initial_commands_buffer
|
||||
copy_initial_command:
|
||||
xchg esi,ebx
|
||||
rep movsb
|
||||
mov esi,ebx
|
||||
sub edi,[initial_commands]
|
||||
mov [initial_commands_length],edi
|
||||
mov al,[esi]
|
||||
test al,al
|
||||
jz initial_command_ready
|
||||
cmp al,20h
|
||||
jne command_segment_found
|
||||
initial_command_ready:
|
||||
mov edi,[initial_commands]
|
||||
add edi,[initial_commands_length]
|
||||
mov ax,0Ah
|
||||
stosw
|
||||
inc [initial_commands_length]
|
||||
pop edi
|
||||
jmp find_next_argument
|
||||
allocate_initial_commands_buffer:
|
||||
push ecx
|
||||
mov ecx,eax
|
||||
call malloc
|
||||
mov [initial_commands],eax
|
||||
mov [initial_commands_maximum_length],ecx
|
||||
mov edi,eax
|
||||
pop ecx
|
||||
jmp copy_initial_command
|
||||
grow_initial_commands_buffer:
|
||||
push ecx
|
||||
mov ecx,eax
|
||||
mov eax,[initial_commands]
|
||||
call realloc
|
||||
mov [initial_commands],eax
|
||||
mov [initial_commands_maximum_length],ecx
|
||||
mov edi,eax
|
||||
add edi,[initial_commands_length]
|
||||
pop ecx
|
||||
jmp copy_initial_command
|
||||
|
||||
include 'system.inc'
|
||||
|
||||
include '../malloc.inc'
|
||||
include '../assembler.inc'
|
||||
include '../symbols.inc'
|
||||
include '../expressions.inc'
|
||||
include '../conditions.inc'
|
||||
include '../floats.inc'
|
||||
include '../directives.inc'
|
||||
include '../calm.inc'
|
||||
include '../errors.inc'
|
||||
include '../map.inc'
|
||||
include '../reader.inc'
|
||||
include '../output.inc'
|
||||
include '../console.inc'
|
||||
|
||||
_logo db 'flat assembler version g.',VERSION,13,10,0
|
||||
|
||||
_usage db 'Usage: fasmg source [output]',13,10
|
||||
db 'Optional settings:',13,10
|
||||
db ' -e limit Set the maximum number of displayed errors (default 1)',13,10
|
||||
db ' -p limit Set the maximum allowed number of passes (default 100)',13,10
|
||||
db ' -r limit Set the maximum depth of the stack (default 10000)',13,10
|
||||
db ' -v flag Enable or disable showing all lines from the stack (default 0)',13,10
|
||||
db ' -i command Insert instruction at the beginning of source',13,10
|
||||
db ' -n Do not show logo nor summary',13,10
|
||||
db 0
|
||||
|
||||
_pass db ' pass, ',0
|
||||
_passes db ' passes, ',0
|
||||
_dot db '.'
|
||||
_seconds db ' seconds, ',0
|
||||
_byte db ' byte.',0
|
||||
_bytes db ' bytes.',0
|
||||
|
||||
_write_failed db 'failed to write the output file',0
|
||||
_out_of_memory db 'not enough memory to complete the assembly',0
|
||||
_code_cannot_be_generated db 'could not generate code within the allowed number of passes',0
|
||||
|
||||
include '../tables.inc'
|
||||
include '../messages.inc'
|
||||
|
||||
align 4
|
||||
|
||||
include '../variables.inc'
|
||||
|
||||
psp_selector dw ?
|
||||
main_selector dw ?
|
||||
|
||||
malloc_freelist dd ?
|
||||
|
||||
source_path dd ?
|
||||
output_path dd ?
|
||||
maximum_number_of_passes dd ?
|
||||
|
||||
initial_commands dd ?
|
||||
initial_commands_length dd ?
|
||||
initial_commands_maximum_length dd ?
|
||||
|
||||
timestamp dq ?
|
||||
|
||||
timer dd ?
|
||||
verbosity_level dd ?
|
||||
no_logo db ?
|
||||
|
||||
command_line db 80h dup ?
|
||||
parameters db 80h dup ?
|
||||
|
||||
segment buffer_segment
|
||||
|
||||
buffer = (buffer_segment-main) shl 4
|
||||
|
||||
db BUFFER_SIZE dup ?
|
||||
|
||||
segment stack_segment
|
||||
|
||||
stack_bottom = (stack_segment-main) shl 4
|
||||
|
||||
db STACK_SIZE dup ?
|
||||
|
||||
stack_top = stack_bottom + $
|
22
toolchain/fasmg.kl0e/source/dos/selfhost.inc
Normal file
22
toolchain/fasmg.kl0e/source/dos/selfhost.inc
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
include '../../examples/x86/include/80386.inc'
|
||||
|
||||
macro format?.MZ?
|
||||
format binary as 'exe'
|
||||
include '../../examples/x86/include/format/mz.inc'
|
||||
end macro
|
||||
|
||||
macro struct? name
|
||||
macro ends?!
|
||||
end namespace
|
||||
esc end struc
|
||||
virtual at 0
|
||||
name name
|
||||
sizeof.name = $
|
||||
end virtual
|
||||
purge ends?
|
||||
end macro
|
||||
esc struc name
|
||||
label . : sizeof.name
|
||||
namespace .
|
||||
end macro
|
415
toolchain/fasmg.kl0e/source/dos/system.inc
Normal file
415
toolchain/fasmg.kl0e/source/dos/system.inc
Normal file
@ -0,0 +1,415 @@
|
||||
|
||||
LINE_FEED equ 13,10
|
||||
|
||||
system_init:
|
||||
cld
|
||||
mov [malloc_freelist],0
|
||||
mov ah,2Ah
|
||||
int 21h
|
||||
push dx cx
|
||||
movzx ecx,cx
|
||||
mov eax,ecx
|
||||
sub eax,1970
|
||||
mov ebx,365
|
||||
mul ebx
|
||||
mov ebp,eax
|
||||
mov eax,ecx
|
||||
sub eax,1969
|
||||
shr eax,2
|
||||
add ebp,eax
|
||||
mov eax,ecx
|
||||
sub eax,1901
|
||||
mov ebx,100
|
||||
div ebx
|
||||
sub ebp,eax
|
||||
mov eax,ecx
|
||||
xor edx,edx
|
||||
sub eax,1601
|
||||
mov ebx,400
|
||||
div ebx
|
||||
add ebp,eax
|
||||
movzx ecx,byte [esp+3]
|
||||
mov eax,ecx
|
||||
dec eax
|
||||
mov ebx,30
|
||||
mul ebx
|
||||
add ebp,eax
|
||||
cmp ecx,8
|
||||
jbe months_correction
|
||||
mov eax,ecx
|
||||
sub eax,7
|
||||
shr eax,1
|
||||
add ebp,eax
|
||||
mov ecx,8
|
||||
months_correction:
|
||||
mov eax,ecx
|
||||
shr eax,1
|
||||
add ebp,eax
|
||||
cmp ecx,2
|
||||
pop cx
|
||||
jbe day_correction_ok
|
||||
sub ebp,2
|
||||
test ecx,11b
|
||||
jnz day_correction_ok
|
||||
xor edx,edx
|
||||
mov eax,ecx
|
||||
mov ebx,100
|
||||
div ebx
|
||||
or edx,edx
|
||||
jnz day_correction
|
||||
mov eax,ecx
|
||||
mov ebx,400
|
||||
div ebx
|
||||
or edx,edx
|
||||
jnz day_correction_ok
|
||||
day_correction:
|
||||
inc ebp
|
||||
day_correction_ok:
|
||||
pop dx
|
||||
movzx eax,dl
|
||||
dec eax
|
||||
add eax,ebp
|
||||
mov ebx,24
|
||||
mul ebx
|
||||
push eax
|
||||
mov ah,2Ch
|
||||
int 21h
|
||||
pop eax
|
||||
push dx
|
||||
movzx ebx,ch
|
||||
add eax,ebx
|
||||
mov ebx,60
|
||||
mul ebx
|
||||
movzx ebx,cl
|
||||
add eax,ebx
|
||||
mov ebx,60
|
||||
mul ebx
|
||||
pop bx
|
||||
movzx ebx,bh
|
||||
add eax,ebx
|
||||
adc edx,0
|
||||
mov dword [timestamp],eax
|
||||
mov dword [timestamp+4],edx
|
||||
retn
|
||||
|
||||
system_shutdown:
|
||||
; call mcheck
|
||||
retn
|
||||
|
||||
dos_int:
|
||||
push 0
|
||||
push 0
|
||||
push 0
|
||||
pushw buffer_segment
|
||||
pushw buffer_segment
|
||||
stc
|
||||
pushfw
|
||||
push eax
|
||||
push ecx
|
||||
push edx
|
||||
push ebx
|
||||
push 0
|
||||
push ebp
|
||||
push esi
|
||||
push edi
|
||||
mov ax,300h
|
||||
mov bx,21h
|
||||
xor cx,cx
|
||||
mov edi,esp
|
||||
push es ss
|
||||
pop es
|
||||
int 31h
|
||||
pop es
|
||||
mov edi,[esp]
|
||||
mov esi,[esp+4]
|
||||
mov ebp,[esp+8]
|
||||
mov ebx,[esp+10h]
|
||||
mov edx,[esp+14h]
|
||||
mov ecx,[esp+18h]
|
||||
mov ah,[esp+20h]
|
||||
sahf
|
||||
mov eax,[esp+1Ch]
|
||||
lea esp,[esp+32h]
|
||||
retn
|
||||
|
||||
open:
|
||||
; in: edx - path to file
|
||||
; out: ebx = file handle, cf set on error
|
||||
; preserves: esi, edi
|
||||
push esi edi
|
||||
call adapt_path
|
||||
mov ax,716Ch
|
||||
mov bx,100000b
|
||||
mov dx,1
|
||||
xor cx,cx
|
||||
xor si,si
|
||||
call dos_int
|
||||
jnc open_done
|
||||
cmp ax,7100h
|
||||
je old_open
|
||||
stc
|
||||
jmp open_done
|
||||
old_open:
|
||||
mov ax,3D00h
|
||||
xor dx,dx
|
||||
call dos_int
|
||||
open_done:
|
||||
mov bx,ax
|
||||
pop edi esi
|
||||
retn
|
||||
adapt_path:
|
||||
mov esi,edx
|
||||
mov edi,buffer
|
||||
copy_path:
|
||||
lodsb
|
||||
cmp al,'/'
|
||||
jne path_char_ok
|
||||
mov al,'\'
|
||||
path_char_ok:
|
||||
stosb
|
||||
cmp edi,buffer+BUFFER_SIZE
|
||||
jae out_of_memory
|
||||
test al,al
|
||||
jnz copy_path
|
||||
retn
|
||||
|
||||
create:
|
||||
; in: edx - path to file
|
||||
; out: ebx = file handle, cf set on error
|
||||
; preserves: esi, edi
|
||||
push esi edi
|
||||
call adapt_path
|
||||
mov ax,716Ch
|
||||
mov bx,100001b
|
||||
mov dx,10010b
|
||||
xor cx,cx
|
||||
xor si,si
|
||||
xor di,di
|
||||
call dos_int
|
||||
jnc create_done
|
||||
cmp ax,7100h
|
||||
je old_create
|
||||
stc
|
||||
jmp create_done
|
||||
old_create:
|
||||
mov ah,3Ch
|
||||
xor cx,cx
|
||||
xor dx,dx
|
||||
call dos_int
|
||||
create_done:
|
||||
mov bx,ax
|
||||
pop edi esi
|
||||
retn
|
||||
|
||||
write:
|
||||
; in: ebx = file handle, edx - data, ecx = number of bytes
|
||||
; out: cf set on error
|
||||
; preserves: ebx, esi, edi
|
||||
push esi edi ebp
|
||||
mov ebp,ecx
|
||||
mov esi,edx
|
||||
write_loop:
|
||||
mov ecx,BUFFER_SIZE
|
||||
sub ebp,BUFFER_SIZE
|
||||
jnc do_write
|
||||
add ebp,BUFFER_SIZE
|
||||
mov ecx,ebp
|
||||
xor ebp,ebp
|
||||
do_write:
|
||||
push ecx
|
||||
mov edi,buffer
|
||||
rep movsb
|
||||
pop ecx
|
||||
mov ah,40h
|
||||
xor dx,dx
|
||||
call dos_int
|
||||
or ebp,ebp
|
||||
jnz write_loop
|
||||
pop ebp edi esi
|
||||
ret
|
||||
|
||||
read:
|
||||
; in: ebx = file handle, edx - buffer, ecx = number of bytes
|
||||
; out: cf set on error
|
||||
; preserves: ebx, esi, edi
|
||||
push esi edi ebp
|
||||
mov ebp,ecx
|
||||
mov edi,edx
|
||||
read_loop:
|
||||
mov ecx,BUFFER_SIZE
|
||||
sub ebp,BUFFER_SIZE
|
||||
jnc do_read
|
||||
add ebp,BUFFER_SIZE
|
||||
mov ecx,ebp
|
||||
xor ebp,ebp
|
||||
do_read:
|
||||
push ecx
|
||||
mov ah,3Fh
|
||||
xor dx,dx
|
||||
call dos_int
|
||||
cmp ax,cx
|
||||
jne read_eof
|
||||
mov esi,buffer
|
||||
pop ecx
|
||||
rep movsb
|
||||
or ebp,ebp
|
||||
jnz read_loop
|
||||
read_done:
|
||||
pop ebp edi esi
|
||||
ret
|
||||
read_eof:
|
||||
pop ecx
|
||||
stc
|
||||
jmp read_done
|
||||
|
||||
close:
|
||||
; in: ebx = file handle
|
||||
; preserves: ebx, esi, edi
|
||||
mov ah,3Eh
|
||||
int 21h
|
||||
ret
|
||||
|
||||
lseek:
|
||||
; in: ebx = file handle, cl = method, edx:eax = offset
|
||||
; out: edx:eax = new offset from the beginning of file, cf set on error
|
||||
; preserves: ebx, esi, edi
|
||||
mov dx,ax
|
||||
xchg ecx,eax
|
||||
shr ecx,16
|
||||
mov ah,42h
|
||||
int 21h
|
||||
pushf
|
||||
shl edx,16
|
||||
popf
|
||||
mov dx,ax
|
||||
mov eax,edx
|
||||
xor edx,edx
|
||||
ret
|
||||
|
||||
get_timestamp:
|
||||
; out: edx:eax = timestamp
|
||||
; preserves: ebx, ecx, esi, edi
|
||||
; note: during the passes of a single assembly this function should always return the same value
|
||||
mov eax,dword [timestamp]
|
||||
mov edx,dword [timestamp+4]
|
||||
retn
|
||||
|
||||
display_string:
|
||||
; in:
|
||||
; esi - string
|
||||
; ecx = string length, zero for ASCIIZ string
|
||||
; preserves: ebx, esi
|
||||
push ebx
|
||||
mov ebx,1
|
||||
jmp write_string
|
||||
display_error_string:
|
||||
; in:
|
||||
; esi - string
|
||||
; ecx = string length, zero for ASCIIZ string
|
||||
; preserves: ebx, esi
|
||||
push ebx
|
||||
mov ebx,2
|
||||
write_string:
|
||||
test ecx,ecx
|
||||
jnz string_length_ok
|
||||
xor al,al
|
||||
mov edi,esi
|
||||
or ecx,-1
|
||||
repne scasb
|
||||
neg ecx
|
||||
sub ecx,2
|
||||
string_length_ok:
|
||||
mov edx,esi
|
||||
call write
|
||||
pop ebx
|
||||
retn
|
||||
|
||||
get_environment_variable:
|
||||
; in:
|
||||
; esi - name
|
||||
; edi - buffer for value
|
||||
; ecx = size of buffer
|
||||
; out:
|
||||
; eax = length of value
|
||||
; preserves: ebx, esi, edi
|
||||
push ebx esi edi
|
||||
mov ebx,esi
|
||||
xor esi,esi
|
||||
compare_variable_names:
|
||||
mov edx,ebx
|
||||
compare_name_character:
|
||||
lods byte [gs:esi]
|
||||
mov ah,[edx]
|
||||
inc edx
|
||||
cmp al,'='
|
||||
je end_of_variable_name
|
||||
test ah,ah
|
||||
jz next_variable
|
||||
sub ah,al
|
||||
jz compare_name_character
|
||||
cmp ah,20h
|
||||
jne next_variable
|
||||
cmp al,41h
|
||||
jb next_variable
|
||||
cmp al,5Ah
|
||||
jna compare_name_character
|
||||
next_variable:
|
||||
lods byte [gs:esi]
|
||||
test al,al
|
||||
jnz next_variable
|
||||
cmp byte [gs:esi],0
|
||||
jne compare_variable_names
|
||||
mov ah,al
|
||||
end_of_variable_name:
|
||||
test ah,ah
|
||||
jnz next_variable
|
||||
add ecx,edi
|
||||
mov edx,esi
|
||||
copy_variable_value:
|
||||
lods byte [gs:esi]
|
||||
cmp edi,ecx
|
||||
jae variable_value_next_character
|
||||
stosb
|
||||
variable_value_next_character:
|
||||
or al,al
|
||||
jnz copy_variable_value
|
||||
lea eax,[esi-1]
|
||||
sub eax,edx
|
||||
pop edi esi ebx
|
||||
ret
|
||||
|
||||
VALLOC_MIN = 40000h
|
||||
|
||||
valloc:
|
||||
; in: ecx = requested minimum size
|
||||
; out: eax - allocated block, ecx = allocated size, zero if failed
|
||||
; preserves: ebx, esi, edi
|
||||
cmp ecx,VALLOC_MIN
|
||||
jbe valloc_size_minimum
|
||||
dec ecx
|
||||
and ecx,(-1) shl 12
|
||||
add ecx,1 shl 12
|
||||
jmp valloc_size_ready
|
||||
valloc_size_minimum:
|
||||
mov ecx,VALLOC_MIN
|
||||
valloc_size_ready:
|
||||
push ebx esi edi
|
||||
push ecx
|
||||
mov ebx,ecx
|
||||
shr ebx,16
|
||||
mov ax,501h
|
||||
int 31h
|
||||
movzx eax,cx
|
||||
pop ecx
|
||||
jc valloc_failed
|
||||
shl ebx,16
|
||||
or eax,ebx
|
||||
mov edx,main
|
||||
shl edx,4
|
||||
sub eax,edx
|
||||
pop edi esi ebx
|
||||
ret
|
||||
valloc_failed:
|
||||
xor ecx,ecx
|
||||
pop edi esi ebx
|
||||
retn
|
177
toolchain/fasmg.kl0e/source/errors.inc
Normal file
177
toolchain/fasmg.kl0e/source/errors.inc
Normal file
@ -0,0 +1,177 @@
|
||||
|
||||
struct Error
|
||||
flags dd ? ; ERR_#
|
||||
message dd ?
|
||||
symbol dd ?
|
||||
preprocessed_data dd ?
|
||||
preprocessed_length dd ?
|
||||
next dd ? ; pointer to another Error
|
||||
; source SourceContext
|
||||
ends
|
||||
|
||||
ERR_CUSTOM = 1
|
||||
|
||||
register_volatile_error:
|
||||
; in:
|
||||
; edx - 32-bit length followed by string data
|
||||
; ebx - data for message formatting (only relevant for non-custom messages that contain % character)
|
||||
; out:
|
||||
; edx - Error
|
||||
; preserves: eax, ebx, ecx, esi, edi
|
||||
cmp [next_pass_needed],0
|
||||
jne error_ignored
|
||||
push eax ebx ecx esi edi
|
||||
or [message_volatile],1
|
||||
jmp get_error_line
|
||||
register_delayed_error:
|
||||
; in:
|
||||
; edx - error message
|
||||
; esi - SourceContext
|
||||
; ebx - data for message formatting (only relevant for non-custom messages that contain % character)
|
||||
; out:
|
||||
; edx - Error
|
||||
; preserves: eax, ebx, ecx, esi, edi
|
||||
cmp [next_pass_needed],0
|
||||
jne error_ignored
|
||||
push eax ebx ecx esi edi
|
||||
and [message_volatile],0
|
||||
and [error_line_start],0
|
||||
and [error_line_end],0
|
||||
jmp add_error
|
||||
register_error:
|
||||
; in:
|
||||
; edx - error message
|
||||
; ebx - data for message formatting (only relevant for non-custom messages that contain % character)
|
||||
; out:
|
||||
; edx - Error, null when error was not registered
|
||||
; preserves: eax, ebx, ecx, esi, edi
|
||||
cmp [next_pass_needed],0
|
||||
jne error_ignored
|
||||
push eax ebx ecx esi edi
|
||||
and [message_volatile],0
|
||||
get_error_line:
|
||||
mov eax,[line_start]
|
||||
mov [error_line_start],eax
|
||||
mov ecx,[line_end]
|
||||
cmp [number_of_line_embeddings],0
|
||||
je error_line_end_ok
|
||||
mov eax,[line_embeddings]
|
||||
mov ecx,[eax+LineEmbedding.previous_end]
|
||||
error_line_end_ok:
|
||||
mov [error_line_end],ecx
|
||||
xor esi,esi
|
||||
add_error:
|
||||
mov [error_symbol],ebx
|
||||
lea ebx,[first_error]
|
||||
xor ecx,ecx
|
||||
find_last_error:
|
||||
mov eax,[ebx]
|
||||
test eax,eax
|
||||
jz last_error_found
|
||||
lea ebx,[eax+Error.next]
|
||||
inc ecx
|
||||
cmp ecx,[maximum_number_of_errors]
|
||||
jb find_last_error
|
||||
pop edi esi ecx ebx eax
|
||||
xor edx,edx
|
||||
retn
|
||||
last_error_found:
|
||||
cmp [message_volatile],0
|
||||
jne prepare_volatile_error
|
||||
test esi,esi
|
||||
jnz prepare_error
|
||||
mov esi,[source_context]
|
||||
prepare_error:
|
||||
mov ecx,[esi+SourceContext.number_of_entries]
|
||||
imul ecx,sizeof.SourceEntry
|
||||
add ecx,sizeof.SourceContext
|
||||
cmp [esi+ecx-sizeof.SourceEntry+SourceEntry.type],SOURCE_CALM
|
||||
jne error_source_context_ready
|
||||
mov eax,[calm_instruction_number]
|
||||
mov [esi+ecx-sizeof.SourceEntry+SourceEntry.line_number],eax
|
||||
and [error_line_start],0
|
||||
and [error_line_end],0
|
||||
error_source_context_ready:
|
||||
add ecx,sizeof.Error
|
||||
add ecx,[error_line_end]
|
||||
sub ecx,[error_line_start]
|
||||
mov edi,edx
|
||||
call malloc
|
||||
mov [ebx],eax
|
||||
mov [eax+Error.message],edi
|
||||
mov ecx,[error_symbol]
|
||||
mov [eax+Error.symbol],ecx
|
||||
xor ecx,ecx
|
||||
mov [eax+Error.flags],ecx
|
||||
mov [eax+Error.next],ecx
|
||||
lea edi,[eax+sizeof.Error]
|
||||
push eax
|
||||
call clone_source_context
|
||||
pop edx
|
||||
store_preprocessed_data:
|
||||
mov [edx+Error.preprocessed_data],edi
|
||||
mov esi,[error_line_start]
|
||||
mov ecx,[error_line_end]
|
||||
sub ecx,esi
|
||||
mov [edx+Error.preprocessed_length],ecx
|
||||
rep movsb
|
||||
pop edi esi ecx ebx eax
|
||||
retn
|
||||
error_ignored:
|
||||
xor edx,edx
|
||||
retn
|
||||
prepare_volatile_error:
|
||||
mov esi,edx
|
||||
mov eax,[source_context]
|
||||
mov ecx,[eax+SourceContext.number_of_entries]
|
||||
imul ecx,sizeof.SourceEntry
|
||||
add ecx,sizeof.SourceContext
|
||||
cmp [eax+ecx-sizeof.SourceEntry+SourceEntry.type],SOURCE_CALM
|
||||
jne volatile_error_source_context_ready
|
||||
mov edx,[calm_instruction_number]
|
||||
mov [eax+ecx-sizeof.SourceEntry+SourceEntry.line_number],edx
|
||||
and [error_line_start],0
|
||||
and [error_line_end],0
|
||||
volatile_error_source_context_ready:
|
||||
add ecx,sizeof.Error
|
||||
add ecx,[error_line_end]
|
||||
sub ecx,[error_line_start]
|
||||
mov edi,ecx
|
||||
add ecx,[esi]
|
||||
inc ecx
|
||||
call malloc
|
||||
add edi,eax
|
||||
mov [ebx],eax
|
||||
mov edx,eax
|
||||
mov [edx+Error.message],edi
|
||||
xor eax,eax
|
||||
mov [edx+Error.next],eax
|
||||
mov [edx+Error.flags],eax
|
||||
lodsd
|
||||
mov ecx,eax
|
||||
rep movsb
|
||||
xor al,al
|
||||
stosb
|
||||
mov esi,[source_context]
|
||||
lea edi,[edx+sizeof.Error]
|
||||
push edx
|
||||
call clone_source_context
|
||||
pop edx
|
||||
jmp store_preprocessed_data
|
||||
|
||||
discard_errors:
|
||||
mov eax,[first_error]
|
||||
test eax,eax
|
||||
jnz discard_error
|
||||
retn
|
||||
discard_error:
|
||||
add eax,sizeof.Error
|
||||
call release_source_context
|
||||
sub eax,sizeof.Error
|
||||
mov ebx,[eax+Error.next]
|
||||
call mfree
|
||||
mov eax,ebx
|
||||
test eax,eax
|
||||
jnz discard_error
|
||||
mov [first_error],eax
|
||||
retn
|
4252
toolchain/fasmg.kl0e/source/expressions.inc
Normal file
4252
toolchain/fasmg.kl0e/source/expressions.inc
Normal file
File diff suppressed because it is too large
Load Diff
1182
toolchain/fasmg.kl0e/source/floats.inc
Normal file
1182
toolchain/fasmg.kl0e/source/floats.inc
Normal file
File diff suppressed because it is too large
Load Diff
23
toolchain/fasmg.kl0e/source/libc/ccall.inc
Normal file
23
toolchain/fasmg.kl0e/source/libc/ccall.inc
Normal file
@ -0,0 +1,23 @@
|
||||
|
||||
macro ccall proc*,[arg]
|
||||
{
|
||||
common
|
||||
local size,count
|
||||
mov ebp,esp
|
||||
if size
|
||||
sub esp,size
|
||||
end if
|
||||
and esp,0FFFFFFF0h
|
||||
count = 0
|
||||
if ~ arg eq
|
||||
forward
|
||||
mov dword [esp+count*4],arg
|
||||
count = count + 1
|
||||
common
|
||||
end if
|
||||
size = count*4
|
||||
call proc
|
||||
mov esp,ebp
|
||||
}
|
||||
|
||||
macro cinvoke proc*,arg& { ccall [proc],arg }
|
499
toolchain/fasmg.kl0e/source/libc/fasmg.asm
Normal file
499
toolchain/fasmg.kl0e/source/libc/fasmg.asm
Normal file
@ -0,0 +1,499 @@
|
||||
|
||||
match ,{
|
||||
|
||||
include 'ccall.inc'
|
||||
include 'struct.inc'
|
||||
|
||||
} match -,{
|
||||
else
|
||||
|
||||
include 'selfhost.inc'
|
||||
|
||||
end match
|
||||
_ equ }
|
||||
|
||||
format ELF
|
||||
public main
|
||||
|
||||
include '../version.inc'
|
||||
|
||||
extrn 'malloc' as libc.malloc
|
||||
extrn 'realloc' as libc.realloc
|
||||
extrn 'free' as libc.free
|
||||
extrn 'fopen' as libc.fopen
|
||||
extrn 'fclose' as libc.fclose
|
||||
extrn 'fread' as libc.fread
|
||||
extrn 'fwrite' as libc.fwrite
|
||||
extrn 'fseek' as libc.fseek
|
||||
extrn 'ftell' as libc.ftell
|
||||
extrn 'time' as libc.time
|
||||
extrn 'write' as libc.write
|
||||
|
||||
extrn getenv
|
||||
extrn gettimeofday
|
||||
extrn exit
|
||||
|
||||
struct timeval
|
||||
time_t dd ?
|
||||
suseconds_t dd ?
|
||||
ends
|
||||
|
||||
section '.text' executable align 16
|
||||
|
||||
main:
|
||||
mov ecx,[esp+4]
|
||||
mov [argc],ecx
|
||||
mov ebx,[esp+8]
|
||||
mov [argv],ebx
|
||||
|
||||
call system_init
|
||||
|
||||
call get_arguments
|
||||
mov bl,al
|
||||
cmp [no_logo],0
|
||||
jne logo_ok
|
||||
mov esi,_logo
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
logo_ok:
|
||||
test bl,bl
|
||||
jnz display_usage_information
|
||||
|
||||
xor al,al
|
||||
mov ecx,[verbosity_level]
|
||||
jecxz init
|
||||
or al,TRACE_ERROR_STACK
|
||||
dec ecx
|
||||
jz init
|
||||
or al,TRACE_DISPLAY
|
||||
init:
|
||||
call assembly_init
|
||||
|
||||
ccall gettimeofday,start_time,0
|
||||
|
||||
assemble:
|
||||
mov esi,[initial_commands]
|
||||
mov edx,[source_path]
|
||||
call assembly_pass
|
||||
jc assembly_done
|
||||
|
||||
mov eax,[current_pass]
|
||||
cmp eax,[maximum_number_of_passes]
|
||||
jb assemble
|
||||
|
||||
call show_display_data
|
||||
|
||||
mov esi,_error_prefix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,_code_cannot_be_generated
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,_message_suffix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
|
||||
jmp assembly_failed
|
||||
|
||||
assembly_done:
|
||||
|
||||
call show_display_data
|
||||
|
||||
cmp [first_error],0
|
||||
jne assembly_failed
|
||||
|
||||
cmp [no_logo],0
|
||||
jne summary_done
|
||||
mov eax,[current_pass]
|
||||
xor edx,edx
|
||||
call itoa
|
||||
call display_string
|
||||
mov esi,_passes
|
||||
cmp [current_pass],1
|
||||
jne display_passes_suffix
|
||||
mov esi,_pass
|
||||
display_passes_suffix:
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
ccall gettimeofday,end_time,0
|
||||
mov eax,[end_time.time_t]
|
||||
sub eax,[start_time.time_t]
|
||||
mov ecx,1000000
|
||||
mul ecx
|
||||
add eax,[end_time.suseconds_t]
|
||||
adc edx,0
|
||||
sub eax,[start_time.suseconds_t]
|
||||
sbb edx,0
|
||||
add eax,50000
|
||||
mov ecx,1000000
|
||||
div ecx
|
||||
mov ebx,eax
|
||||
mov eax,edx
|
||||
xor edx,edx
|
||||
mov ecx,100000
|
||||
div ecx
|
||||
mov [tenths_of_second],eax
|
||||
xchg eax,ebx
|
||||
or ebx,eax
|
||||
jz display_output_length
|
||||
xor edx,edx
|
||||
call itoa
|
||||
call display_string
|
||||
mov esi,_message_suffix
|
||||
mov ecx,1
|
||||
call display_string
|
||||
mov eax,[tenths_of_second]
|
||||
xor edx,edx
|
||||
call itoa
|
||||
call display_string
|
||||
mov esi,_seconds
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
display_output_length:
|
||||
call get_output_length
|
||||
push eax edx
|
||||
call itoa
|
||||
call display_string
|
||||
pop edx eax
|
||||
mov esi,_bytes
|
||||
cmp eax,1
|
||||
jne display_bytes_suffix
|
||||
test edx,edx
|
||||
jnz display_bytes_suffix
|
||||
mov esi,_byte
|
||||
display_bytes_suffix:
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
mov esi,_new_line
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
summary_done:
|
||||
|
||||
mov ebx,[source_path]
|
||||
mov edi,[output_path]
|
||||
call write_output_file
|
||||
jc write_failed
|
||||
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
|
||||
ccall exit,0
|
||||
|
||||
assembly_failed:
|
||||
|
||||
call show_errors
|
||||
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
|
||||
ccall exit,2
|
||||
|
||||
write_failed:
|
||||
mov ebx,_write_failed
|
||||
jmp fatal_error
|
||||
|
||||
out_of_memory:
|
||||
mov ebx,_out_of_memory
|
||||
jmp fatal_error
|
||||
|
||||
fatal_error:
|
||||
|
||||
mov esi,_error_prefix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,ebx
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,_message_suffix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
|
||||
ccall exit,3
|
||||
|
||||
display_usage_information:
|
||||
|
||||
mov esi,_usage
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
|
||||
call system_shutdown
|
||||
|
||||
ccall exit,1
|
||||
|
||||
get_arguments:
|
||||
xor eax,eax
|
||||
mov [initial_commands],eax
|
||||
mov [source_path],eax
|
||||
mov [output_path],eax
|
||||
mov [no_logo],al
|
||||
mov [verbosity_level],eax
|
||||
mov [maximum_number_of_passes],100
|
||||
mov [maximum_number_of_errors],1
|
||||
mov [maximum_depth_of_stack],10000
|
||||
mov ecx,[argc]
|
||||
mov ebx,[argv]
|
||||
add ebx,4
|
||||
dec ecx
|
||||
jz error_in_arguments
|
||||
get_argument:
|
||||
mov esi,[ebx]
|
||||
mov al,[esi]
|
||||
cmp al,'-'
|
||||
je get_option
|
||||
cmp [source_path],0
|
||||
jne get_output_file
|
||||
mov [source_path],esi
|
||||
jmp next_argument
|
||||
get_output_file:
|
||||
cmp [output_path],0
|
||||
jne error_in_arguments
|
||||
mov [output_path],esi
|
||||
jmp next_argument
|
||||
get_option:
|
||||
inc esi
|
||||
lodsb
|
||||
cmp al,'e'
|
||||
je set_errors_limit
|
||||
cmp al,'E'
|
||||
je set_errors_limit
|
||||
cmp al,'i'
|
||||
je insert_initial_command
|
||||
cmp al,'I'
|
||||
je insert_initial_command
|
||||
cmp al,'p'
|
||||
je set_passes_limit
|
||||
cmp al,'P'
|
||||
je set_passes_limit
|
||||
cmp al,'r'
|
||||
je set_recursion_limit
|
||||
cmp al,'R'
|
||||
je set_recursion_limit
|
||||
cmp al,'v'
|
||||
je set_verbose_mode
|
||||
cmp al,'V'
|
||||
je set_verbose_mode
|
||||
cmp al,'n'
|
||||
je set_no_logo
|
||||
cmp al,'N'
|
||||
jne error_in_arguments
|
||||
set_no_logo:
|
||||
or [no_logo],-1
|
||||
cmp byte [esi],0
|
||||
je next_argument
|
||||
error_in_arguments:
|
||||
or al,-1
|
||||
ret
|
||||
set_verbose_mode:
|
||||
cmp byte [esi],0
|
||||
jne get_verbose_setting
|
||||
dec ecx
|
||||
jz error_in_arguments
|
||||
add ebx,4
|
||||
mov esi,[ebx]
|
||||
get_verbose_setting:
|
||||
call get_option_value
|
||||
cmp edx,2
|
||||
ja error_in_arguments
|
||||
mov [verbosity_level],edx
|
||||
jmp next_argument
|
||||
set_errors_limit:
|
||||
cmp byte [esi],0
|
||||
jne get_errors_setting
|
||||
dec ecx
|
||||
jz error_in_arguments
|
||||
add ebx,4
|
||||
mov esi,[ebx]
|
||||
get_errors_setting:
|
||||
call get_option_value
|
||||
test edx,edx
|
||||
jz error_in_arguments
|
||||
mov [maximum_number_of_errors],edx
|
||||
jmp next_argument
|
||||
set_recursion_limit:
|
||||
cmp byte [esi],0
|
||||
jne get_recursion_setting
|
||||
dec ecx
|
||||
jz error_in_arguments
|
||||
add ebx,4
|
||||
mov esi,[ebx]
|
||||
get_recursion_setting:
|
||||
call get_option_value
|
||||
test edx,edx
|
||||
jz error_in_arguments
|
||||
mov [maximum_depth_of_stack],edx
|
||||
jmp next_argument
|
||||
set_passes_limit:
|
||||
cmp byte [esi],0
|
||||
jne get_passes_setting
|
||||
dec ecx
|
||||
jz error_in_arguments
|
||||
add ebx,4
|
||||
mov esi,[ebx]
|
||||
get_passes_setting:
|
||||
call get_option_value
|
||||
test edx,edx
|
||||
jz error_in_arguments
|
||||
mov [maximum_number_of_passes],edx
|
||||
next_argument:
|
||||
add ebx,4
|
||||
dec ecx
|
||||
jnz get_argument
|
||||
cmp [source_path],0
|
||||
je error_in_arguments
|
||||
xor al,al
|
||||
ret
|
||||
get_option_value:
|
||||
xor eax,eax
|
||||
mov edx,eax
|
||||
find_option_value:
|
||||
cmp byte [esi],20h
|
||||
jne get_option_digit
|
||||
inc esi
|
||||
jmp find_option_value
|
||||
get_option_digit:
|
||||
lodsb
|
||||
test al,al
|
||||
jz option_value_ok
|
||||
sub al,30h
|
||||
jc invalid_option_value
|
||||
cmp al,9
|
||||
ja invalid_option_value
|
||||
imul edx,10
|
||||
jo invalid_option_value
|
||||
add edx,eax
|
||||
jc invalid_option_value
|
||||
jmp get_option_digit
|
||||
option_value_ok:
|
||||
dec esi
|
||||
clc
|
||||
ret
|
||||
invalid_option_value:
|
||||
stc
|
||||
ret
|
||||
insert_initial_command:
|
||||
cmp byte [esi],0
|
||||
jne measure_initial_command
|
||||
dec ecx
|
||||
jz error_in_arguments
|
||||
add ebx,4
|
||||
mov esi,[ebx]
|
||||
measure_initial_command:
|
||||
push ebx ecx edi
|
||||
mov edi,esi
|
||||
or ecx,-1
|
||||
xor al,al
|
||||
repne scasb
|
||||
not ecx
|
||||
dec ecx
|
||||
mov edi,[initial_commands]
|
||||
lea eax,[ecx+2]
|
||||
test edi,edi
|
||||
jz allocate_initial_commands_buffer
|
||||
mov edx,[initial_commands_length]
|
||||
add edi,edx
|
||||
add eax,edx
|
||||
cmp eax,[initial_commands_maximum_length]
|
||||
ja grow_initial_commands_buffer
|
||||
copy_initial_command:
|
||||
rep movsb
|
||||
mov ax,0Ah
|
||||
stosw
|
||||
dec edi
|
||||
sub edi,[initial_commands]
|
||||
mov [initial_commands_length],edi
|
||||
pop edi ecx ebx
|
||||
jmp next_argument
|
||||
allocate_initial_commands_buffer:
|
||||
push ecx
|
||||
mov ecx,eax
|
||||
call malloc
|
||||
mov [initial_commands],eax
|
||||
mov [initial_commands_maximum_length],ecx
|
||||
mov edi,eax
|
||||
pop ecx
|
||||
jmp copy_initial_command
|
||||
grow_initial_commands_buffer:
|
||||
push ecx
|
||||
mov ecx,eax
|
||||
mov eax,[initial_commands]
|
||||
call realloc
|
||||
mov [initial_commands],eax
|
||||
mov [initial_commands_maximum_length],ecx
|
||||
mov edi,eax
|
||||
add edi,[initial_commands_length]
|
||||
pop ecx
|
||||
jmp copy_initial_command
|
||||
|
||||
include 'system.inc'
|
||||
|
||||
include '../assembler.inc'
|
||||
include '../symbols.inc'
|
||||
include '../expressions.inc'
|
||||
include '../conditions.inc'
|
||||
include '../floats.inc'
|
||||
include '../directives.inc'
|
||||
include '../calm.inc'
|
||||
include '../errors.inc'
|
||||
include '../map.inc'
|
||||
include '../reader.inc'
|
||||
include '../output.inc'
|
||||
include '../console.inc'
|
||||
|
||||
section '.data'
|
||||
|
||||
_logo db 'flat assembler version g.',VERSION,10,0
|
||||
|
||||
_usage db 'Usage: fasmg source [output]',10
|
||||
db 'Optional settings:',10
|
||||
db ' -p limit Set the maximum allowed number of passes (default 100)',10
|
||||
db ' -e limit Set the maximum number of displayed errors (default 1)',10
|
||||
db ' -r limit Set the maximum depth of the stack (default 10000)',10
|
||||
db ' -v flag Enable or disable showing all lines from the stack (default 0)',10
|
||||
db ' -i command Insert instruction at the beginning of source',13,10
|
||||
db ' -n Do not show logo nor summary',13,10
|
||||
db 0
|
||||
|
||||
_pass db ' pass, ',0
|
||||
_passes db ' passes, ',0
|
||||
_dot db '.'
|
||||
_seconds db ' seconds, ',0
|
||||
_byte db ' byte.',0
|
||||
_bytes db ' bytes.',0
|
||||
|
||||
_write_failed db 'failed to write the output file',0
|
||||
_out_of_memory db 'not enough memory to complete the assembly',0
|
||||
_code_cannot_be_generated db 'could not generate code within the allowed number of passes',0
|
||||
|
||||
_open_mode db 'r',0
|
||||
_create_mode db 'w',0
|
||||
|
||||
include '../tables.inc'
|
||||
include '../messages.inc'
|
||||
|
||||
section '.bss' writeable align 4
|
||||
|
||||
include '../variables.inc'
|
||||
|
||||
source_path dd ?
|
||||
output_path dd ?
|
||||
maximum_number_of_passes dd ?
|
||||
|
||||
initial_commands dd ?
|
||||
initial_commands_length dd ?
|
||||
initial_commands_maximum_length dd ?
|
||||
|
||||
argc dd ?
|
||||
argv dd ?
|
||||
timestamp dq ?
|
||||
|
||||
start_time timeval
|
||||
end_time timeval
|
||||
tenths_of_second dd ?
|
||||
|
||||
verbosity_level dd ?
|
||||
no_logo db ?
|
||||
|
||||
path_buffer rb 1000h
|
60
toolchain/fasmg.kl0e/source/libc/selfhost.inc
Normal file
60
toolchain/fasmg.kl0e/source/libc/selfhost.inc
Normal file
@ -0,0 +1,60 @@
|
||||
|
||||
include '../../examples/x86/include/80386.inc'
|
||||
|
||||
macro format?.ELF? variant
|
||||
match , variant
|
||||
format binary as 'o'
|
||||
include '../../examples/x86/include/format/elf32.inc'
|
||||
use32
|
||||
else match =executable? settings, variant:
|
||||
match brand =at? base:, settings
|
||||
ELF.Settings.ABI = brand
|
||||
ELF.Settings.BaseAddress = base
|
||||
else match =at? base:, settings
|
||||
ELF.Settings.BaseAddress = base
|
||||
else match brand:, settings
|
||||
ELF.Settings.ABI = brand
|
||||
end match
|
||||
include '../../examples/x86/include/format/elfexe.inc'
|
||||
use32
|
||||
else
|
||||
err 'invalid argument'
|
||||
end match
|
||||
end macro
|
||||
|
||||
|
||||
macro struct? name
|
||||
macro ends?!
|
||||
end namespace
|
||||
esc end struc
|
||||
virtual at 0
|
||||
name name
|
||||
sizeof.name = $
|
||||
end virtual
|
||||
purge ends?
|
||||
end macro
|
||||
esc struc name
|
||||
label . : sizeof.name
|
||||
namespace .
|
||||
end macro
|
||||
|
||||
macro ccall? proc*,args&
|
||||
local size
|
||||
mov ebp,esp
|
||||
if size
|
||||
sub esp,size
|
||||
end if
|
||||
and esp,0FFFFFFF0h
|
||||
match any, args
|
||||
iterate arg, args
|
||||
mov dword [esp+(%-1)*4],arg
|
||||
if % = 1
|
||||
size := %%*4
|
||||
end if
|
||||
end iterate
|
||||
else
|
||||
size := 0
|
||||
end match
|
||||
call proc
|
||||
mov esp,ebp
|
||||
end macro
|
17
toolchain/fasmg.kl0e/source/libc/struct.inc
Normal file
17
toolchain/fasmg.kl0e/source/libc/struct.inc
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
macro struct name*
|
||||
{
|
||||
local body
|
||||
define body struc name \{
|
||||
irp d, db,rb,dw,rw,dd,rd,dq,rq \{ struc d value& \\{ define body \\\.\\#. d value \\} \}
|
||||
macro ends
|
||||
\{
|
||||
define body \\}
|
||||
irp d, db,rb,dw,rw,dd,rd,dq,rq \\{ restruc d \\}
|
||||
irpv line, body \\{ line \\}
|
||||
virtual at 0
|
||||
name name
|
||||
sizeof.#name = $
|
||||
end virtual
|
||||
\}
|
||||
}
|
225
toolchain/fasmg.kl0e/source/libc/system.inc
Normal file
225
toolchain/fasmg.kl0e/source/libc/system.inc
Normal file
@ -0,0 +1,225 @@
|
||||
|
||||
LINE_FEED = 0Ah
|
||||
|
||||
system_init:
|
||||
ccall libc.time,timestamp
|
||||
retn
|
||||
|
||||
system_shutdown:
|
||||
retn
|
||||
|
||||
malloc:
|
||||
malloc_fixed:
|
||||
malloc_growable:
|
||||
; in: ecx = requested size
|
||||
; out: eax - allocated block, ecx = allocated size, on error jumps to out_of_memory (does not return)
|
||||
; preserves: ebx, esi, edi
|
||||
; note:
|
||||
; use of malloc_fixed hints that block will be kept as is until the end of assembly
|
||||
; use of malloc_growable hints that block is likely to be resized
|
||||
push ebx ecx esi edi
|
||||
ccall libc.malloc,ecx
|
||||
pop edi esi ecx ebx
|
||||
test eax,eax
|
||||
jz out_of_memory
|
||||
retn
|
||||
realloc:
|
||||
; in: eax - memory block, ecx = requested size
|
||||
; out: eax - resized block, ecx = allocated size, on error jumps to out_of_memory (does not return)
|
||||
; preserves: ebx, esi, edi
|
||||
push ebx ecx esi edi
|
||||
ccall libc.realloc,eax,ecx
|
||||
pop edi esi ecx ebx
|
||||
test eax,eax
|
||||
jz out_of_memory
|
||||
retn
|
||||
mfree:
|
||||
; in: eax - memory block
|
||||
; out: cf set on error
|
||||
; preserves: ebx, esi, edi
|
||||
; note: eax may have value 0 or -1, it should be treated as invalid input then
|
||||
test eax,eax
|
||||
jz interface_error
|
||||
cmp eax,-1
|
||||
je interface_error
|
||||
push ebx esi edi
|
||||
ccall libc.free,eax
|
||||
pop edi esi ebx
|
||||
clc
|
||||
retn
|
||||
interface_error:
|
||||
stc
|
||||
retn
|
||||
|
||||
open:
|
||||
; in: edx - path to file
|
||||
; out: ebx = file handle, cf set on error
|
||||
; preserves: esi, edi
|
||||
push esi edi
|
||||
call adapt_path
|
||||
ccall libc.fopen,ebx,_open_mode
|
||||
pop edi esi
|
||||
test eax,eax
|
||||
jz interface_error
|
||||
mov ebx,eax
|
||||
clc
|
||||
retn
|
||||
adapt_path:
|
||||
xor ecx,ecx
|
||||
mov ebx,path_buffer
|
||||
copy_path:
|
||||
mov al,[edx+ecx]
|
||||
cmp al,'\'
|
||||
jne path_char_ok
|
||||
mov al,'/'
|
||||
path_char_ok:
|
||||
cmp ecx,1000h
|
||||
jae out_of_memory
|
||||
mov [ebx+ecx],al
|
||||
inc ecx
|
||||
test al,al
|
||||
jnz copy_path
|
||||
retn
|
||||
create:
|
||||
; in: edx - path to file
|
||||
; out: ebx = file handle, cf set on error
|
||||
; preserves: esi, edi
|
||||
push esi edi
|
||||
call adapt_path
|
||||
ccall libc.fopen,ebx,_create_mode
|
||||
pop edi esi
|
||||
test eax,eax
|
||||
jz interface_error
|
||||
mov ebx,eax
|
||||
clc
|
||||
retn
|
||||
write:
|
||||
; in: ebx = file handle, edx - data, ecx = number of bytes
|
||||
; out: cf set on error
|
||||
; preserves: ebx, esi, edi
|
||||
push ebx ecx esi edi
|
||||
ccall libc.fwrite,edx,1,ecx,ebx
|
||||
pop edi esi ecx ebx
|
||||
cmp eax,ecx
|
||||
jne interface_error
|
||||
clc
|
||||
ret
|
||||
read:
|
||||
; in: ebx = file handle, edx - buffer, ecx = number of bytes
|
||||
; out: cf set on error
|
||||
; preserves: ebx, esi, edi
|
||||
push ebx ecx esi edi
|
||||
ccall libc.fread,edx,1,ecx,ebx
|
||||
pop edi esi ecx ebx
|
||||
cmp eax,ecx
|
||||
jne interface_error
|
||||
clc
|
||||
ret
|
||||
close:
|
||||
; in: ebx = file handle
|
||||
; preserves: ebx, esi, edi
|
||||
ccall libc.fclose,ebx
|
||||
ret
|
||||
lseek:
|
||||
; in: ebx = file handle, cl = method, edx:eax = offset
|
||||
; out: edx:eax = new offset from the beginning of file, cf set on error
|
||||
; preserves: ebx, esi, edi
|
||||
test edx,edx
|
||||
jnz interface_error
|
||||
push esi edi ebx
|
||||
movzx ecx,cl
|
||||
ccall libc.fseek,ebx,eax,ecx
|
||||
test eax,eax
|
||||
jnz lseek_error
|
||||
mov ebx,[esp]
|
||||
ccall libc.ftell,ebx
|
||||
cmp eax,-1
|
||||
je lseek_error
|
||||
xor edx,edx
|
||||
pop ebx edi esi
|
||||
clc
|
||||
ret
|
||||
lseek_error:
|
||||
pop ebx edi esi
|
||||
stc
|
||||
ret
|
||||
|
||||
get_timestamp:
|
||||
; out: edx:eax = timestamp
|
||||
; preserves: ebx, ecx, esi, edi
|
||||
; note: during the passes of a single assembly this function should always return the same value
|
||||
mov eax,dword [timestamp]
|
||||
mov edx,dword [timestamp+4]
|
||||
retn
|
||||
|
||||
display_string:
|
||||
; in:
|
||||
; esi - string
|
||||
; ecx = string length, zero for ASCIIZ string
|
||||
; preserves: ebx, esi
|
||||
push ebx esi
|
||||
test ecx,ecx
|
||||
jnz write_string_to_stdout
|
||||
xor al,al
|
||||
mov edi,esi
|
||||
or ecx,-1
|
||||
repne scasb
|
||||
neg ecx
|
||||
sub ecx,2
|
||||
write_string_to_stdout:
|
||||
ccall libc.write,1,esi,ecx
|
||||
pop esi ebx
|
||||
retn
|
||||
|
||||
display_error_string:
|
||||
; in:
|
||||
; esi - string
|
||||
; ecx = string length, zero for ASCIIZ string
|
||||
; preserves: ebx, esi
|
||||
push ebx esi
|
||||
test ecx,ecx
|
||||
jnz write_string_to_stderr
|
||||
xor al,al
|
||||
mov edi,esi
|
||||
or ecx,-1
|
||||
repne scasb
|
||||
neg ecx
|
||||
sub ecx,2
|
||||
write_string_to_stderr:
|
||||
ccall libc.write,2,esi,ecx
|
||||
pop esi ebx
|
||||
retn
|
||||
|
||||
get_environment_variable:
|
||||
; in:
|
||||
; esi - name
|
||||
; edi - buffer for value
|
||||
; ecx = size of buffer
|
||||
; out:
|
||||
; eax = length of value
|
||||
; preserves: ebx, esi, edi
|
||||
push ebx ecx esi edi
|
||||
ccall getenv,esi
|
||||
pop edi esi ecx ebx
|
||||
test eax,eax
|
||||
jz no_environment_variable
|
||||
push esi
|
||||
mov esi,eax
|
||||
xor eax,eax
|
||||
copy_environment_variable:
|
||||
mov dl,[esi+eax]
|
||||
cmp eax,ecx
|
||||
jae next_environment_variable_character
|
||||
mov [edi+eax],dl
|
||||
next_environment_variable_character:
|
||||
inc eax
|
||||
test dl,dl
|
||||
jnz copy_environment_variable
|
||||
pop esi
|
||||
environment_variable_ok:
|
||||
ret
|
||||
no_environment_variable:
|
||||
mov eax,1
|
||||
jecxz environment_variable_ok
|
||||
and byte [edi],0
|
||||
ret
|
513
toolchain/fasmg.kl0e/source/linux/fasmg.asm
Normal file
513
toolchain/fasmg.kl0e/source/linux/fasmg.asm
Normal file
@ -0,0 +1,513 @@
|
||||
|
||||
match ,{
|
||||
|
||||
include '../libc/struct.inc'
|
||||
|
||||
} match -,{
|
||||
else
|
||||
|
||||
include 'selfhost.inc'
|
||||
|
||||
end match
|
||||
_ equ }
|
||||
|
||||
format ELF executable 3
|
||||
entry start
|
||||
|
||||
include '../version.inc'
|
||||
|
||||
struct timeval
|
||||
time_t dd ?
|
||||
suseconds_t dd ?
|
||||
ends
|
||||
|
||||
segment readable executable
|
||||
|
||||
start:
|
||||
|
||||
mov ecx,[esp]
|
||||
mov [argc],ecx
|
||||
lea ebx,[esp+4]
|
||||
mov [argv],ebx
|
||||
lea esi,[esp+4+ecx*4+4]
|
||||
mov [env],esi
|
||||
|
||||
call system_init
|
||||
|
||||
call get_arguments
|
||||
mov bl,al
|
||||
cmp [no_logo],0
|
||||
jne logo_ok
|
||||
mov esi,_logo
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
logo_ok:
|
||||
test bl,bl
|
||||
jnz display_usage_information
|
||||
|
||||
xor al,al
|
||||
mov ecx,[verbosity_level]
|
||||
jecxz init
|
||||
or al,TRACE_ERROR_STACK
|
||||
dec ecx
|
||||
jz init
|
||||
or al,TRACE_DISPLAY
|
||||
init:
|
||||
call assembly_init
|
||||
|
||||
mov eax,78 ; sys_gettimeofday
|
||||
mov ebx,start_time
|
||||
xor ecx,ecx
|
||||
int 0x80
|
||||
|
||||
assemble:
|
||||
mov esi,[initial_commands]
|
||||
mov edx,[source_path]
|
||||
call assembly_pass
|
||||
jc assembly_done
|
||||
|
||||
mov eax,[current_pass]
|
||||
cmp eax,[maximum_number_of_passes]
|
||||
jb assemble
|
||||
|
||||
call show_display_data
|
||||
|
||||
mov esi,_error_prefix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,_code_cannot_be_generated
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,_message_suffix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
|
||||
jmp assembly_failed
|
||||
|
||||
assembly_done:
|
||||
|
||||
call show_display_data
|
||||
|
||||
cmp [first_error],0
|
||||
jne assembly_failed
|
||||
|
||||
cmp [no_logo],0
|
||||
jne summary_done
|
||||
mov eax,[current_pass]
|
||||
xor edx,edx
|
||||
call itoa
|
||||
call display_string
|
||||
mov esi,_passes
|
||||
cmp [current_pass],1
|
||||
jne display_passes_suffix
|
||||
mov esi,_pass
|
||||
display_passes_suffix:
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
mov eax,78 ; sys_gettimeofday
|
||||
mov ebx,end_time
|
||||
xor ecx,ecx
|
||||
int 0x80
|
||||
mov eax,[end_time.time_t]
|
||||
sub eax,[start_time.time_t]
|
||||
mov ecx,1000000
|
||||
mul ecx
|
||||
add eax,[end_time.suseconds_t]
|
||||
adc edx,0
|
||||
sub eax,[start_time.suseconds_t]
|
||||
sbb edx,0
|
||||
add eax,50000
|
||||
mov ecx,1000000
|
||||
div ecx
|
||||
mov ebx,eax
|
||||
mov eax,edx
|
||||
xor edx,edx
|
||||
mov ecx,100000
|
||||
div ecx
|
||||
mov [tenths_of_second],eax
|
||||
xchg eax,ebx
|
||||
or ebx,eax
|
||||
jz display_output_length
|
||||
xor edx,edx
|
||||
call itoa
|
||||
call display_string
|
||||
mov esi,_message_suffix
|
||||
mov ecx,1
|
||||
call display_string
|
||||
mov eax,[tenths_of_second]
|
||||
xor edx,edx
|
||||
call itoa
|
||||
call display_string
|
||||
mov esi,_seconds
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
display_output_length:
|
||||
call get_output_length
|
||||
push eax edx
|
||||
call itoa
|
||||
call display_string
|
||||
pop edx eax
|
||||
mov esi,_bytes
|
||||
cmp eax,1
|
||||
jne display_bytes_suffix
|
||||
test edx,edx
|
||||
jnz display_bytes_suffix
|
||||
mov esi,_byte
|
||||
display_bytes_suffix:
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
mov esi,_new_line
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
summary_done:
|
||||
|
||||
mov ebx,[source_path]
|
||||
mov edi,[output_path]
|
||||
call write_output_file
|
||||
jc write_failed
|
||||
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
|
||||
xor ebx,ebx
|
||||
mov eax,1 ; sys_exit
|
||||
int 0x80
|
||||
|
||||
assembly_failed:
|
||||
|
||||
call show_errors
|
||||
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
|
||||
mov ebx,2
|
||||
mov eax,1 ; sys_exit
|
||||
int 0x80
|
||||
|
||||
write_failed:
|
||||
mov ebx,_write_failed
|
||||
jmp fatal_error
|
||||
|
||||
out_of_memory:
|
||||
mov ebx,_out_of_memory
|
||||
jmp fatal_error
|
||||
|
||||
fatal_error:
|
||||
|
||||
mov esi,_error_prefix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,ebx
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,_message_suffix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
|
||||
mov ebx,3
|
||||
mov eax,1 ; sys_exit
|
||||
int 0x80
|
||||
|
||||
display_usage_information:
|
||||
|
||||
mov esi,_usage
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
|
||||
call system_shutdown
|
||||
|
||||
mov ebx,1
|
||||
mov eax,1 ; sys_exit
|
||||
int 0x80
|
||||
|
||||
get_arguments:
|
||||
xor eax,eax
|
||||
mov [initial_commands],eax
|
||||
mov [source_path],eax
|
||||
mov [output_path],eax
|
||||
mov [no_logo],al
|
||||
mov [verbosity_level],eax
|
||||
mov [maximum_number_of_passes],100
|
||||
mov [maximum_number_of_errors],1
|
||||
mov [maximum_depth_of_stack],10000
|
||||
mov ecx,[argc]
|
||||
mov ebx,[argv]
|
||||
add ebx,4
|
||||
dec ecx
|
||||
jz error_in_arguments
|
||||
get_argument:
|
||||
mov esi,[ebx]
|
||||
mov al,[esi]
|
||||
cmp al,'-'
|
||||
je get_option
|
||||
cmp [source_path],0
|
||||
jne get_output_file
|
||||
mov [source_path],esi
|
||||
jmp next_argument
|
||||
get_output_file:
|
||||
cmp [output_path],0
|
||||
jne error_in_arguments
|
||||
mov [output_path],esi
|
||||
jmp next_argument
|
||||
get_option:
|
||||
inc esi
|
||||
lodsb
|
||||
cmp al,'e'
|
||||
je set_errors_limit
|
||||
cmp al,'E'
|
||||
je set_errors_limit
|
||||
cmp al,'i'
|
||||
je insert_initial_command
|
||||
cmp al,'I'
|
||||
je insert_initial_command
|
||||
cmp al,'p'
|
||||
je set_passes_limit
|
||||
cmp al,'P'
|
||||
je set_passes_limit
|
||||
cmp al,'r'
|
||||
je set_recursion_limit
|
||||
cmp al,'R'
|
||||
je set_recursion_limit
|
||||
cmp al,'v'
|
||||
je set_verbose_mode
|
||||
cmp al,'V'
|
||||
je set_verbose_mode
|
||||
cmp al,'n'
|
||||
je set_no_logo
|
||||
cmp al,'N'
|
||||
jne error_in_arguments
|
||||
set_no_logo:
|
||||
or [no_logo],-1
|
||||
cmp byte [esi],0
|
||||
je next_argument
|
||||
error_in_arguments:
|
||||
or al,-1
|
||||
ret
|
||||
set_verbose_mode:
|
||||
cmp byte [esi],0
|
||||
jne get_verbose_setting
|
||||
dec ecx
|
||||
jz error_in_arguments
|
||||
add ebx,4
|
||||
mov esi,[ebx]
|
||||
get_verbose_setting:
|
||||
call get_option_value
|
||||
cmp edx,2
|
||||
ja error_in_arguments
|
||||
mov [verbosity_level],edx
|
||||
jmp next_argument
|
||||
set_errors_limit:
|
||||
cmp byte [esi],0
|
||||
jne get_errors_setting
|
||||
dec ecx
|
||||
jz error_in_arguments
|
||||
add ebx,4
|
||||
mov esi,[ebx]
|
||||
get_errors_setting:
|
||||
call get_option_value
|
||||
test edx,edx
|
||||
jz error_in_arguments
|
||||
mov [maximum_number_of_errors],edx
|
||||
jmp next_argument
|
||||
set_recursion_limit:
|
||||
cmp byte [esi],0
|
||||
jne get_recursion_setting
|
||||
dec ecx
|
||||
jz error_in_arguments
|
||||
add ebx,4
|
||||
mov esi,[ebx]
|
||||
get_recursion_setting:
|
||||
call get_option_value
|
||||
test edx,edx
|
||||
jz error_in_arguments
|
||||
mov [maximum_depth_of_stack],edx
|
||||
jmp next_argument
|
||||
set_passes_limit:
|
||||
cmp byte [esi],0
|
||||
jne get_passes_setting
|
||||
dec ecx
|
||||
jz error_in_arguments
|
||||
add ebx,4
|
||||
mov esi,[ebx]
|
||||
get_passes_setting:
|
||||
call get_option_value
|
||||
test edx,edx
|
||||
jz error_in_arguments
|
||||
mov [maximum_number_of_passes],edx
|
||||
next_argument:
|
||||
add ebx,4
|
||||
dec ecx
|
||||
jnz get_argument
|
||||
cmp [source_path],0
|
||||
je error_in_arguments
|
||||
xor al,al
|
||||
ret
|
||||
get_option_value:
|
||||
xor eax,eax
|
||||
mov edx,eax
|
||||
find_option_value:
|
||||
cmp byte [esi],20h
|
||||
jne get_option_digit
|
||||
inc esi
|
||||
jmp find_option_value
|
||||
get_option_digit:
|
||||
lodsb
|
||||
test al,al
|
||||
jz option_value_ok
|
||||
sub al,30h
|
||||
jc invalid_option_value
|
||||
cmp al,9
|
||||
ja invalid_option_value
|
||||
imul edx,10
|
||||
jo invalid_option_value
|
||||
add edx,eax
|
||||
jc invalid_option_value
|
||||
jmp get_option_digit
|
||||
option_value_ok:
|
||||
dec esi
|
||||
clc
|
||||
ret
|
||||
invalid_option_value:
|
||||
stc
|
||||
ret
|
||||
insert_initial_command:
|
||||
cmp byte [esi],0
|
||||
jne measure_initial_command
|
||||
dec ecx
|
||||
jz error_in_arguments
|
||||
add ebx,4
|
||||
mov esi,[ebx]
|
||||
measure_initial_command:
|
||||
push ebx ecx edi
|
||||
mov edi,esi
|
||||
or ecx,-1
|
||||
xor al,al
|
||||
repne scasb
|
||||
not ecx
|
||||
dec ecx
|
||||
mov edi,[initial_commands]
|
||||
lea eax,[ecx+2]
|
||||
test edi,edi
|
||||
jz allocate_initial_commands_buffer
|
||||
mov edx,[initial_commands_length]
|
||||
add edi,edx
|
||||
add eax,edx
|
||||
cmp eax,[initial_commands_maximum_length]
|
||||
ja grow_initial_commands_buffer
|
||||
copy_initial_command:
|
||||
rep movsb
|
||||
mov ax,0Ah
|
||||
stosw
|
||||
dec edi
|
||||
sub edi,[initial_commands]
|
||||
mov [initial_commands_length],edi
|
||||
pop edi ecx ebx
|
||||
jmp next_argument
|
||||
allocate_initial_commands_buffer:
|
||||
push ecx
|
||||
mov ecx,eax
|
||||
call malloc
|
||||
mov [initial_commands],eax
|
||||
mov [initial_commands_maximum_length],ecx
|
||||
mov edi,eax
|
||||
pop ecx
|
||||
jmp copy_initial_command
|
||||
grow_initial_commands_buffer:
|
||||
push ecx
|
||||
mov ecx,eax
|
||||
mov eax,[initial_commands]
|
||||
call realloc
|
||||
mov [initial_commands],eax
|
||||
mov [initial_commands_maximum_length],ecx
|
||||
mov edi,eax
|
||||
add edi,[initial_commands_length]
|
||||
pop ecx
|
||||
jmp copy_initial_command
|
||||
|
||||
include 'system.inc'
|
||||
|
||||
include '../malloc.inc'
|
||||
include '../assembler.inc'
|
||||
include '../symbols.inc'
|
||||
include '../expressions.inc'
|
||||
include '../conditions.inc'
|
||||
include '../floats.inc'
|
||||
include '../directives.inc'
|
||||
include '../calm.inc'
|
||||
include '../errors.inc'
|
||||
include '../map.inc'
|
||||
include '../reader.inc'
|
||||
include '../output.inc'
|
||||
include '../console.inc'
|
||||
|
||||
segment readable
|
||||
|
||||
_logo db 'flat assembler version g.',VERSION,10,0
|
||||
|
||||
_usage db 'Usage: fasmg source [output]',10
|
||||
db 'Optional settings:',10
|
||||
db ' -p limit Set the maximum allowed number of passes (default 100)',10
|
||||
db ' -e limit Set the maximum number of displayed errors (default 1)',10
|
||||
db ' -r limit Set the maximum depth of the stack (default 10000)',10
|
||||
db ' -v flag Enable or disable showing all lines from the stack (default 0)',10
|
||||
db ' -i command Insert instruction at the beginning of source',13,10
|
||||
db ' -n Do not show logo nor summary',13,10
|
||||
db 0
|
||||
|
||||
_pass db ' pass, ',0
|
||||
_passes db ' passes, ',0
|
||||
_dot db '.'
|
||||
_seconds db ' seconds, ',0
|
||||
_byte db ' byte.',0
|
||||
_bytes db ' bytes.',0
|
||||
|
||||
_write_failed db 'failed to write the output file',0
|
||||
_out_of_memory db 'not enough memory to complete the assembly',0
|
||||
_code_cannot_be_generated db 'could not generate code within the allowed number of passes',0
|
||||
|
||||
_open_mode db 'r',0
|
||||
_create_mode db 'w',0
|
||||
|
||||
include '../tables.inc'
|
||||
include '../messages.inc'
|
||||
|
||||
segment readable writeable
|
||||
|
||||
align 16
|
||||
|
||||
include '../variables.inc'
|
||||
|
||||
align 16
|
||||
|
||||
timestamp dq ?
|
||||
|
||||
loff dq ?
|
||||
argc dd ?
|
||||
argv dd ?
|
||||
env dd ?
|
||||
|
||||
mmap_args rd 6
|
||||
malloc_freelist dd ?
|
||||
|
||||
source_path dd ?
|
||||
output_path dd ?
|
||||
maximum_number_of_passes dd ?
|
||||
|
||||
initial_commands dd ?
|
||||
initial_commands_length dd ?
|
||||
initial_commands_maximum_length dd ?
|
||||
|
||||
|
||||
start_time timeval
|
||||
end_time timeval
|
||||
tenths_of_second dd ?
|
||||
|
||||
verbosity_level dd ?
|
||||
no_logo db ?
|
||||
|
||||
path_buffer rb 1000h
|
||||
|
||||
segment readable writeable gnustack
|
59
toolchain/fasmg.kl0e/source/linux/selfhost.inc
Normal file
59
toolchain/fasmg.kl0e/source/linux/selfhost.inc
Normal file
@ -0,0 +1,59 @@
|
||||
|
||||
include '../../examples/x86/include/80386.inc'
|
||||
|
||||
macro format?.ELF? variant
|
||||
match , variant
|
||||
format binary as 'o'
|
||||
include '../../examples/x86/include/format/elf32.inc'
|
||||
use32
|
||||
else match =executable? settings, variant:
|
||||
match brand =at? base:, settings
|
||||
ELF.Settings.ABI = brand
|
||||
ELF.Settings.BaseAddress = base
|
||||
else match =at? base:, settings
|
||||
ELF.Settings.BaseAddress = base
|
||||
else match brand:, settings
|
||||
ELF.Settings.ABI = brand
|
||||
end match
|
||||
include '../../examples/x86/include/format/elfexe.inc'
|
||||
use32
|
||||
else
|
||||
err 'invalid argument'
|
||||
end match
|
||||
end macro
|
||||
|
||||
macro struct? name
|
||||
macro ends?!
|
||||
end namespace
|
||||
esc end struc
|
||||
virtual at 0
|
||||
name name
|
||||
sizeof.name = $
|
||||
end virtual
|
||||
purge ends?
|
||||
end macro
|
||||
esc struc name
|
||||
label . : sizeof.name
|
||||
namespace .
|
||||
end macro
|
||||
|
||||
macro cinvoke? proc*,args&
|
||||
local size
|
||||
mov ebp,esp
|
||||
if size
|
||||
sub esp,size
|
||||
end if
|
||||
and esp,0FFFFFFF0h
|
||||
match any, args
|
||||
iterate arg, args
|
||||
mov dword [esp+(%-1)*4],arg
|
||||
if % = 1
|
||||
size := %%*4
|
||||
end if
|
||||
end iterate
|
||||
else
|
||||
size := 0
|
||||
end match
|
||||
call [proc]
|
||||
mov esp,ebp
|
||||
end macro
|
298
toolchain/fasmg.kl0e/source/linux/system.inc
Normal file
298
toolchain/fasmg.kl0e/source/linux/system.inc
Normal file
@ -0,0 +1,298 @@
|
||||
|
||||
LINE_FEED = 0Ah
|
||||
|
||||
O_ACCMODE = 0003o
|
||||
O_RDONLY = 0000o
|
||||
O_WRONLY = 0001o
|
||||
O_RDWR = 0002o
|
||||
O_CREAT = 0100o
|
||||
O_EXCL = 0200o
|
||||
O_NOCTTY = 0400o
|
||||
O_TRUNC = 1000o
|
||||
O_APPEND = 2000o
|
||||
O_NONBLOCK = 4000o
|
||||
|
||||
S_ISUID = 4000o
|
||||
S_ISGID = 2000o
|
||||
S_ISVTX = 1000o
|
||||
S_IRUSR = 0400o
|
||||
S_IWUSR = 0200o
|
||||
S_IXUSR = 0100o
|
||||
S_IRGRP = 0040o
|
||||
S_IWGRP = 0020o
|
||||
S_IXGRP = 0010o
|
||||
S_IROTH = 0004o
|
||||
S_IWOTH = 0002o
|
||||
S_IXOTH = 0001o
|
||||
|
||||
system_init:
|
||||
mov eax,13 ; sys_time
|
||||
mov ebx,timestamp
|
||||
int 0x80
|
||||
retn
|
||||
|
||||
system_shutdown:
|
||||
retn
|
||||
|
||||
open:
|
||||
; in: edx - path to file
|
||||
; out: ebx = file handle, cf set on error
|
||||
; preserves: esi, edi
|
||||
push esi edi ebp
|
||||
call adapt_path
|
||||
mov eax,5 ; sys_open
|
||||
mov ecx,O_RDONLY
|
||||
xor edx,edx
|
||||
int 0x80
|
||||
pop ebp edi esi
|
||||
test eax,eax
|
||||
js interface_error
|
||||
mov ebx,eax
|
||||
clc
|
||||
retn
|
||||
adapt_path:
|
||||
xor ecx,ecx
|
||||
mov ebx,path_buffer
|
||||
copy_path:
|
||||
mov al,[edx+ecx]
|
||||
cmp al,'\'
|
||||
jne path_char_ok
|
||||
mov al,'/'
|
||||
path_char_ok:
|
||||
cmp ecx,1000h
|
||||
jae out_of_memory
|
||||
mov [ebx+ecx],al
|
||||
inc ecx
|
||||
test al,al
|
||||
jnz copy_path
|
||||
retn
|
||||
interface_error:
|
||||
stc
|
||||
retn
|
||||
create:
|
||||
; in: edx - path to file
|
||||
; out: ebx = file handle, cf set on error
|
||||
; preserves: esi, edi
|
||||
push esi edi ebp
|
||||
call adapt_path
|
||||
mov eax,5 ; sys_open
|
||||
mov ecx,O_CREAT+O_TRUNC+O_WRONLY
|
||||
mov edx,S_IRUSR+S_IWUSR+S_IRGRP+S_IROTH
|
||||
int 0x80
|
||||
pop ebp edi esi
|
||||
test eax,eax
|
||||
js interface_error
|
||||
mov ebx,eax
|
||||
clc
|
||||
retn
|
||||
write:
|
||||
; in: ebx = file handle, edx - data, ecx = number of bytes
|
||||
; out: cf set on error
|
||||
; preserves: ebx, esi, edi
|
||||
push ebx ecx esi edi ebp
|
||||
mov eax,4 ; sys_write
|
||||
xchg ecx,edx
|
||||
int 0x80
|
||||
pop ebp edi esi ecx ebx
|
||||
test eax,eax
|
||||
js interface_error
|
||||
cmp eax,ecx
|
||||
jne interface_error
|
||||
clc
|
||||
ret
|
||||
read:
|
||||
; in: ebx = file handle, edx - buffer, ecx = number of bytes
|
||||
; out: cf set on error
|
||||
; preserves: ebx, esi, edi
|
||||
push ebx ecx esi edi ebp
|
||||
mov eax,3 ; sys_read
|
||||
xchg ecx,edx
|
||||
int 0x80
|
||||
pop ebp edi esi ecx ebx
|
||||
test eax,eax
|
||||
js interface_error
|
||||
cmp eax,ecx
|
||||
jne interface_error
|
||||
clc
|
||||
ret
|
||||
close:
|
||||
; in: ebx = file handle
|
||||
; preserves: ebx, esi, edi
|
||||
push ebx esi edi ebp
|
||||
mov eax,6 ; sys_close
|
||||
int 0x80
|
||||
pop ebp edi esi ebx
|
||||
ret
|
||||
lseek:
|
||||
; in: ebx = file handle, cl = method, edx:eax = offset
|
||||
; out: edx:eax = new offset from the beginning of file, cf set on error
|
||||
; preserves: ebx, esi, edi
|
||||
test edx,edx
|
||||
jnz interface_error
|
||||
push esi edi ebx ebp
|
||||
movzx edi,cl
|
||||
mov ecx,edx
|
||||
mov edx,eax
|
||||
mov eax,140 ; sys_llseek
|
||||
mov esi,loff
|
||||
int 0x80
|
||||
pop ebp ebx edi esi
|
||||
test eax,eax
|
||||
js interface_error
|
||||
mov eax,dword [loff]
|
||||
mov edx,dword [loff+4]
|
||||
clc
|
||||
ret
|
||||
|
||||
get_timestamp:
|
||||
; out: edx:eax = timestamp
|
||||
; preserves: ebx, ecx, esi, edi
|
||||
; note: during the passes of a single assembly this function should always return the same value
|
||||
mov eax,dword [timestamp]
|
||||
mov edx,dword [timestamp+4]
|
||||
retn
|
||||
|
||||
display_string:
|
||||
; in:
|
||||
; esi - string
|
||||
; ecx = string length, zero for ASCIIZ string
|
||||
; preserves: ebx, esi
|
||||
push ebx esi ebp
|
||||
test ecx,ecx
|
||||
jnz write_string_to_stdout
|
||||
xor al,al
|
||||
mov edi,esi
|
||||
or ecx,-1
|
||||
repne scasb
|
||||
neg ecx
|
||||
sub ecx,2
|
||||
write_string_to_stdout:
|
||||
mov eax,4 ; sys_write
|
||||
mov ebx,1
|
||||
mov edx,ecx
|
||||
mov ecx,esi
|
||||
int 0x80
|
||||
pop ebp esi ebx
|
||||
retn
|
||||
|
||||
display_error_string:
|
||||
; in:
|
||||
; esi - string
|
||||
; ecx = string length, zero for ASCIIZ string
|
||||
; preserves: ebx, esi
|
||||
push ebx esi ebp
|
||||
test ecx,ecx
|
||||
jnz write_string_to_stderr
|
||||
xor al,al
|
||||
mov edi,esi
|
||||
or ecx,-1
|
||||
repne scasb
|
||||
neg ecx
|
||||
sub ecx,2
|
||||
write_string_to_stderr:
|
||||
mov eax,4 ; sys_write
|
||||
mov ebx,2
|
||||
mov edx,ecx
|
||||
mov ecx,esi
|
||||
int 0x80
|
||||
pop ebp esi ebx
|
||||
retn
|
||||
|
||||
get_environment_variable:
|
||||
; in:
|
||||
; esi - name
|
||||
; edi - buffer for value
|
||||
; ecx = size of buffer
|
||||
; out:
|
||||
; eax = length of value
|
||||
; preserves: ebx, esi, edi
|
||||
push ebx ecx
|
||||
mov edx,[env]
|
||||
scan_environment:
|
||||
mov ebx,[edx]
|
||||
test ebx,ebx
|
||||
jz no_environment_variable
|
||||
xor ecx,ecx
|
||||
compare_character:
|
||||
mov al,[ebx+ecx]
|
||||
mov ah,[esi+ecx]
|
||||
inc ecx
|
||||
cmp al,'='
|
||||
je end_of_variable_name
|
||||
test ah,ah
|
||||
jz next_variable
|
||||
sub ah,al
|
||||
je compare_character
|
||||
cmp ah,20h
|
||||
jne next_variable
|
||||
cmp al,'A'
|
||||
jb next_variable
|
||||
cmp al,'Z'
|
||||
jna compare_character
|
||||
next_variable:
|
||||
add edx,4
|
||||
jmp scan_environment
|
||||
end_of_variable_name:
|
||||
test ah,ah
|
||||
jnz next_variable
|
||||
add ebx,ecx
|
||||
pop ecx
|
||||
xor eax,eax
|
||||
copy_environment_variable:
|
||||
mov dl,[ebx+eax]
|
||||
cmp eax,ecx
|
||||
jae next_environment_variable_character
|
||||
mov [edi+eax],dl
|
||||
next_environment_variable_character:
|
||||
inc eax
|
||||
test dl,dl
|
||||
jnz copy_environment_variable
|
||||
environment_variable_ok:
|
||||
pop ebx
|
||||
ret
|
||||
no_environment_variable:
|
||||
pop ecx
|
||||
mov eax,1
|
||||
jecxz environment_variable_ok
|
||||
and byte [edi],0
|
||||
pop ebx
|
||||
ret
|
||||
|
||||
VALLOC_MINIMUM_SIZE = 100000h
|
||||
|
||||
valloc:
|
||||
; in: ecx = requested minimum size
|
||||
; out: eax - allocated block, ecx = allocated size, zero if failed
|
||||
; preserves: ebx, esi, edi
|
||||
cmp ecx,VALLOC_MINIMUM_SIZE
|
||||
jbe valloc_size_minimum
|
||||
dec ecx
|
||||
and ecx,(-1) shl 12
|
||||
add ecx,1 shl 12
|
||||
jmp valloc_size_ready
|
||||
valloc_size_minimum:
|
||||
mov ecx,VALLOC_MINIMUM_SIZE
|
||||
valloc_size_ready:
|
||||
push ebx edi
|
||||
mov ebx,mmap_args
|
||||
mov edi,ebx
|
||||
xor eax,eax
|
||||
stosd
|
||||
mov eax,ecx
|
||||
stosd
|
||||
mov eax,3 ; PROT_READ + PROT_WRITE
|
||||
stosd
|
||||
mov eax,22h ; MAP_PRIVATE + MAP_ANONYMOUS
|
||||
stosd
|
||||
or eax,-1
|
||||
stosd
|
||||
xor eax,eax
|
||||
stosd
|
||||
mov eax,0x5A ; old_mmap
|
||||
int 0x80
|
||||
cmp eax,-1
|
||||
jne valloc_ok
|
||||
xor ecx,ecx
|
||||
valloc_ok:
|
||||
pop edi ebx
|
||||
retn
|
124
toolchain/fasmg.kl0e/source/linux/x64/32on64.inc
Normal file
124
toolchain/fasmg.kl0e/source/linux/x64/32on64.inc
Normal file
@ -0,0 +1,124 @@
|
||||
|
||||
macro use32on64
|
||||
{
|
||||
|
||||
define esp rsp
|
||||
|
||||
define promote.eax rax
|
||||
define promote.ebx rbx
|
||||
define promote.ecx rcx
|
||||
define promote.edx rdx
|
||||
define promote.esi rsi
|
||||
define promote.edi rdi
|
||||
define promote.ebp rbp
|
||||
define promote.esp rsp
|
||||
|
||||
macro push args
|
||||
\{
|
||||
local list,arg,status
|
||||
define list
|
||||
define arg
|
||||
irps sym, args \\{
|
||||
define status
|
||||
match =dword, sym \\\{
|
||||
define status :
|
||||
\\\}
|
||||
match [any, status arg sym \\\{
|
||||
define arg [any
|
||||
match [mem], arg \\\\{
|
||||
match previous, list \\\\\{ define list previous,[mem] \\\\\}
|
||||
match , list \\\\\{ define list [mem] \\\\\}
|
||||
define arg
|
||||
\\\\}
|
||||
define status :
|
||||
\\\}
|
||||
match [, status arg sym \\\{
|
||||
define arg [
|
||||
define status :
|
||||
\\\}
|
||||
match , status \\\{
|
||||
match previous, list \\\\{ define list previous,sym \\\\}
|
||||
match , list \\\\{ define list sym \\\\}
|
||||
\\\}
|
||||
\\}
|
||||
match ops,list \\{
|
||||
irp op, ops \\\{
|
||||
if op eqtype eax
|
||||
push promote.\\\#op
|
||||
else
|
||||
mov r8d,op
|
||||
push r8
|
||||
end if
|
||||
\\\}
|
||||
\\}
|
||||
\}
|
||||
|
||||
macro pop args
|
||||
\{
|
||||
local list,arg,status
|
||||
define list
|
||||
define arg
|
||||
irps sym, args \\{
|
||||
define status
|
||||
match =dword, sym \\\{
|
||||
define status :
|
||||
\\\}
|
||||
match [any, status arg sym \\\{
|
||||
define arg [any
|
||||
match [mem], arg \\\\{
|
||||
match previous, list \\\\\{ define list previous,[mem] \\\\\}
|
||||
match , list \\\\\{ define list [mem] \\\\\}
|
||||
define arg
|
||||
\\\\}
|
||||
define status :
|
||||
\\\}
|
||||
match [, status arg sym \\\{
|
||||
define arg [
|
||||
define status :
|
||||
\\\}
|
||||
match , status \\\{
|
||||
match previous, list \\\\{ define list previous,sym \\\\}
|
||||
match , list \\\\{ define list sym \\\\}
|
||||
\\\}
|
||||
\\}
|
||||
match ops,list \\{
|
||||
irp op, ops \\\{
|
||||
if op eqtype eax
|
||||
pop promote.\\\#op
|
||||
else
|
||||
pop r8
|
||||
mov op,r8d
|
||||
end if
|
||||
\\\}
|
||||
\\}
|
||||
\}
|
||||
|
||||
irp instr, jmp,call
|
||||
\{
|
||||
macro instr op
|
||||
\\{
|
||||
if op eqtype [0]
|
||||
mov r8d,op
|
||||
instr r8
|
||||
else if op eqtype 0
|
||||
instr op
|
||||
else
|
||||
instr promote.\\#op
|
||||
end if
|
||||
\\}
|
||||
\}
|
||||
|
||||
macro jecxz target
|
||||
\{
|
||||
if target-($+1) < 80h & target-($+1) >= -80h
|
||||
jecxz target
|
||||
else
|
||||
local j,k
|
||||
jecxz j
|
||||
jmp k
|
||||
j: jmp target
|
||||
k:
|
||||
end if
|
||||
\}
|
||||
|
||||
}
|
545
toolchain/fasmg.kl0e/source/linux/x64/fasmg.asm
Normal file
545
toolchain/fasmg.kl0e/source/linux/x64/fasmg.asm
Normal file
@ -0,0 +1,545 @@
|
||||
|
||||
match ,{
|
||||
|
||||
include '../../libc/struct.inc'
|
||||
include '32on64.inc'
|
||||
|
||||
} match -,{
|
||||
else
|
||||
|
||||
include 'selfhost.inc'
|
||||
|
||||
end match
|
||||
_ equ }
|
||||
|
||||
format ELF64 executable 3
|
||||
entry start
|
||||
|
||||
include '../../version.inc'
|
||||
|
||||
struct timeval
|
||||
time_t dq ?
|
||||
suseconds_t dq ?
|
||||
ends
|
||||
|
||||
segment readable executable
|
||||
|
||||
start:
|
||||
|
||||
mov rcx,[rsp]
|
||||
mov [argc],rcx
|
||||
lea rbx,[rsp+8]
|
||||
mov [argv],rbx
|
||||
lea rsi,[rsp+8+rcx*8+8]
|
||||
mov [env],rsi
|
||||
|
||||
call system_init
|
||||
|
||||
call get_arguments
|
||||
mov bl,al
|
||||
cmp [no_logo],0
|
||||
jne logo_ok
|
||||
mov esi,_logo
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
logo_ok:
|
||||
test bl,bl
|
||||
jnz display_usage_information
|
||||
|
||||
xor al,al
|
||||
mov ecx,[verbosity_level]
|
||||
jecxz init
|
||||
or al,TRACE_ERROR_STACK
|
||||
dec ecx
|
||||
jz init
|
||||
or al,TRACE_DISPLAY
|
||||
init:
|
||||
call assembly_init
|
||||
|
||||
mov eax,96 ; sys_gettimeofday
|
||||
mov edi,start_time
|
||||
xor esi,esi
|
||||
syscall
|
||||
|
||||
assemble:
|
||||
mov esi,[initial_commands]
|
||||
mov edx,[source_path]
|
||||
call assembly_pass
|
||||
jc assembly_done
|
||||
|
||||
mov eax,[current_pass]
|
||||
cmp eax,[maximum_number_of_passes]
|
||||
jb assemble
|
||||
|
||||
call show_display_data
|
||||
|
||||
mov esi,_error_prefix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,_code_cannot_be_generated
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,_message_suffix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
|
||||
jmp assembly_failed
|
||||
|
||||
assembly_done:
|
||||
|
||||
call show_display_data
|
||||
|
||||
cmp [first_error],0
|
||||
jne assembly_failed
|
||||
|
||||
cmp [no_logo],0
|
||||
jne summary_done
|
||||
mov eax,[current_pass]
|
||||
xor edx,edx
|
||||
call itoa
|
||||
call display_string
|
||||
mov esi,_passes
|
||||
cmp [current_pass],1
|
||||
jne display_passes_suffix
|
||||
mov esi,_pass
|
||||
display_passes_suffix:
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
mov eax,96 ; sys_gettimeofday
|
||||
mov edi,end_time
|
||||
xor esi,esi
|
||||
syscall
|
||||
mov rax,[end_time.time_t]
|
||||
sub rax,[start_time.time_t]
|
||||
mov rcx,1000000
|
||||
mul rcx
|
||||
add rax,[end_time.suseconds_t]
|
||||
adc rdx,0
|
||||
sub rax,[start_time.suseconds_t]
|
||||
sbb rdx,0
|
||||
add rax,50000
|
||||
mov rcx,1000000
|
||||
div rcx
|
||||
mov rbx,rax
|
||||
mov rax,rdx
|
||||
xor rdx,rdx
|
||||
mov rcx,100000
|
||||
div rcx
|
||||
mov [tenths_of_second],eax
|
||||
xchg rax,rbx
|
||||
or rbx,rax
|
||||
jz display_output_length
|
||||
mov rdx,rax
|
||||
shr rdx,32
|
||||
call itoa
|
||||
call display_string
|
||||
mov esi,_message_suffix
|
||||
mov ecx,1
|
||||
call display_string
|
||||
mov eax,[tenths_of_second]
|
||||
xor edx,edx
|
||||
call itoa
|
||||
call display_string
|
||||
mov esi,_seconds
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
display_output_length:
|
||||
call get_output_length
|
||||
push rax rdx
|
||||
call itoa
|
||||
call display_string
|
||||
pop rdx rax
|
||||
mov esi,_bytes
|
||||
cmp eax,1
|
||||
jne display_bytes_suffix
|
||||
test edx,edx
|
||||
jnz display_bytes_suffix
|
||||
mov esi,_byte
|
||||
display_bytes_suffix:
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
mov esi,_new_line
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
summary_done:
|
||||
|
||||
mov ebx,[source_path]
|
||||
mov edi,[output_path]
|
||||
call write_output_file
|
||||
jc write_failed
|
||||
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
|
||||
xor edi,edi ; exit code 0
|
||||
mov eax,60 ; sys_exit
|
||||
syscall
|
||||
|
||||
assembly_failed:
|
||||
|
||||
call show_errors
|
||||
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
|
||||
mov edi,2
|
||||
mov eax,60 ; sys_exit
|
||||
syscall
|
||||
|
||||
write_failed:
|
||||
mov ebx,_write_failed
|
||||
jmp fatal_error
|
||||
|
||||
out_of_memory:
|
||||
mov ebx,_out_of_memory
|
||||
jmp fatal_error
|
||||
|
||||
fatal_error:
|
||||
|
||||
mov esi,_error_prefix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,ebx
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,_message_suffix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
|
||||
mov edi,3
|
||||
mov eax,60 ; sys_exit
|
||||
syscall
|
||||
|
||||
internal_error:
|
||||
int3
|
||||
|
||||
display_usage_information:
|
||||
|
||||
mov esi,_usage
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
|
||||
call system_shutdown
|
||||
|
||||
mov edi,1
|
||||
mov eax,60 ; sys_exit
|
||||
syscall
|
||||
|
||||
get_arguments:
|
||||
xor eax,eax
|
||||
mov [initial_commands],eax
|
||||
mov [source_path],eax
|
||||
mov [output_path],eax
|
||||
mov [no_logo],al
|
||||
mov [verbosity_level],eax
|
||||
mov [maximum_number_of_passes],100
|
||||
mov [maximum_number_of_errors],1
|
||||
mov [maximum_depth_of_stack],10000
|
||||
mov rcx,[argc]
|
||||
mov rbx,[argv]
|
||||
add rbx,8
|
||||
dec ecx
|
||||
jz error_in_arguments
|
||||
get_argument:
|
||||
mov rsi,[rbx]
|
||||
mov al,[rsi]
|
||||
cmp al,'-'
|
||||
je get_option
|
||||
cmp [source_path],0
|
||||
jne get_output_file
|
||||
call strdup
|
||||
mov [source_path],eax
|
||||
jmp next_argument
|
||||
get_output_file:
|
||||
cmp [output_path],0
|
||||
jne error_in_arguments
|
||||
call strdup
|
||||
mov [output_path],eax
|
||||
jmp next_argument
|
||||
get_option:
|
||||
inc rsi
|
||||
lodsb
|
||||
cmp al,'e'
|
||||
je set_errors_limit
|
||||
cmp al,'E'
|
||||
je set_errors_limit
|
||||
cmp al,'i'
|
||||
je insert_initial_command
|
||||
cmp al,'I'
|
||||
je insert_initial_command
|
||||
cmp al,'p'
|
||||
je set_passes_limit
|
||||
cmp al,'P'
|
||||
je set_passes_limit
|
||||
cmp al,'r'
|
||||
je set_recursion_limit
|
||||
cmp al,'R'
|
||||
je set_recursion_limit
|
||||
cmp al,'v'
|
||||
je set_verbose_mode
|
||||
cmp al,'V'
|
||||
je set_verbose_mode
|
||||
cmp al,'n'
|
||||
je set_no_logo
|
||||
cmp al,'N'
|
||||
jne error_in_arguments
|
||||
set_no_logo:
|
||||
or [no_logo],-1
|
||||
cmp byte [rsi],0
|
||||
je next_argument
|
||||
error_in_arguments:
|
||||
or al,-1
|
||||
ret
|
||||
set_verbose_mode:
|
||||
cmp byte [rsi],0
|
||||
jne get_verbose_setting
|
||||
dec ecx
|
||||
jz error_in_arguments
|
||||
add rbx,8
|
||||
mov rsi,[rbx]
|
||||
get_verbose_setting:
|
||||
call get_option_value
|
||||
cmp edx,2
|
||||
ja error_in_arguments
|
||||
mov [verbosity_level],edx
|
||||
jmp next_argument
|
||||
set_errors_limit:
|
||||
cmp byte [rsi],0
|
||||
jne get_errors_setting
|
||||
dec ecx
|
||||
jz error_in_arguments
|
||||
add rbx,8
|
||||
mov rsi,[rbx]
|
||||
get_errors_setting:
|
||||
call get_option_value
|
||||
test edx,edx
|
||||
jz error_in_arguments
|
||||
mov [maximum_number_of_errors],edx
|
||||
jmp next_argument
|
||||
set_recursion_limit:
|
||||
cmp byte [rsi],0
|
||||
jne get_recursion_setting
|
||||
dec ecx
|
||||
jz error_in_arguments
|
||||
add rbx,8
|
||||
mov rsi,[rbx]
|
||||
get_recursion_setting:
|
||||
call get_option_value
|
||||
test edx,edx
|
||||
jz error_in_arguments
|
||||
mov [maximum_depth_of_stack],edx
|
||||
jmp next_argument
|
||||
set_passes_limit:
|
||||
cmp byte [rsi],0
|
||||
jne get_passes_setting
|
||||
dec ecx
|
||||
jz error_in_arguments
|
||||
add rbx,8
|
||||
mov rsi,[rbx]
|
||||
get_passes_setting:
|
||||
call get_option_value
|
||||
test edx,edx
|
||||
jz error_in_arguments
|
||||
mov [maximum_number_of_passes],edx
|
||||
next_argument:
|
||||
add rbx,8
|
||||
dec ecx
|
||||
jnz get_argument
|
||||
cmp [source_path],0
|
||||
je error_in_arguments
|
||||
xor al,al
|
||||
ret
|
||||
get_option_value:
|
||||
xor eax,eax
|
||||
mov edx,eax
|
||||
find_option_value:
|
||||
cmp byte [rsi],20h
|
||||
jne get_option_digit
|
||||
inc rsi
|
||||
jmp find_option_value
|
||||
get_option_digit:
|
||||
lodsb
|
||||
test al,al
|
||||
jz option_value_ok
|
||||
sub al,30h
|
||||
jc invalid_option_value
|
||||
cmp al,9
|
||||
ja invalid_option_value
|
||||
imul edx,10
|
||||
jo invalid_option_value
|
||||
add edx,eax
|
||||
jc invalid_option_value
|
||||
jmp get_option_digit
|
||||
option_value_ok:
|
||||
dec rsi
|
||||
clc
|
||||
ret
|
||||
invalid_option_value:
|
||||
stc
|
||||
ret
|
||||
insert_initial_command:
|
||||
cmp byte [rsi],0
|
||||
jne measure_initial_command
|
||||
dec ecx
|
||||
jz error_in_arguments
|
||||
add rbx,8
|
||||
mov rsi,[rbx]
|
||||
measure_initial_command:
|
||||
push rbx rcx rdi
|
||||
mov rdi,rsi
|
||||
or ecx,-1
|
||||
xor al,al
|
||||
repne scasb
|
||||
not ecx
|
||||
dec ecx
|
||||
mov edi,[initial_commands]
|
||||
lea eax,[ecx+2]
|
||||
test edi,edi
|
||||
jz allocate_initial_commands_buffer
|
||||
mov edx,[initial_commands_length]
|
||||
add edi,edx
|
||||
add eax,edx
|
||||
cmp eax,[initial_commands_maximum_length]
|
||||
ja grow_initial_commands_buffer
|
||||
copy_initial_command:
|
||||
rep movsb
|
||||
mov ax,0Ah
|
||||
stosw
|
||||
dec edi
|
||||
sub edi,[initial_commands]
|
||||
mov [initial_commands_length],edi
|
||||
pop rdi rcx rbx
|
||||
jmp next_argument
|
||||
allocate_initial_commands_buffer:
|
||||
push rsi rcx
|
||||
mov ecx,eax
|
||||
call malloc
|
||||
mov [initial_commands],eax
|
||||
mov [initial_commands_maximum_length],ecx
|
||||
mov edi,eax
|
||||
pop rcx rsi
|
||||
jmp copy_initial_command
|
||||
grow_initial_commands_buffer:
|
||||
push rsi rcx
|
||||
mov ecx,eax
|
||||
mov eax,[initial_commands]
|
||||
call realloc
|
||||
mov [initial_commands],eax
|
||||
mov [initial_commands_maximum_length],ecx
|
||||
mov edi,eax
|
||||
add edi,[initial_commands_length]
|
||||
pop rcx rsi
|
||||
jmp copy_initial_command
|
||||
|
||||
strdup:
|
||||
; in: rsi - ASCIIZ string
|
||||
; out: eax - copy of the string in 32-bit addressable memory
|
||||
; preserves: rbx, rcx, rsi
|
||||
push rbx rcx rsi
|
||||
mov rdi,rsi
|
||||
or ecx,-1
|
||||
xor al,al
|
||||
repne scasb
|
||||
not ecx
|
||||
push rsi rcx
|
||||
call malloc
|
||||
pop rcx rsi
|
||||
mov edi,eax
|
||||
rep movsb
|
||||
pop rsi rcx rbx
|
||||
ret
|
||||
|
||||
include 'system.inc'
|
||||
|
||||
use32on64
|
||||
|
||||
include '../../malloc.inc'
|
||||
include '../../assembler.inc'
|
||||
include '../../symbols.inc'
|
||||
include '../../expressions.inc'
|
||||
include '../../conditions.inc'
|
||||
include '../../floats.inc'
|
||||
include '../../directives.inc'
|
||||
include '../../calm.inc'
|
||||
include '../../errors.inc'
|
||||
include '../../map.inc'
|
||||
include '../../reader.inc'
|
||||
include '../../output.inc'
|
||||
include '../../console.inc'
|
||||
|
||||
segment readable
|
||||
|
||||
_logo db 'flat assembler version g.',VERSION,10,0
|
||||
|
||||
_usage db 'Usage: fasmg source [output]',10
|
||||
db 'Optional settings:',10
|
||||
db ' -p limit Set the maximum allowed number of passes (default 100)',10
|
||||
db ' -e limit Set the maximum number of displayed errors (default 1)',10
|
||||
db ' -r limit Set the maximum depth of the stack (default 10000)',10
|
||||
db ' -v flag Enable or disable showing all lines from the stack (default 0)',10
|
||||
db ' -i command Insert instruction at the beginning of source',13,10
|
||||
db ' -n Do not show logo nor summary',13,10
|
||||
db 0
|
||||
|
||||
_pass db ' pass, ',0
|
||||
_passes db ' passes, ',0
|
||||
_dot db '.'
|
||||
_seconds db ' seconds, ',0
|
||||
_byte db ' byte.',0
|
||||
_bytes db ' bytes.',0
|
||||
|
||||
_write_failed db 'failed to write the output file',0
|
||||
_out_of_memory db 'not enough memory to complete the assembly',0
|
||||
_code_cannot_be_generated db 'could not generate code within the allowed number of passes',0
|
||||
|
||||
include '../../tables.inc'
|
||||
include '../../messages.inc'
|
||||
|
||||
segment readable writeable
|
||||
|
||||
align 16
|
||||
|
||||
include '../../variables.inc'
|
||||
|
||||
align 16
|
||||
|
||||
timestamp dq ?
|
||||
|
||||
argc dq ?
|
||||
argv dq ?
|
||||
env dq ?
|
||||
|
||||
mmap_hint dd ?
|
||||
malloc_freelist dd ?
|
||||
|
||||
source_path dd ?
|
||||
output_path dd ?
|
||||
maximum_number_of_passes dd ?
|
||||
|
||||
initial_commands dd ?
|
||||
initial_commands_length dd ?
|
||||
initial_commands_maximum_length dd ?
|
||||
|
||||
start_time timeval
|
||||
end_time timeval
|
||||
tenths_of_second dd ?
|
||||
|
||||
verbosity_level dd ?
|
||||
no_logo db ?
|
||||
|
||||
local_heap_available db ?
|
||||
|
||||
path_buffer rb 1000h
|
||||
|
||||
segment readable writeable
|
||||
|
||||
align 1000h
|
||||
|
||||
LOCAL_HEAP_SIZE = 1000000h
|
||||
|
||||
local_heap rb LOCAL_HEAP_SIZE
|
||||
|
||||
segment readable writeable gnustack
|
120
toolchain/fasmg.kl0e/source/linux/x64/selfhost.inc
Normal file
120
toolchain/fasmg.kl0e/source/linux/x64/selfhost.inc
Normal file
@ -0,0 +1,120 @@
|
||||
|
||||
include '../../../examples/x86/include/x64.inc'
|
||||
|
||||
macro format?.ELF64? variant
|
||||
match , variant
|
||||
format binary as 'o'
|
||||
include '../../../examples/x86/include/format/elf64.inc'
|
||||
use64
|
||||
else match =executable? settings, variant:
|
||||
ELF.Settings.Class = ELFCLASS64
|
||||
ELF.Settings.Machine = EM_X86_64
|
||||
ELF.Settings.BaseAddress = 400000h
|
||||
match brand =at? base:, settings
|
||||
ELF.Settings.ABI = brand
|
||||
ELF.Settings.BaseAddress = base
|
||||
else match =at? base:, settings
|
||||
ELF.Settings.BaseAddress = base
|
||||
else match brand:, settings
|
||||
ELF.Settings.ABI = brand
|
||||
end match
|
||||
include '../../../examples/x86/include/format/elfexe.inc'
|
||||
use64
|
||||
else
|
||||
err 'invalid argument'
|
||||
end match
|
||||
end macro
|
||||
|
||||
macro struct? name
|
||||
macro ends?!
|
||||
end namespace
|
||||
esc end struc
|
||||
virtual at 0
|
||||
name name
|
||||
sizeof.name = $
|
||||
end virtual
|
||||
purge ends?
|
||||
end macro
|
||||
esc struc name
|
||||
label . : sizeof.name
|
||||
namespace .
|
||||
end macro
|
||||
|
||||
macro use32on64?
|
||||
|
||||
define esp rsp
|
||||
|
||||
define promote
|
||||
|
||||
iterate <reg32,reg64>, eax,rax, ebx,rbx, ecx,rcx, edx,rdx, esi,rsi, edi,rdi, esp,rsp, ebp,rbp
|
||||
promote.reg32? equ reg64
|
||||
end iterate
|
||||
|
||||
iterate instr, jmp,call
|
||||
calminstruction instr? arg
|
||||
local tmp
|
||||
match [tmp], arg
|
||||
jyes zero_extend
|
||||
transform arg, promote
|
||||
arrange tmp, =instr arg
|
||||
assemble tmp
|
||||
exit
|
||||
zero_extend:
|
||||
arrange tmp, =mov =r8d,[tmp]
|
||||
assemble tmp
|
||||
arrange tmp, =instr =r8
|
||||
assemble tmp
|
||||
end calminstruction
|
||||
end iterate
|
||||
|
||||
calminstruction push? arg
|
||||
local car, cdr
|
||||
match car cdr?, arg
|
||||
loop:
|
||||
transform car, promote
|
||||
jno non_reg
|
||||
arrange car, =push car
|
||||
assemble car
|
||||
match car cdr?, cdr
|
||||
jyes loop
|
||||
exit
|
||||
non_reg:
|
||||
arrange tmp, =mov =r8d,arg
|
||||
assemble tmp
|
||||
arrange tmp, =push =r8
|
||||
assemble tmp
|
||||
exit
|
||||
end calminstruction
|
||||
|
||||
calminstruction pop? arg
|
||||
local car, cdr
|
||||
match car cdr?, arg
|
||||
loop:
|
||||
transform car, promote
|
||||
jno non_reg
|
||||
arrange car, =pop car
|
||||
assemble car
|
||||
match car cdr?, cdr
|
||||
jyes loop
|
||||
exit
|
||||
non_reg:
|
||||
arrange tmp, =pop =r8
|
||||
assemble tmp
|
||||
arrange tmp, =mov arg,=r8d
|
||||
assemble tmp
|
||||
exit
|
||||
end calminstruction
|
||||
|
||||
macro jecxz? target
|
||||
if target-($+1) < 80h & target-($+1) >= -80h
|
||||
jecxz target
|
||||
else
|
||||
local j,k
|
||||
jecxz j
|
||||
jmp k
|
||||
j: jmp target
|
||||
k:
|
||||
end if
|
||||
end macro
|
||||
|
||||
end macro
|
334
toolchain/fasmg.kl0e/source/linux/x64/system.inc
Normal file
334
toolchain/fasmg.kl0e/source/linux/x64/system.inc
Normal file
@ -0,0 +1,334 @@
|
||||
|
||||
LINE_FEED = 0Ah
|
||||
|
||||
O_ACCMODE = 0003o
|
||||
O_RDONLY = 0000o
|
||||
O_WRONLY = 0001o
|
||||
O_RDWR = 0002o
|
||||
O_CREAT = 0100o
|
||||
O_EXCL = 0200o
|
||||
O_NOCTTY = 0400o
|
||||
O_TRUNC = 1000o
|
||||
O_APPEND = 2000o
|
||||
O_NONBLOCK = 4000o
|
||||
|
||||
S_ISUID = 4000o
|
||||
S_ISGID = 2000o
|
||||
S_ISVTX = 1000o
|
||||
S_IRUSR = 0400o
|
||||
S_IWUSR = 0200o
|
||||
S_IXUSR = 0100o
|
||||
S_IRGRP = 0040o
|
||||
S_IWGRP = 0020o
|
||||
S_IXGRP = 0010o
|
||||
S_IROTH = 0004o
|
||||
S_IWOTH = 0002o
|
||||
S_IXOTH = 0001o
|
||||
|
||||
system_init:
|
||||
mov eax,201 ; sys_time
|
||||
mov edi,timestamp
|
||||
syscall
|
||||
or [local_heap_available],1
|
||||
retn
|
||||
|
||||
system_shutdown:
|
||||
call mcheck
|
||||
retn
|
||||
|
||||
open:
|
||||
; in: edx - path to file
|
||||
; out: ebx = file handle, cf set on error
|
||||
; preserves: esi, edi
|
||||
push rsi rdi
|
||||
call adapt_path
|
||||
mov eax,2 ; sys_open
|
||||
mov esi,O_RDONLY
|
||||
xor edx,edx
|
||||
syscall
|
||||
pop rdi rsi
|
||||
test eax,eax
|
||||
js interface_error
|
||||
mov ebx,eax
|
||||
clc
|
||||
ret
|
||||
interface_error:
|
||||
stc
|
||||
ret
|
||||
adapt_path:
|
||||
xor ecx,ecx
|
||||
mov edi,path_buffer
|
||||
copy_path:
|
||||
mov al,[edx+ecx]
|
||||
cmp al,'\'
|
||||
jne path_char_ok
|
||||
mov al,'/'
|
||||
path_char_ok:
|
||||
cmp ecx,1000h
|
||||
jae out_of_memory
|
||||
mov [edi+ecx],al
|
||||
inc ecx
|
||||
test al,al
|
||||
jnz copy_path
|
||||
retn
|
||||
create:
|
||||
; in: edx - path to file
|
||||
; out: ebx = file handle, cf set on error
|
||||
; preserves: esi, edi
|
||||
push rsi rdi
|
||||
call adapt_path
|
||||
mov esi,O_CREAT+O_TRUNC+O_WRONLY
|
||||
mov edx,S_IRUSR+S_IWUSR+S_IRGRP+S_IROTH
|
||||
mov eax,2 ; sys_open
|
||||
syscall
|
||||
pop rdi rsi
|
||||
test eax,eax
|
||||
js interface_error
|
||||
mov ebx,eax
|
||||
clc
|
||||
retn
|
||||
write:
|
||||
; in: ebx = file handle, edx - data, ecx = number of bytes
|
||||
; out: cf set on error
|
||||
; preserves: ebx, esi, edi
|
||||
push rsi rdi
|
||||
mov eax,1 ; sys_write
|
||||
mov edi,ebx
|
||||
mov esi,edx
|
||||
mov edx,ecx
|
||||
syscall
|
||||
pop rdi rsi
|
||||
test eax,eax
|
||||
js interface_error
|
||||
cmp eax,edx
|
||||
jne interface_error
|
||||
clc
|
||||
ret
|
||||
read:
|
||||
; in: ebx = file handle, edx - buffer, ecx = number of bytes
|
||||
; out: cf set on error
|
||||
; preserves: ebx, esi, edi
|
||||
push rsi rdi
|
||||
mov eax,0 ; sys_read
|
||||
mov edi,ebx
|
||||
mov esi,edx
|
||||
mov edx,ecx
|
||||
syscall
|
||||
pop rdi rsi
|
||||
test eax,eax
|
||||
js interface_error
|
||||
cmp eax,edx
|
||||
jne interface_error
|
||||
clc
|
||||
ret
|
||||
close:
|
||||
; in: ebx = file handle
|
||||
; preserves: ebx, esi, edi
|
||||
push rdi
|
||||
mov edi,ebx
|
||||
mov eax,3 ; sys_close
|
||||
syscall
|
||||
pop rdi
|
||||
ret
|
||||
lseek:
|
||||
; in: ebx = file handle, cl = method, edx:eax = offset
|
||||
; out: edx:eax = new offset from the beginning of file, cf set on error
|
||||
; preserves: ebx, esi, edi
|
||||
push rsi rdi
|
||||
mov edi,ebx
|
||||
mov esi,edx
|
||||
mov eax,eax
|
||||
shl rsi,32
|
||||
or rsi,rax
|
||||
xor edx,edx
|
||||
mov dl,cl
|
||||
mov eax,8 ; sys_lseek
|
||||
syscall
|
||||
pop rdi rsi
|
||||
cmp rax,-1
|
||||
je interface_error
|
||||
mov rdx,rax
|
||||
shr rdx,32
|
||||
clc
|
||||
ret
|
||||
|
||||
get_timestamp:
|
||||
; out: edx:eax = timestamp
|
||||
; preserves: ebx, ecx, esi, edi
|
||||
; note: during the passes of a single assembly this function should always return the same value
|
||||
mov eax,dword [timestamp]
|
||||
mov edx,dword [timestamp+4]
|
||||
retn
|
||||
|
||||
display_string:
|
||||
; in:
|
||||
; esi - string
|
||||
; ecx = string length, zero for ASCIIZ string
|
||||
; preserves: ebx, esi
|
||||
push rbx rsi rbp
|
||||
test ecx,ecx
|
||||
jnz write_string_to_stdout
|
||||
xor al,al
|
||||
mov edi,esi
|
||||
or ecx,-1
|
||||
repne scasb
|
||||
neg ecx
|
||||
sub ecx,2
|
||||
write_string_to_stdout:
|
||||
mov eax,1 ; sys_write
|
||||
mov edi,1
|
||||
mov edx,ecx
|
||||
syscall
|
||||
pop rbp rsi rbx
|
||||
retn
|
||||
|
||||
display_error_string:
|
||||
; in:
|
||||
; esi - string
|
||||
; ecx = string length, zero for ASCIIZ string
|
||||
; preserves: ebx, esi
|
||||
push rbx rsi rbp
|
||||
test ecx,ecx
|
||||
jnz write_string_to_stderr
|
||||
xor al,al
|
||||
mov edi,esi
|
||||
or ecx,-1
|
||||
repne scasb
|
||||
neg ecx
|
||||
sub ecx,2
|
||||
write_string_to_stderr:
|
||||
mov eax,1 ; sys_write
|
||||
mov edi,2
|
||||
mov edx,ecx
|
||||
syscall
|
||||
pop rbp rsi rbx
|
||||
retn
|
||||
|
||||
get_environment_variable:
|
||||
; in:
|
||||
; esi - name
|
||||
; edi - buffer for value
|
||||
; ecx = size of buffer
|
||||
; out:
|
||||
; eax = length of value
|
||||
; preserves: ebx, esi, edi
|
||||
push rbx rcx
|
||||
mov rdx,[env]
|
||||
scan_environment:
|
||||
mov rbx,[rdx]
|
||||
test rbx,rbx
|
||||
jz no_environment_variable
|
||||
xor ecx,ecx
|
||||
compare_character:
|
||||
mov al,[rbx+rcx]
|
||||
mov ah,[esi+ecx]
|
||||
inc ecx
|
||||
cmp al,'='
|
||||
je end_of_variable_name
|
||||
test ah,ah
|
||||
jz next_variable
|
||||
sub ah,al
|
||||
je compare_character
|
||||
cmp ah,20h
|
||||
jne next_variable
|
||||
cmp al,'A'
|
||||
jb next_variable
|
||||
cmp al,'Z'
|
||||
jna compare_character
|
||||
next_variable:
|
||||
add rdx,8
|
||||
jmp scan_environment
|
||||
end_of_variable_name:
|
||||
test ah,ah
|
||||
jnz next_variable
|
||||
add rbx,rcx
|
||||
pop rcx
|
||||
xor eax,eax
|
||||
copy_environment_variable:
|
||||
mov dl,[rbx+rax]
|
||||
cmp eax,ecx
|
||||
jae next_environment_variable_character
|
||||
mov [edi+eax],dl
|
||||
next_environment_variable_character:
|
||||
inc eax
|
||||
test dl,dl
|
||||
jnz copy_environment_variable
|
||||
environment_variable_ok:
|
||||
pop rbx
|
||||
ret
|
||||
no_environment_variable:
|
||||
pop rcx
|
||||
mov eax,1
|
||||
jecxz environment_variable_ok
|
||||
and byte [edi],0
|
||||
pop rbx
|
||||
ret
|
||||
|
||||
VALLOC_MINIMUM_SIZE = 100000h
|
||||
|
||||
valloc:
|
||||
; in: ecx = requested minimum size
|
||||
; out: eax - allocated block, ecx = allocated size, zero if failed
|
||||
; preserves: ebx, esi, edi
|
||||
cmp ecx,VALLOC_MINIMUM_SIZE
|
||||
jbe valloc_size_minimum
|
||||
dec ecx
|
||||
and ecx,(-1) shl 12
|
||||
add ecx,1 shl 12
|
||||
jmp valloc_size_ready
|
||||
valloc_size_minimum:
|
||||
mov ecx,VALLOC_MINIMUM_SIZE
|
||||
valloc_size_ready:
|
||||
push rbx rsi rdi
|
||||
cmp [local_heap_available],0
|
||||
je valloc_mmap
|
||||
cmp ecx,LOCAL_HEAP_SIZE
|
||||
ja valloc_mmap
|
||||
and [local_heap_available],0
|
||||
mov eax,local_heap
|
||||
mov ecx,LOCAL_HEAP_SIZE
|
||||
jmp valloc_ok
|
||||
valloc_mmap:
|
||||
xor r9d,r9d
|
||||
or r8,-1
|
||||
mov r10d,62h ; MAP_PRIVATE + MAP_ANONYMOUS + MAP_32BIT
|
||||
mov edx,3 ; PROT_READ + PROT_WRITE
|
||||
mov esi,ecx
|
||||
xor edi,edi
|
||||
mov eax,9 ; sys_mmap
|
||||
syscall
|
||||
cmp eax,-1
|
||||
je valloc_mmap_with_hint
|
||||
mov ecx,eax
|
||||
cmp rcx,rax
|
||||
jne valloc_mmap_unusable
|
||||
add ecx,esi
|
||||
jnc mmap_ok
|
||||
valloc_mmap_unusable:
|
||||
mov rdi,rax
|
||||
mov eax,11 ; sys_munmap
|
||||
syscall
|
||||
valloc_mmap_with_hint:
|
||||
mov r10d,22h ; MAP_PRIVATE + MAP_ANONYMOUS
|
||||
mov edx,3 ; PROT_READ + PROT_WRITE
|
||||
mov edi,[mmap_hint]
|
||||
mov eax,9 ; sys_mmap
|
||||
syscall
|
||||
cmp eax,-1
|
||||
je valloc_failed
|
||||
mov ecx,eax
|
||||
cmp rcx,rax
|
||||
jne valloc_failed
|
||||
add ecx,esi
|
||||
jc valloc_failed
|
||||
mmap_ok:
|
||||
sub ecx,eax
|
||||
valloc_ok:
|
||||
lea edx,[eax+ecx]
|
||||
mov [mmap_hint],edx
|
||||
pop rdi rsi rbx
|
||||
retn
|
||||
valloc_failed:
|
||||
xor ecx,ecx
|
||||
pop rdi rsi rbx
|
||||
retn
|
BIN
toolchain/fasmg.kl0e/source/macos/fasmg
Normal file
BIN
toolchain/fasmg.kl0e/source/macos/fasmg
Normal file
Binary file not shown.
504
toolchain/fasmg.kl0e/source/macos/fasmg.asm
Normal file
504
toolchain/fasmg.kl0e/source/macos/fasmg.asm
Normal file
@ -0,0 +1,504 @@
|
||||
|
||||
match ,{
|
||||
|
||||
err ; fasm 1 assembly not supported
|
||||
|
||||
} match -,{
|
||||
else
|
||||
|
||||
include 'selfhost.inc'
|
||||
|
||||
end match
|
||||
_ equ }
|
||||
|
||||
format MachO executable
|
||||
entry start
|
||||
|
||||
include '../version.inc'
|
||||
|
||||
interpreter '/usr/lib/dyld'
|
||||
uses '/usr/lib/libSystem.B.dylib'
|
||||
|
||||
import libc.malloc,'_malloc',\
|
||||
libc.realloc,'_realloc',\
|
||||
libc.free,'_free',\
|
||||
libc.fopen,'_fopen',\
|
||||
libc.fclose,'_fclose',\
|
||||
libc.fread,'_fread',\
|
||||
libc.fwrite,'_fwrite',\
|
||||
libc.fseek,'_fseek',\
|
||||
libc.ftell,'_ftell',\
|
||||
libc.time,'_time',\
|
||||
libc.write,'_write',\
|
||||
getenv,'_getenv',\
|
||||
gettimeofday,'_gettimeofday',\
|
||||
exit,'_exit'
|
||||
|
||||
struct timeval
|
||||
time_t dd ?
|
||||
suseconds_t dd ?
|
||||
ends
|
||||
|
||||
segment '__TEXT' readable executable
|
||||
|
||||
section '__text' align 16
|
||||
|
||||
start:
|
||||
mov ecx,[esp]
|
||||
mov [argc],ecx
|
||||
lea ebx,[esp+4]
|
||||
mov [argv],ebx
|
||||
|
||||
call system_init
|
||||
|
||||
call get_arguments
|
||||
mov bl,al
|
||||
cmp [no_logo],0
|
||||
jne logo_ok
|
||||
mov esi,_logo
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
logo_ok:
|
||||
test bl,bl
|
||||
jnz display_usage_information
|
||||
|
||||
xor al,al
|
||||
mov ecx,[verbosity_level]
|
||||
jecxz init
|
||||
or al,TRACE_ERROR_STACK
|
||||
dec ecx
|
||||
jz init
|
||||
or al,TRACE_DISPLAY
|
||||
init:
|
||||
call assembly_init
|
||||
|
||||
ccall gettimeofday,start_time,0
|
||||
|
||||
assemble:
|
||||
mov esi,[initial_commands]
|
||||
mov edx,[source_path]
|
||||
call assembly_pass
|
||||
jc assembly_done
|
||||
|
||||
mov eax,[current_pass]
|
||||
cmp eax,[maximum_number_of_passes]
|
||||
jb assemble
|
||||
|
||||
call show_display_data
|
||||
|
||||
mov esi,_error_prefix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,_code_cannot_be_generated
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,_message_suffix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
|
||||
jmp assembly_failed
|
||||
|
||||
assembly_done:
|
||||
|
||||
call show_display_data
|
||||
|
||||
cmp [first_error],0
|
||||
jne assembly_failed
|
||||
|
||||
cmp [no_logo],0
|
||||
jne summary_done
|
||||
mov eax,[current_pass]
|
||||
xor edx,edx
|
||||
call itoa
|
||||
call display_string
|
||||
mov esi,_passes
|
||||
cmp [current_pass],1
|
||||
jne display_passes_suffix
|
||||
mov esi,_pass
|
||||
display_passes_suffix:
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
ccall gettimeofday,end_time,0
|
||||
mov eax,[end_time.time_t]
|
||||
sub eax,[start_time.time_t]
|
||||
mov ecx,1000000
|
||||
mul ecx
|
||||
add eax,[end_time.suseconds_t]
|
||||
adc edx,0
|
||||
sub eax,[start_time.suseconds_t]
|
||||
sbb edx,0
|
||||
add eax,50000
|
||||
mov ecx,1000000
|
||||
div ecx
|
||||
mov ebx,eax
|
||||
mov eax,edx
|
||||
xor edx,edx
|
||||
mov ecx,100000
|
||||
div ecx
|
||||
mov [tenths_of_second],eax
|
||||
xchg eax,ebx
|
||||
or ebx,eax
|
||||
jz display_output_length
|
||||
xor edx,edx
|
||||
call itoa
|
||||
call display_string
|
||||
mov esi,_message_suffix
|
||||
mov ecx,1
|
||||
call display_string
|
||||
mov eax,[tenths_of_second]
|
||||
xor edx,edx
|
||||
call itoa
|
||||
call display_string
|
||||
mov esi,_seconds
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
display_output_length:
|
||||
call get_output_length
|
||||
push eax edx
|
||||
call itoa
|
||||
call display_string
|
||||
pop edx eax
|
||||
mov esi,_bytes
|
||||
cmp eax,1
|
||||
jne display_bytes_suffix
|
||||
test edx,edx
|
||||
jnz display_bytes_suffix
|
||||
mov esi,_byte
|
||||
display_bytes_suffix:
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
mov esi,_new_line
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
summary_done:
|
||||
|
||||
mov ebx,[source_path]
|
||||
mov edi,[output_path]
|
||||
call write_output_file
|
||||
jc write_failed
|
||||
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
|
||||
ccall exit,0
|
||||
|
||||
assembly_failed:
|
||||
|
||||
call show_errors
|
||||
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
|
||||
ccall exit,2
|
||||
|
||||
write_failed:
|
||||
mov ebx,_write_failed
|
||||
jmp fatal_error
|
||||
|
||||
out_of_memory:
|
||||
mov ebx,_out_of_memory
|
||||
jmp fatal_error
|
||||
|
||||
fatal_error:
|
||||
|
||||
mov esi,_error_prefix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,ebx
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,_message_suffix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
|
||||
ccall exit,3
|
||||
|
||||
display_usage_information:
|
||||
|
||||
mov esi,_usage
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
|
||||
call system_shutdown
|
||||
|
||||
ccall exit,1
|
||||
|
||||
get_arguments:
|
||||
xor eax,eax
|
||||
mov [initial_commands],eax
|
||||
mov [source_path],eax
|
||||
mov [output_path],eax
|
||||
mov [no_logo],al
|
||||
mov [verbosity_level],eax
|
||||
mov [maximum_number_of_passes],100
|
||||
mov [maximum_number_of_errors],1
|
||||
mov [maximum_depth_of_stack],10000
|
||||
mov ecx,[argc]
|
||||
mov ebx,[argv]
|
||||
add ebx,4
|
||||
dec ecx
|
||||
jz error_in_arguments
|
||||
get_argument:
|
||||
mov esi,[ebx]
|
||||
mov al,[esi]
|
||||
cmp al,'-'
|
||||
je get_option
|
||||
cmp [source_path],0
|
||||
jne get_output_file
|
||||
mov [source_path],esi
|
||||
jmp next_argument
|
||||
get_output_file:
|
||||
cmp [output_path],0
|
||||
jne error_in_arguments
|
||||
mov [output_path],esi
|
||||
jmp next_argument
|
||||
get_option:
|
||||
inc esi
|
||||
lodsb
|
||||
cmp al,'e'
|
||||
je set_errors_limit
|
||||
cmp al,'E'
|
||||
je set_errors_limit
|
||||
cmp al,'i'
|
||||
je insert_initial_command
|
||||
cmp al,'I'
|
||||
je insert_initial_command
|
||||
cmp al,'p'
|
||||
je set_passes_limit
|
||||
cmp al,'P'
|
||||
je set_passes_limit
|
||||
cmp al,'r'
|
||||
je set_recursion_limit
|
||||
cmp al,'R'
|
||||
je set_recursion_limit
|
||||
cmp al,'v'
|
||||
je set_verbose_mode
|
||||
cmp al,'V'
|
||||
je set_verbose_mode
|
||||
cmp al,'n'
|
||||
je set_no_logo
|
||||
cmp al,'N'
|
||||
jne error_in_arguments
|
||||
set_no_logo:
|
||||
or [no_logo],-1
|
||||
cmp byte [esi],0
|
||||
je next_argument
|
||||
error_in_arguments:
|
||||
or al,-1
|
||||
ret
|
||||
set_verbose_mode:
|
||||
cmp byte [esi],0
|
||||
jne get_verbose_setting
|
||||
dec ecx
|
||||
jz error_in_arguments
|
||||
add ebx,4
|
||||
mov esi,[ebx]
|
||||
get_verbose_setting:
|
||||
call get_option_value
|
||||
cmp edx,2
|
||||
ja error_in_arguments
|
||||
mov [verbosity_level],edx
|
||||
jmp next_argument
|
||||
set_errors_limit:
|
||||
cmp byte [esi],0
|
||||
jne get_errors_setting
|
||||
dec ecx
|
||||
jz error_in_arguments
|
||||
add ebx,4
|
||||
mov esi,[ebx]
|
||||
get_errors_setting:
|
||||
call get_option_value
|
||||
test edx,edx
|
||||
jz error_in_arguments
|
||||
mov [maximum_number_of_errors],edx
|
||||
jmp next_argument
|
||||
set_recursion_limit:
|
||||
cmp byte [esi],0
|
||||
jne get_recursion_setting
|
||||
dec ecx
|
||||
jz error_in_arguments
|
||||
add ebx,4
|
||||
mov esi,[ebx]
|
||||
get_recursion_setting:
|
||||
call get_option_value
|
||||
test edx,edx
|
||||
jz error_in_arguments
|
||||
mov [maximum_depth_of_stack],edx
|
||||
jmp next_argument
|
||||
set_passes_limit:
|
||||
cmp byte [esi],0
|
||||
jne get_passes_setting
|
||||
dec ecx
|
||||
jz error_in_arguments
|
||||
add ebx,4
|
||||
mov esi,[ebx]
|
||||
get_passes_setting:
|
||||
call get_option_value
|
||||
test edx,edx
|
||||
jz error_in_arguments
|
||||
mov [maximum_number_of_passes],edx
|
||||
next_argument:
|
||||
add ebx,4
|
||||
dec ecx
|
||||
jnz get_argument
|
||||
cmp [source_path],0
|
||||
je error_in_arguments
|
||||
xor al,al
|
||||
ret
|
||||
get_option_value:
|
||||
xor eax,eax
|
||||
mov edx,eax
|
||||
find_option_value:
|
||||
cmp byte [esi],20h
|
||||
jne get_option_digit
|
||||
inc esi
|
||||
jmp find_option_value
|
||||
get_option_digit:
|
||||
lodsb
|
||||
test al,al
|
||||
jz option_value_ok
|
||||
sub al,30h
|
||||
jc invalid_option_value
|
||||
cmp al,9
|
||||
ja invalid_option_value
|
||||
imul edx,10
|
||||
jo invalid_option_value
|
||||
add edx,eax
|
||||
jc invalid_option_value
|
||||
jmp get_option_digit
|
||||
option_value_ok:
|
||||
dec esi
|
||||
clc
|
||||
ret
|
||||
invalid_option_value:
|
||||
stc
|
||||
ret
|
||||
insert_initial_command:
|
||||
cmp byte [esi],0
|
||||
jne measure_initial_command
|
||||
dec ecx
|
||||
jz error_in_arguments
|
||||
add ebx,4
|
||||
mov esi,[ebx]
|
||||
measure_initial_command:
|
||||
push ebx ecx edi
|
||||
mov edi,esi
|
||||
or ecx,-1
|
||||
xor al,al
|
||||
repne scasb
|
||||
not ecx
|
||||
dec ecx
|
||||
mov edi,[initial_commands]
|
||||
lea eax,[ecx+2]
|
||||
test edi,edi
|
||||
jz allocate_initial_commands_buffer
|
||||
mov edx,[initial_commands_length]
|
||||
add edi,edx
|
||||
add eax,edx
|
||||
cmp eax,[initial_commands_maximum_length]
|
||||
ja grow_initial_commands_buffer
|
||||
copy_initial_command:
|
||||
rep movsb
|
||||
mov ax,0Ah
|
||||
stosw
|
||||
dec edi
|
||||
sub edi,[initial_commands]
|
||||
mov [initial_commands_length],edi
|
||||
pop edi ecx ebx
|
||||
jmp next_argument
|
||||
allocate_initial_commands_buffer:
|
||||
push ecx
|
||||
mov ecx,eax
|
||||
call malloc
|
||||
mov [initial_commands],eax
|
||||
mov [initial_commands_maximum_length],ecx
|
||||
mov edi,eax
|
||||
pop ecx
|
||||
jmp copy_initial_command
|
||||
grow_initial_commands_buffer:
|
||||
push ecx
|
||||
mov ecx,eax
|
||||
mov eax,[initial_commands]
|
||||
call realloc
|
||||
mov [initial_commands],eax
|
||||
mov [initial_commands_maximum_length],ecx
|
||||
mov edi,eax
|
||||
add edi,[initial_commands_length]
|
||||
pop ecx
|
||||
jmp copy_initial_command
|
||||
|
||||
include 'system.inc'
|
||||
|
||||
include '../assembler.inc'
|
||||
include '../symbols.inc'
|
||||
include '../expressions.inc'
|
||||
include '../conditions.inc'
|
||||
include '../floats.inc'
|
||||
include '../directives.inc'
|
||||
include '../calm.inc'
|
||||
include '../errors.inc'
|
||||
include '../map.inc'
|
||||
include '../reader.inc'
|
||||
include '../output.inc'
|
||||
include '../console.inc'
|
||||
|
||||
section '__cstring' align 4
|
||||
|
||||
_logo db 'flat assembler version g.',VERSION,10,0
|
||||
|
||||
_usage db 'Usage: fasmg source [output]',10
|
||||
db 'Optional settings:',10
|
||||
db ' -p limit Set the maximum allowed number of passes (default 100)',10
|
||||
db ' -e limit Set the maximum number of displayed errors (default 1)',10
|
||||
db ' -r limit Set the maximum depth of the stack (default 10000)',10
|
||||
db ' -v flag Enable or disable showing all lines from the stack (default 0)',10
|
||||
db ' -i command Insert instruction at the beginning of source',13,10
|
||||
db ' -n Do not show logo nor summary',13,10
|
||||
db 0
|
||||
|
||||
_pass db ' pass, ',0
|
||||
_passes db ' passes, ',0
|
||||
_dot db '.'
|
||||
_seconds db ' seconds, ',0
|
||||
_byte db ' byte.',0
|
||||
_bytes db ' bytes.',0
|
||||
|
||||
_write_failed db 'failed to write the output file',0
|
||||
_out_of_memory db 'not enough memory to complete the assembly',0
|
||||
_code_cannot_be_generated db 'could not generate code within the allowed number of passes',0
|
||||
|
||||
_open_mode db 'r',0
|
||||
_create_mode db 'w',0
|
||||
|
||||
include '../tables.inc'
|
||||
include '../messages.inc'
|
||||
|
||||
segment '__DATA' readable writable
|
||||
|
||||
section '__bss' align 4
|
||||
|
||||
include '../variables.inc'
|
||||
|
||||
source_path dd ?
|
||||
output_path dd ?
|
||||
maximum_number_of_passes dd ?
|
||||
|
||||
initial_commands dd ?
|
||||
initial_commands_length dd ?
|
||||
initial_commands_maximum_length dd ?
|
||||
|
||||
argc dd ?
|
||||
argv dd ?
|
||||
timestamp dq ?
|
||||
|
||||
start_time timeval
|
||||
end_time timeval
|
||||
tenths_of_second dd ?
|
||||
|
||||
verbosity_level dd ?
|
||||
no_logo db ?
|
||||
|
||||
path_buffer rb 1000h
|
498
toolchain/fasmg.kl0e/source/macos/fasmg.o.asm
Normal file
498
toolchain/fasmg.kl0e/source/macos/fasmg.o.asm
Normal file
@ -0,0 +1,498 @@
|
||||
|
||||
match ,{
|
||||
|
||||
err ; fasm 1 assembly not supported
|
||||
|
||||
} match -,{
|
||||
else
|
||||
|
||||
include 'selfhost.inc'
|
||||
|
||||
end match
|
||||
_ equ }
|
||||
|
||||
format MachO
|
||||
public main as '_main'
|
||||
|
||||
include '../version.inc'
|
||||
|
||||
extrn '_malloc' as libc.malloc
|
||||
extrn '_realloc' as libc.realloc
|
||||
extrn '_free' as libc.free
|
||||
extrn '_fopen' as libc.fopen
|
||||
extrn '_fclose' as libc.fclose
|
||||
extrn '_fread' as libc.fread
|
||||
extrn '_fwrite' as libc.fwrite
|
||||
extrn '_fseek' as libc.fseek
|
||||
extrn '_ftell' as libc.ftell
|
||||
extrn '_time' as libc.time
|
||||
extrn '_write' as libc.write
|
||||
|
||||
extrn '_getenv' as getenv
|
||||
extrn '_gettimeofday' as gettimeofday
|
||||
extrn '_exit' as exit
|
||||
|
||||
struct timeval
|
||||
time_t dd ?
|
||||
suseconds_t dd ?
|
||||
ends
|
||||
|
||||
section '__TEXT':'__text' align 16
|
||||
|
||||
main:
|
||||
mov ecx,[esp+4]
|
||||
mov [argc],ecx
|
||||
mov ebx,[esp+8]
|
||||
mov [argv],ebx
|
||||
|
||||
call system_init
|
||||
|
||||
call get_arguments
|
||||
mov bl,al
|
||||
cmp [no_logo],0
|
||||
jne logo_ok
|
||||
mov esi,_logo
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
logo_ok:
|
||||
test bl,bl
|
||||
jnz display_usage_information
|
||||
|
||||
xor al,al
|
||||
mov ecx,[verbosity_level]
|
||||
jecxz init
|
||||
or al,TRACE_ERROR_STACK
|
||||
dec ecx
|
||||
jz init
|
||||
or al,TRACE_DISPLAY
|
||||
init:
|
||||
call assembly_init
|
||||
|
||||
ccall gettimeofday,start_time,0
|
||||
|
||||
assemble:
|
||||
mov esi,[initial_commands]
|
||||
mov edx,[source_path]
|
||||
call assembly_pass
|
||||
jc assembly_done
|
||||
|
||||
mov eax,[current_pass]
|
||||
cmp eax,[maximum_number_of_passes]
|
||||
jb assemble
|
||||
|
||||
call show_display_data
|
||||
|
||||
mov esi,_error_prefix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,_code_cannot_be_generated
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,_message_suffix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
|
||||
jmp assembly_failed
|
||||
|
||||
assembly_done:
|
||||
|
||||
call show_display_data
|
||||
|
||||
cmp [first_error],0
|
||||
jne assembly_failed
|
||||
|
||||
cmp [no_logo],0
|
||||
jne summary_done
|
||||
mov eax,[current_pass]
|
||||
xor edx,edx
|
||||
call itoa
|
||||
call display_string
|
||||
mov esi,_passes
|
||||
cmp [current_pass],1
|
||||
jne display_passes_suffix
|
||||
mov esi,_pass
|
||||
display_passes_suffix:
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
ccall gettimeofday,end_time,0
|
||||
mov eax,[end_time.time_t]
|
||||
sub eax,[start_time.time_t]
|
||||
mov ecx,1000000
|
||||
mul ecx
|
||||
add eax,[end_time.suseconds_t]
|
||||
adc edx,0
|
||||
sub eax,[start_time.suseconds_t]
|
||||
sbb edx,0
|
||||
add eax,50000
|
||||
mov ecx,1000000
|
||||
div ecx
|
||||
mov ebx,eax
|
||||
mov eax,edx
|
||||
xor edx,edx
|
||||
mov ecx,100000
|
||||
div ecx
|
||||
mov [tenths_of_second],eax
|
||||
xchg eax,ebx
|
||||
or ebx,eax
|
||||
jz display_output_length
|
||||
xor edx,edx
|
||||
call itoa
|
||||
call display_string
|
||||
mov esi,_message_suffix
|
||||
mov ecx,1
|
||||
call display_string
|
||||
mov eax,[tenths_of_second]
|
||||
xor edx,edx
|
||||
call itoa
|
||||
call display_string
|
||||
mov esi,_seconds
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
display_output_length:
|
||||
call get_output_length
|
||||
push eax edx
|
||||
call itoa
|
||||
call display_string
|
||||
pop edx eax
|
||||
mov esi,_bytes
|
||||
cmp eax,1
|
||||
jne display_bytes_suffix
|
||||
test edx,edx
|
||||
jnz display_bytes_suffix
|
||||
mov esi,_byte
|
||||
display_bytes_suffix:
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
mov esi,_new_line
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
summary_done:
|
||||
|
||||
mov ebx,[source_path]
|
||||
mov edi,[output_path]
|
||||
call write_output_file
|
||||
jc write_failed
|
||||
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
|
||||
ccall exit,0
|
||||
|
||||
assembly_failed:
|
||||
|
||||
call show_errors
|
||||
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
|
||||
ccall exit,2
|
||||
|
||||
write_failed:
|
||||
mov ebx,_write_failed
|
||||
jmp fatal_error
|
||||
|
||||
out_of_memory:
|
||||
mov ebx,_out_of_memory
|
||||
jmp fatal_error
|
||||
|
||||
fatal_error:
|
||||
|
||||
mov esi,_error_prefix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,ebx
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,_message_suffix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
|
||||
ccall exit,3
|
||||
|
||||
display_usage_information:
|
||||
|
||||
mov esi,_usage
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
|
||||
call system_shutdown
|
||||
|
||||
ccall exit,1
|
||||
|
||||
get_arguments:
|
||||
xor eax,eax
|
||||
mov [initial_commands],eax
|
||||
mov [source_path],eax
|
||||
mov [output_path],eax
|
||||
mov [no_logo],al
|
||||
mov [verbosity_level],eax
|
||||
mov [maximum_number_of_passes],100
|
||||
mov [maximum_number_of_errors],1
|
||||
mov [maximum_depth_of_stack],10000
|
||||
mov ecx,[argc]
|
||||
mov ebx,[argv]
|
||||
add ebx,4
|
||||
dec ecx
|
||||
jz error_in_arguments
|
||||
get_argument:
|
||||
mov esi,[ebx]
|
||||
mov al,[esi]
|
||||
cmp al,'-'
|
||||
je get_option
|
||||
cmp [source_path],0
|
||||
jne get_output_file
|
||||
mov [source_path],esi
|
||||
jmp next_argument
|
||||
get_output_file:
|
||||
cmp [output_path],0
|
||||
jne error_in_arguments
|
||||
mov [output_path],esi
|
||||
jmp next_argument
|
||||
get_option:
|
||||
inc esi
|
||||
lodsb
|
||||
cmp al,'e'
|
||||
je set_errors_limit
|
||||
cmp al,'E'
|
||||
je set_errors_limit
|
||||
cmp al,'i'
|
||||
je insert_initial_command
|
||||
cmp al,'I'
|
||||
je insert_initial_command
|
||||
cmp al,'p'
|
||||
je set_passes_limit
|
||||
cmp al,'P'
|
||||
je set_passes_limit
|
||||
cmp al,'r'
|
||||
je set_recursion_limit
|
||||
cmp al,'R'
|
||||
je set_recursion_limit
|
||||
cmp al,'v'
|
||||
je set_verbose_mode
|
||||
cmp al,'V'
|
||||
je set_verbose_mode
|
||||
cmp al,'n'
|
||||
je set_no_logo
|
||||
cmp al,'N'
|
||||
jne error_in_arguments
|
||||
set_no_logo:
|
||||
or [no_logo],-1
|
||||
cmp byte [esi],0
|
||||
je next_argument
|
||||
error_in_arguments:
|
||||
or al,-1
|
||||
ret
|
||||
set_verbose_mode:
|
||||
cmp byte [esi],0
|
||||
jne get_verbose_setting
|
||||
dec ecx
|
||||
jz error_in_arguments
|
||||
add ebx,4
|
||||
mov esi,[ebx]
|
||||
get_verbose_setting:
|
||||
call get_option_value
|
||||
cmp edx,2
|
||||
ja error_in_arguments
|
||||
mov [verbosity_level],edx
|
||||
jmp next_argument
|
||||
set_errors_limit:
|
||||
cmp byte [esi],0
|
||||
jne get_errors_setting
|
||||
dec ecx
|
||||
jz error_in_arguments
|
||||
add ebx,4
|
||||
mov esi,[ebx]
|
||||
get_errors_setting:
|
||||
call get_option_value
|
||||
test edx,edx
|
||||
jz error_in_arguments
|
||||
mov [maximum_number_of_errors],edx
|
||||
jmp next_argument
|
||||
set_recursion_limit:
|
||||
cmp byte [esi],0
|
||||
jne get_recursion_setting
|
||||
dec ecx
|
||||
jz error_in_arguments
|
||||
add ebx,4
|
||||
mov esi,[ebx]
|
||||
get_recursion_setting:
|
||||
call get_option_value
|
||||
test edx,edx
|
||||
jz error_in_arguments
|
||||
mov [maximum_depth_of_stack],edx
|
||||
jmp next_argument
|
||||
set_passes_limit:
|
||||
cmp byte [esi],0
|
||||
jne get_passes_setting
|
||||
dec ecx
|
||||
jz error_in_arguments
|
||||
add ebx,4
|
||||
mov esi,[ebx]
|
||||
get_passes_setting:
|
||||
call get_option_value
|
||||
test edx,edx
|
||||
jz error_in_arguments
|
||||
mov [maximum_number_of_passes],edx
|
||||
next_argument:
|
||||
add ebx,4
|
||||
dec ecx
|
||||
jnz get_argument
|
||||
cmp [source_path],0
|
||||
je error_in_arguments
|
||||
xor al,al
|
||||
ret
|
||||
get_option_value:
|
||||
xor eax,eax
|
||||
mov edx,eax
|
||||
find_option_value:
|
||||
cmp byte [esi],20h
|
||||
jne get_option_digit
|
||||
inc esi
|
||||
jmp find_option_value
|
||||
get_option_digit:
|
||||
lodsb
|
||||
test al,al
|
||||
jz option_value_ok
|
||||
sub al,30h
|
||||
jc invalid_option_value
|
||||
cmp al,9
|
||||
ja invalid_option_value
|
||||
imul edx,10
|
||||
jo invalid_option_value
|
||||
add edx,eax
|
||||
jc invalid_option_value
|
||||
jmp get_option_digit
|
||||
option_value_ok:
|
||||
dec esi
|
||||
clc
|
||||
ret
|
||||
invalid_option_value:
|
||||
stc
|
||||
ret
|
||||
insert_initial_command:
|
||||
cmp byte [esi],0
|
||||
jne measure_initial_command
|
||||
dec ecx
|
||||
jz error_in_arguments
|
||||
add ebx,4
|
||||
mov esi,[ebx]
|
||||
measure_initial_command:
|
||||
push ebx ecx edi
|
||||
mov edi,esi
|
||||
or ecx,-1
|
||||
xor al,al
|
||||
repne scasb
|
||||
not ecx
|
||||
dec ecx
|
||||
mov edi,[initial_commands]
|
||||
lea eax,[ecx+2]
|
||||
test edi,edi
|
||||
jz allocate_initial_commands_buffer
|
||||
mov edx,[initial_commands_length]
|
||||
add edi,edx
|
||||
add eax,edx
|
||||
cmp eax,[initial_commands_maximum_length]
|
||||
ja grow_initial_commands_buffer
|
||||
copy_initial_command:
|
||||
rep movsb
|
||||
mov ax,0Ah
|
||||
stosw
|
||||
dec edi
|
||||
sub edi,[initial_commands]
|
||||
mov [initial_commands_length],edi
|
||||
pop edi ecx ebx
|
||||
jmp next_argument
|
||||
allocate_initial_commands_buffer:
|
||||
push ecx
|
||||
mov ecx,eax
|
||||
call malloc
|
||||
mov [initial_commands],eax
|
||||
mov [initial_commands_maximum_length],ecx
|
||||
mov edi,eax
|
||||
pop ecx
|
||||
jmp copy_initial_command
|
||||
grow_initial_commands_buffer:
|
||||
push ecx
|
||||
mov ecx,eax
|
||||
mov eax,[initial_commands]
|
||||
call realloc
|
||||
mov [initial_commands],eax
|
||||
mov [initial_commands_maximum_length],ecx
|
||||
mov edi,eax
|
||||
add edi,[initial_commands_length]
|
||||
pop ecx
|
||||
jmp copy_initial_command
|
||||
|
||||
include 'system.inc'
|
||||
|
||||
include '../assembler.inc'
|
||||
include '../symbols.inc'
|
||||
include '../expressions.inc'
|
||||
include '../conditions.inc'
|
||||
include '../floats.inc'
|
||||
include '../directives.inc'
|
||||
include '../calm.inc'
|
||||
include '../errors.inc'
|
||||
include '../map.inc'
|
||||
include '../reader.inc'
|
||||
include '../output.inc'
|
||||
include '../console.inc'
|
||||
|
||||
section '__TEXT':'__cstring' align 4
|
||||
|
||||
_logo db 'flat assembler version g.',VERSION,10,0
|
||||
|
||||
_usage db 'Usage: fasmg source [output]',10
|
||||
db 'Optional settings:',10
|
||||
db ' -p limit Set the maximum allowed number of passes (default 100)',10
|
||||
db ' -e limit Set the maximum number of displayed errors (default 1)',10
|
||||
db ' -r limit Set the maximum depth of the stack (default 10000)',10
|
||||
db ' -v flag Enable or disable showing all lines from the stack (default 0)',10
|
||||
db ' -i command Insert instruction at the beginning of source',13,10
|
||||
db ' -n Do not show logo nor summary',13,10
|
||||
db 0
|
||||
|
||||
_pass db ' pass, ',0
|
||||
_passes db ' passes, ',0
|
||||
_dot db '.'
|
||||
_seconds db ' seconds, ',0
|
||||
_byte db ' byte.',0
|
||||
_bytes db ' bytes.',0
|
||||
|
||||
_write_failed db 'failed to write the output file',0
|
||||
_out_of_memory db 'not enough memory to complete the assembly',0
|
||||
_code_cannot_be_generated db 'could not generate code within the allowed number of passes',0
|
||||
|
||||
_open_mode db 'r',0
|
||||
_create_mode db 'w',0
|
||||
|
||||
include '../tables.inc'
|
||||
include '../messages.inc'
|
||||
|
||||
section '__DATA':'__data' align 4
|
||||
|
||||
include '../variables.inc'
|
||||
|
||||
source_path dd ?
|
||||
output_path dd ?
|
||||
maximum_number_of_passes dd ?
|
||||
|
||||
initial_commands dd ?
|
||||
initial_commands_length dd ?
|
||||
initial_commands_maximum_length dd ?
|
||||
|
||||
argc dd ?
|
||||
argv dd ?
|
||||
timestamp dq ?
|
||||
|
||||
start_time timeval
|
||||
end_time timeval
|
||||
tenths_of_second dd ?
|
||||
|
||||
verbosity_level dd ?
|
||||
no_logo db ?
|
||||
|
||||
path_buffer rb 1000h
|
50
toolchain/fasmg.kl0e/source/macos/selfhost.inc
Normal file
50
toolchain/fasmg.kl0e/source/macos/selfhost.inc
Normal file
@ -0,0 +1,50 @@
|
||||
|
||||
include '../../examples/x86/include/80386.inc'
|
||||
|
||||
macro format?.MachO? variant
|
||||
match , variant
|
||||
MachO.Settings.FileType equ MH_OBJECT
|
||||
include '../../examples/x86/include/format/macho.inc'
|
||||
use32
|
||||
else match =executable?, variant
|
||||
MachO.Settings.BaseAddress = 0x1000
|
||||
include '../../examples/x86/include/format/macho.inc'
|
||||
use32
|
||||
else
|
||||
err 'invalid argument'
|
||||
end match
|
||||
end macro
|
||||
|
||||
macro struct? name
|
||||
macro ends?!
|
||||
end namespace
|
||||
esc end struc
|
||||
virtual at 0
|
||||
name name
|
||||
sizeof.name = $
|
||||
end virtual
|
||||
purge ends?
|
||||
end macro
|
||||
esc struc name
|
||||
label . : sizeof.name
|
||||
namespace .
|
||||
end macro
|
||||
|
||||
macro ccall? proc*,args&
|
||||
local size
|
||||
mov ebp,esp
|
||||
sub esp,size
|
||||
and esp,0FFFFFFF0h
|
||||
match any, args
|
||||
iterate arg, args
|
||||
mov dword [esp+(%-1)*4],arg
|
||||
if % = 1
|
||||
size := %%*4
|
||||
end if
|
||||
end iterate
|
||||
else
|
||||
size := 0
|
||||
end match
|
||||
call proc
|
||||
mov esp,ebp
|
||||
end macro
|
225
toolchain/fasmg.kl0e/source/macos/system.inc
Normal file
225
toolchain/fasmg.kl0e/source/macos/system.inc
Normal file
@ -0,0 +1,225 @@
|
||||
|
||||
LINE_FEED = 0Ah
|
||||
|
||||
system_init:
|
||||
ccall libc.time,timestamp
|
||||
retn
|
||||
|
||||
system_shutdown:
|
||||
retn
|
||||
|
||||
malloc:
|
||||
malloc_fixed:
|
||||
malloc_growable:
|
||||
; in: ecx = requested size
|
||||
; out: eax - allocated block, ecx = allocated size, on error jumps to out_of_memory (does not return)
|
||||
; preserves: ebx, esi, edi
|
||||
; note:
|
||||
; use of malloc_fixed hints that block will be kept as is until the end of assembly
|
||||
; use of malloc_growable hints that block is likely to be resized
|
||||
push ebx ecx esi edi
|
||||
ccall libc.malloc,ecx
|
||||
pop edi esi ecx ebx
|
||||
test eax,eax
|
||||
jz out_of_memory
|
||||
retn
|
||||
realloc:
|
||||
; in: eax - memory block, ecx = requested size
|
||||
; out: eax - resized block, ecx = allocated size, on error jumps to out_of_memory (does not return)
|
||||
; preserves: ebx, esi, edi
|
||||
push ebx ecx esi edi
|
||||
ccall libc.realloc,eax,ecx
|
||||
pop edi esi ecx ebx
|
||||
test eax,eax
|
||||
jz out_of_memory
|
||||
retn
|
||||
mfree:
|
||||
; in: eax - memory block
|
||||
; out: cf set on error
|
||||
; preserves: ebx, esi, edi
|
||||
; note: eax may have value 0 or -1, it should be treated as invalid input then
|
||||
test eax,eax
|
||||
jz interface_error
|
||||
cmp eax,-1
|
||||
je interface_error
|
||||
push ebx esi edi
|
||||
ccall libc.free,eax
|
||||
pop edi esi ebx
|
||||
clc
|
||||
retn
|
||||
interface_error:
|
||||
stc
|
||||
retn
|
||||
|
||||
open:
|
||||
; in: edx - path to file
|
||||
; out: ebx = file handle, cf set on error
|
||||
; preserves: esi, edi
|
||||
push esi edi
|
||||
call adapt_path
|
||||
ccall libc.fopen,ebx,_open_mode
|
||||
pop edi esi
|
||||
test eax,eax
|
||||
jz interface_error
|
||||
mov ebx,eax
|
||||
clc
|
||||
retn
|
||||
adapt_path:
|
||||
xor ecx,ecx
|
||||
mov ebx,path_buffer
|
||||
copy_path:
|
||||
mov al,[edx+ecx]
|
||||
cmp al,'\'
|
||||
jne path_char_ok
|
||||
mov al,'/'
|
||||
path_char_ok:
|
||||
cmp ecx,1000h
|
||||
jae out_of_memory
|
||||
mov [ebx+ecx],al
|
||||
inc ecx
|
||||
test al,al
|
||||
jnz copy_path
|
||||
retn
|
||||
create:
|
||||
; in: edx - path to file
|
||||
; out: ebx = file handle, cf set on error
|
||||
; preserves: esi, edi
|
||||
push esi edi
|
||||
call adapt_path
|
||||
ccall libc.fopen,ebx,_create_mode
|
||||
pop edi esi
|
||||
test eax,eax
|
||||
jz interface_error
|
||||
mov ebx,eax
|
||||
clc
|
||||
retn
|
||||
write:
|
||||
; in: ebx = file handle, edx - data, ecx = number of bytes
|
||||
; out: cf set on error
|
||||
; preserves: ebx, esi, edi
|
||||
push ebx ecx esi edi
|
||||
ccall libc.fwrite,edx,1,ecx,ebx
|
||||
pop edi esi ecx ebx
|
||||
cmp eax,ecx
|
||||
jne interface_error
|
||||
clc
|
||||
ret
|
||||
read:
|
||||
; in: ebx = file handle, edx - buffer, ecx = number of bytes
|
||||
; out: cf set on error
|
||||
; preserves: ebx, esi, edi
|
||||
push ebx ecx esi edi
|
||||
ccall libc.fread,edx,1,ecx,ebx
|
||||
pop edi esi ecx ebx
|
||||
cmp eax,ecx
|
||||
jne interface_error
|
||||
clc
|
||||
ret
|
||||
close:
|
||||
; in: ebx = file handle
|
||||
; preserves: ebx, esi, edi
|
||||
ccall libc.fclose,ebx
|
||||
ret
|
||||
lseek:
|
||||
; in: ebx = file handle, cl = method, edx:eax = offset
|
||||
; out: edx:eax = new offset from the beginning of file, cf set on error
|
||||
; preserves: ebx, esi, edi
|
||||
test edx,edx
|
||||
jnz interface_error
|
||||
push esi edi ebx
|
||||
movzx ecx,cl
|
||||
ccall libc.fseek,ebx,eax,ecx
|
||||
test eax,eax
|
||||
jnz lseek_error
|
||||
mov ebx,[esp]
|
||||
ccall libc.ftell,ebx
|
||||
cmp eax,-1
|
||||
je lseek_error
|
||||
xor edx,edx
|
||||
pop ebx edi esi
|
||||
clc
|
||||
ret
|
||||
lseek_error:
|
||||
pop ebx edi esi
|
||||
stc
|
||||
ret
|
||||
|
||||
get_timestamp:
|
||||
; out: edx:eax = timestamp
|
||||
; preserves: ebx, ecx, esi, edi
|
||||
; note: during the passes of a single assembly this function should always return the same value
|
||||
mov eax,dword [timestamp]
|
||||
mov edx,dword [timestamp+4]
|
||||
retn
|
||||
|
||||
display_string:
|
||||
; in:
|
||||
; esi - string
|
||||
; ecx = string length, zero for ASCIIZ string
|
||||
; preserves: ebx, esi
|
||||
push ebx esi
|
||||
test ecx,ecx
|
||||
jnz write_string_to_stdout
|
||||
xor al,al
|
||||
mov edi,esi
|
||||
or ecx,-1
|
||||
repne scasb
|
||||
neg ecx
|
||||
sub ecx,2
|
||||
write_string_to_stdout:
|
||||
ccall libc.write,1,esi,ecx
|
||||
pop esi ebx
|
||||
retn
|
||||
|
||||
display_error_string:
|
||||
; in:
|
||||
; esi - string
|
||||
; ecx = string length, zero for ASCIIZ string
|
||||
; preserves: ebx, esi
|
||||
push ebx esi
|
||||
test ecx,ecx
|
||||
jnz write_string_to_stderr
|
||||
xor al,al
|
||||
mov edi,esi
|
||||
or ecx,-1
|
||||
repne scasb
|
||||
neg ecx
|
||||
sub ecx,2
|
||||
write_string_to_stderr:
|
||||
ccall libc.write,2,esi,ecx
|
||||
pop esi ebx
|
||||
retn
|
||||
|
||||
get_environment_variable:
|
||||
; in:
|
||||
; esi - name
|
||||
; edi - buffer for value
|
||||
; ecx = size of buffer
|
||||
; out:
|
||||
; eax = length of value
|
||||
; preserves: ebx, esi, edi
|
||||
push ebx ecx esi edi
|
||||
ccall getenv,esi
|
||||
pop edi esi ecx ebx
|
||||
test eax,eax
|
||||
jz no_environment_variable
|
||||
push esi
|
||||
mov esi,eax
|
||||
xor eax,eax
|
||||
copy_environment_variable:
|
||||
mov dl,[esi+eax]
|
||||
cmp eax,ecx
|
||||
jae next_environment_variable_character
|
||||
mov [edi+eax],dl
|
||||
next_environment_variable_character:
|
||||
inc eax
|
||||
test dl,dl
|
||||
jnz copy_environment_variable
|
||||
pop esi
|
||||
environment_variable_ok:
|
||||
ret
|
||||
no_environment_variable:
|
||||
mov eax,1
|
||||
jecxz environment_variable_ok
|
||||
and byte [edi],0
|
||||
ret
|
BIN
toolchain/fasmg.kl0e/source/macos/x64/fasmg
Normal file
BIN
toolchain/fasmg.kl0e/source/macos/x64/fasmg
Normal file
Binary file not shown.
546
toolchain/fasmg.kl0e/source/macos/x64/fasmg.asm
Normal file
546
toolchain/fasmg.kl0e/source/macos/x64/fasmg.asm
Normal file
@ -0,0 +1,546 @@
|
||||
|
||||
; Adapted and tested by Jacob Young (jacobly.alt@gmail.com)
|
||||
|
||||
match ,{
|
||||
|
||||
err ; fasm 1 assembly not supported
|
||||
|
||||
} match -,{
|
||||
else
|
||||
|
||||
include 'selfhost.inc'
|
||||
|
||||
end match
|
||||
_ equ }
|
||||
|
||||
format MachO64 executable
|
||||
entry start
|
||||
|
||||
include '../../version.inc'
|
||||
|
||||
interpreter '/usr/lib/dyld'
|
||||
uses '/usr/lib/libSystem.B.dylib'
|
||||
|
||||
import libc.fopen,'_fopen',\
|
||||
libc.fclose,'_fclose',\
|
||||
libc.fread,'_fread',\
|
||||
libc.fwrite,'_fwrite',\
|
||||
libc.fseek,'_fseek',\
|
||||
libc.ftell,'_ftell',\
|
||||
libc.time,'_time',\
|
||||
libc.write,'_write',\
|
||||
mmap,'_mmap',\
|
||||
munmap,'_munmap',\
|
||||
getenv,'_getenv',\
|
||||
gettimeofday,'_gettimeofday',\
|
||||
exit,'_exit'
|
||||
|
||||
struct timeval
|
||||
time_t dq ?
|
||||
suseconds_t dd ?,?
|
||||
ends
|
||||
|
||||
segment '__TEXT' readable executable
|
||||
|
||||
section '__text' align 16
|
||||
|
||||
start:
|
||||
mov rcx,[rsp]
|
||||
mov [argc],rcx
|
||||
lea rbx,[rsp+8]
|
||||
mov [argv],rbx
|
||||
|
||||
call system_init
|
||||
|
||||
call get_arguments
|
||||
mov bl,al
|
||||
cmp [no_logo],0
|
||||
jne logo_ok
|
||||
mov esi,_logo
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
logo_ok:
|
||||
test bl,bl
|
||||
jnz display_usage_information
|
||||
|
||||
xor al,al
|
||||
mov ecx,[verbosity_level]
|
||||
jecxz init
|
||||
or al,TRACE_ERROR_STACK
|
||||
dec ecx
|
||||
jz init
|
||||
or al,TRACE_DISPLAY
|
||||
init:
|
||||
call assembly_init
|
||||
|
||||
ccall gettimeofday,start_time,0
|
||||
|
||||
assemble:
|
||||
mov esi,[initial_commands]
|
||||
mov edx,[source_path]
|
||||
call assembly_pass
|
||||
jc assembly_done
|
||||
|
||||
mov eax,[current_pass]
|
||||
cmp eax,[maximum_number_of_passes]
|
||||
jb assemble
|
||||
|
||||
call show_display_data
|
||||
|
||||
mov esi,_error_prefix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,_code_cannot_be_generated
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,_message_suffix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
|
||||
jmp assembly_failed
|
||||
|
||||
assembly_done:
|
||||
|
||||
call show_display_data
|
||||
|
||||
cmp [first_error],0
|
||||
jne assembly_failed
|
||||
|
||||
cmp [no_logo],0
|
||||
jne summary_done
|
||||
mov eax,[current_pass]
|
||||
xor edx,edx
|
||||
call itoa
|
||||
call display_string
|
||||
mov esi,_passes
|
||||
cmp [current_pass],1
|
||||
jne display_passes_suffix
|
||||
mov esi,_pass
|
||||
display_passes_suffix:
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
ccall gettimeofday,end_time,0
|
||||
mov rax,[end_time.time_t]
|
||||
sub rax,[start_time.time_t]
|
||||
mov rcx,1000000
|
||||
mul rcx
|
||||
mov ecx,[end_time.suseconds_t]
|
||||
add ecx,50000
|
||||
add rax,rcx
|
||||
adc rdx,0
|
||||
mov ecx,[start_time.suseconds_t]
|
||||
sub rax,rcx
|
||||
sbb rdx,0
|
||||
mov rcx,1000000
|
||||
div rcx
|
||||
mov rbx,rax
|
||||
mov rax,rdx
|
||||
xor edx,edx
|
||||
mov rcx,100000
|
||||
div rcx
|
||||
mov [tenths_of_second],eax
|
||||
xchg rax,rbx
|
||||
or rbx,rax
|
||||
jz display_output_length
|
||||
mov rdx,rax
|
||||
shr rdx,32
|
||||
call itoa
|
||||
call display_string
|
||||
mov esi,_message_suffix
|
||||
mov ecx,1
|
||||
call display_string
|
||||
mov eax,[tenths_of_second]
|
||||
xor edx,edx
|
||||
call itoa
|
||||
call display_string
|
||||
mov esi,_seconds
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
display_output_length:
|
||||
call get_output_length
|
||||
push rax rdx
|
||||
call itoa
|
||||
call display_string
|
||||
pop rdx rax
|
||||
mov esi,_bytes
|
||||
cmp eax,1
|
||||
jne display_bytes_suffix
|
||||
test edx,edx
|
||||
jnz display_bytes_suffix
|
||||
mov esi,_byte
|
||||
display_bytes_suffix:
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
mov esi,_new_line
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
summary_done:
|
||||
|
||||
mov ebx,[source_path]
|
||||
mov edi,[output_path]
|
||||
call write_output_file
|
||||
jc write_failed
|
||||
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
|
||||
ccall exit,0
|
||||
|
||||
assembly_failed:
|
||||
|
||||
call show_errors
|
||||
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
|
||||
ccall exit,2
|
||||
|
||||
write_failed:
|
||||
mov ebx,_write_failed
|
||||
jmp fatal_error
|
||||
|
||||
out_of_memory:
|
||||
mov ebx,_out_of_memory
|
||||
jmp fatal_error
|
||||
|
||||
fatal_error:
|
||||
|
||||
mov esi,_error_prefix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,ebx
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,_message_suffix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
|
||||
ccall exit,3
|
||||
|
||||
display_usage_information:
|
||||
|
||||
mov esi,_usage
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
|
||||
call system_shutdown
|
||||
|
||||
ccall exit,1
|
||||
|
||||
get_arguments:
|
||||
xor eax,eax
|
||||
mov [initial_commands],eax
|
||||
mov [source_path],eax
|
||||
mov [output_path],eax
|
||||
mov [no_logo],al
|
||||
mov [verbosity_level],eax
|
||||
mov [maximum_number_of_passes],100
|
||||
mov [maximum_number_of_errors],1
|
||||
mov [maximum_depth_of_stack],10000
|
||||
mov rcx,[argc]
|
||||
mov rbx,[argv]
|
||||
add rbx,8
|
||||
dec ecx
|
||||
jz error_in_arguments
|
||||
get_argument:
|
||||
mov rsi,[rbx]
|
||||
mov al,[rsi]
|
||||
cmp al,'-'
|
||||
je get_option
|
||||
cmp [source_path],0
|
||||
jne get_output_file
|
||||
call strdup
|
||||
mov [source_path],eax
|
||||
jmp next_argument
|
||||
get_output_file:
|
||||
cmp [output_path],0
|
||||
jne error_in_arguments
|
||||
call strdup
|
||||
mov [output_path],eax
|
||||
jmp next_argument
|
||||
get_option:
|
||||
inc rsi
|
||||
lodsb
|
||||
cmp al,'e'
|
||||
je set_errors_limit
|
||||
cmp al,'E'
|
||||
je set_errors_limit
|
||||
cmp al,'i'
|
||||
je insert_initial_command
|
||||
cmp al,'I'
|
||||
je insert_initial_command
|
||||
cmp al,'p'
|
||||
je set_passes_limit
|
||||
cmp al,'P'
|
||||
je set_passes_limit
|
||||
cmp al,'r'
|
||||
je set_recursion_limit
|
||||
cmp al,'R'
|
||||
je set_recursion_limit
|
||||
cmp al,'v'
|
||||
je set_verbose_mode
|
||||
cmp al,'V'
|
||||
je set_verbose_mode
|
||||
cmp al,'n'
|
||||
je set_no_logo
|
||||
cmp al,'N'
|
||||
jne error_in_arguments
|
||||
set_no_logo:
|
||||
or [no_logo],-1
|
||||
cmp byte [rsi],0
|
||||
je next_argument
|
||||
error_in_arguments:
|
||||
or al,-1
|
||||
ret
|
||||
set_verbose_mode:
|
||||
cmp byte [rsi],0
|
||||
jne get_verbose_setting
|
||||
dec ecx
|
||||
jz error_in_arguments
|
||||
add rbx,8
|
||||
mov rsi,[rbx]
|
||||
get_verbose_setting:
|
||||
call get_option_value
|
||||
cmp edx,2
|
||||
ja error_in_arguments
|
||||
mov [verbosity_level],edx
|
||||
jmp next_argument
|
||||
set_errors_limit:
|
||||
cmp byte [rsi],0
|
||||
jne get_errors_setting
|
||||
dec ecx
|
||||
jz error_in_arguments
|
||||
add rbx,8
|
||||
mov rsi,[rbx]
|
||||
get_errors_setting:
|
||||
call get_option_value
|
||||
test edx,edx
|
||||
jz error_in_arguments
|
||||
mov [maximum_number_of_errors],edx
|
||||
jmp next_argument
|
||||
set_recursion_limit:
|
||||
cmp byte [rsi],0
|
||||
jne get_recursion_setting
|
||||
dec ecx
|
||||
jz error_in_arguments
|
||||
add rbx,8
|
||||
mov rsi,[rbx]
|
||||
get_recursion_setting:
|
||||
call get_option_value
|
||||
test edx,edx
|
||||
jz error_in_arguments
|
||||
mov [maximum_depth_of_stack],edx
|
||||
jmp next_argument
|
||||
set_passes_limit:
|
||||
cmp byte [rsi],0
|
||||
jne get_passes_setting
|
||||
dec ecx
|
||||
jz error_in_arguments
|
||||
add rbx,8
|
||||
mov rsi,[rbx]
|
||||
get_passes_setting:
|
||||
call get_option_value
|
||||
test edx,edx
|
||||
jz error_in_arguments
|
||||
mov [maximum_number_of_passes],edx
|
||||
next_argument:
|
||||
add rbx,8
|
||||
dec ecx
|
||||
jnz get_argument
|
||||
cmp [source_path],0
|
||||
je error_in_arguments
|
||||
xor al,al
|
||||
ret
|
||||
get_option_value:
|
||||
xor eax,eax
|
||||
mov edx,eax
|
||||
find_option_value:
|
||||
cmp byte [rsi],20h
|
||||
jne get_option_digit
|
||||
inc rsi
|
||||
jmp find_option_value
|
||||
get_option_digit:
|
||||
lodsb
|
||||
test al,al
|
||||
jz option_value_ok
|
||||
sub al,30h
|
||||
jc invalid_option_value
|
||||
cmp al,9
|
||||
ja invalid_option_value
|
||||
imul edx,10
|
||||
jo invalid_option_value
|
||||
add edx,eax
|
||||
jc invalid_option_value
|
||||
jmp get_option_digit
|
||||
option_value_ok:
|
||||
dec rsi
|
||||
clc
|
||||
ret
|
||||
invalid_option_value:
|
||||
stc
|
||||
ret
|
||||
insert_initial_command:
|
||||
cmp byte [rsi],0
|
||||
jne measure_initial_command
|
||||
dec ecx
|
||||
jz error_in_arguments
|
||||
add rbx,8
|
||||
mov rsi,[rbx]
|
||||
measure_initial_command:
|
||||
push rbx rcx rdi
|
||||
mov rdi,rsi
|
||||
or ecx,-1
|
||||
xor al,al
|
||||
repne scasb
|
||||
not ecx
|
||||
dec ecx
|
||||
mov edi,[initial_commands]
|
||||
lea eax,[ecx+2]
|
||||
test edi,edi
|
||||
jz allocate_initial_commands_buffer
|
||||
mov edx,[initial_commands_length]
|
||||
add edi,edx
|
||||
add eax,edx
|
||||
cmp eax,[initial_commands_maximum_length]
|
||||
ja grow_initial_commands_buffer
|
||||
copy_initial_command:
|
||||
rep movsb
|
||||
mov ax,0Ah
|
||||
stosw
|
||||
dec edi
|
||||
sub edi,[initial_commands]
|
||||
mov [initial_commands_length],edi
|
||||
pop rdi rcx rbx
|
||||
jmp next_argument
|
||||
allocate_initial_commands_buffer:
|
||||
push rsi rcx
|
||||
mov ecx,eax
|
||||
call malloc
|
||||
mov [initial_commands],eax
|
||||
mov [initial_commands_maximum_length],ecx
|
||||
mov edi,eax
|
||||
pop rcx rsi
|
||||
jmp copy_initial_command
|
||||
grow_initial_commands_buffer:
|
||||
push rsi rcx
|
||||
mov ecx,eax
|
||||
mov eax,[initial_commands]
|
||||
call realloc
|
||||
mov [initial_commands],eax
|
||||
mov [initial_commands_maximum_length],ecx
|
||||
mov edi,eax
|
||||
add edi,[initial_commands_length]
|
||||
pop rcx rsi
|
||||
jmp copy_initial_command
|
||||
|
||||
strdup:
|
||||
; in: rsi - ASCIIZ string
|
||||
; out: eax - copy of the string in 32-bit addressable memory
|
||||
; preserves: rbx, rcx, rsi
|
||||
push rbx rcx rsi
|
||||
mov rdi,rsi
|
||||
or ecx,-1
|
||||
xor al,al
|
||||
repne scasb
|
||||
not ecx
|
||||
push rsi rcx
|
||||
call malloc
|
||||
pop rcx rsi
|
||||
mov edi,eax
|
||||
rep movsb
|
||||
pop rsi rcx rbx
|
||||
ret
|
||||
|
||||
include 'system.inc'
|
||||
|
||||
use32on64
|
||||
|
||||
include '../../malloc.inc'
|
||||
include '../../assembler.inc'
|
||||
include '../../symbols.inc'
|
||||
include '../../expressions.inc'
|
||||
include '../../conditions.inc'
|
||||
include '../../floats.inc'
|
||||
include '../../directives.inc'
|
||||
include '../../calm.inc'
|
||||
include '../../errors.inc'
|
||||
include '../../map.inc'
|
||||
include '../../reader.inc'
|
||||
include '../../output.inc'
|
||||
include '../../console.inc'
|
||||
|
||||
section '__cstring' align 4
|
||||
|
||||
_logo db 'flat assembler version g.',VERSION,10,0
|
||||
|
||||
_usage db 'Usage: fasmg source [output]',10
|
||||
db 'Optional settings:',10
|
||||
db ' -p limit Set the maximum allowed number of passes (default 100)',10
|
||||
db ' -e limit Set the maximum number of displayed errors (default 1)',10
|
||||
db ' -r limit Set the maximum depth of the stack (default 10000)',10
|
||||
db ' -v flag Enable or disable showing all lines from the stack (default 0)',10
|
||||
db ' -i command Insert instruction at the beginning of source',13,10
|
||||
db ' -n Do not show logo nor summary',13,10
|
||||
db 0
|
||||
|
||||
_pass db ' pass, ',0
|
||||
_passes db ' passes, ',0
|
||||
_dot db '.'
|
||||
_seconds db ' seconds, ',0
|
||||
_byte db ' byte.',0
|
||||
_bytes db ' bytes.',0
|
||||
|
||||
_write_failed db 'failed to write the output file',0
|
||||
_out_of_memory db 'not enough memory to complete the assembly',0
|
||||
_code_cannot_be_generated db 'could not generate code within the allowed number of passes',0
|
||||
|
||||
_open_mode db 'r',0
|
||||
_create_mode db 'w',0
|
||||
|
||||
include '../../tables.inc'
|
||||
include '../../messages.inc'
|
||||
|
||||
segment '__DATA' readable writable
|
||||
|
||||
section '__bss' align 4
|
||||
|
||||
include '../../variables.inc'
|
||||
|
||||
mmap_hint dd ?
|
||||
malloc_freelist dd ?
|
||||
|
||||
source_path dd ?
|
||||
output_path dd ?
|
||||
maximum_number_of_passes dd ?
|
||||
|
||||
initial_commands dd ?
|
||||
initial_commands_length dd ?
|
||||
initial_commands_maximum_length dd ?
|
||||
|
||||
files dd ?
|
||||
files_count dd ?
|
||||
files_maximum_count dd ?
|
||||
|
||||
argc dq ?
|
||||
argv dq ?
|
||||
timestamp dq ?
|
||||
|
||||
start_time timeval
|
||||
end_time timeval
|
||||
tenths_of_second dd ?
|
||||
|
||||
verbosity_level dd ?
|
||||
no_logo db ?
|
||||
|
||||
local_heap_available db ?
|
||||
|
||||
path_buffer rb 1000h
|
||||
|
||||
align 1000h
|
||||
|
||||
LOCAL_HEAP_SIZE = 1000000h
|
||||
|
||||
local_heap rb LOCAL_HEAP_SIZE
|
41
toolchain/fasmg.kl0e/source/macos/x64/selfhost.inc
Normal file
41
toolchain/fasmg.kl0e/source/macos/x64/selfhost.inc
Normal file
@ -0,0 +1,41 @@
|
||||
|
||||
; Adapted and tested by Jacob Young (jacobly.alt@gmail.com)
|
||||
|
||||
include '../../linux/x64/selfhost.inc'
|
||||
|
||||
macro format?.MachO64? variant
|
||||
match , variant
|
||||
MachO.Settings.ProcessorType = CPU_TYPE_X86_64
|
||||
MachO.Settings.FileType equ MH_OBJECT
|
||||
include '../../../examples/x86/include/format/macho.inc'
|
||||
use64
|
||||
else match =executable?, variant
|
||||
MachO.Settings.ProcessorType = CPU_TYPE_X86_64
|
||||
MachO.Settings.BaseAddress = 0x1000
|
||||
include '../../../examples/x86/include/format/macho.inc'
|
||||
use64
|
||||
else
|
||||
err 'invalid argument'
|
||||
end match
|
||||
end macro
|
||||
|
||||
iterate reg, rdi, rsi, rdx, rcx, r8, r9
|
||||
arguments.%? equ reg
|
||||
end iterate
|
||||
|
||||
macro ccall? proc*,args&
|
||||
local size
|
||||
mov rbp,rsp
|
||||
and rsp,0FFFFFFFFFFFFFFF0h
|
||||
match any, args
|
||||
iterate arg, args
|
||||
if sizeof (arg)
|
||||
lea arguments.%,[arg]
|
||||
else if ~ arg eq arguments.%
|
||||
mov arguments.%,arg
|
||||
end if
|
||||
end iterate
|
||||
end match
|
||||
call proc
|
||||
mov rsp,rbp
|
||||
end macro
|
287
toolchain/fasmg.kl0e/source/macos/x64/system.inc
Normal file
287
toolchain/fasmg.kl0e/source/macos/x64/system.inc
Normal file
@ -0,0 +1,287 @@
|
||||
|
||||
; Adapted and tested by Jacob Young (jacobly.alt@gmail.com)
|
||||
|
||||
LINE_FEED = 0Ah
|
||||
|
||||
system_init:
|
||||
ccall libc.time,timestamp
|
||||
or [local_heap_available],1
|
||||
retn
|
||||
|
||||
system_shutdown:
|
||||
retn
|
||||
|
||||
open:
|
||||
; in: edx - path to file
|
||||
; out: ebx = file handle, cf set on error
|
||||
; preserves: esi, edi
|
||||
push rsi rdi
|
||||
call adapt_path
|
||||
ccall libc.fopen,rbx,_open_mode
|
||||
put_file_entry:
|
||||
pop rdi rsi
|
||||
test rax,rax
|
||||
jz interface_error
|
||||
push rax
|
||||
mov eax,[files]
|
||||
mov ecx,[files_count]
|
||||
mov ebx,ecx
|
||||
inc ecx
|
||||
mov [files_count],ecx
|
||||
cmp ecx,[files_maximum_count]
|
||||
ja grow_files_buffer
|
||||
store_file_entry:
|
||||
pop rdx
|
||||
mov [eax+ebx*8],rdx
|
||||
clc
|
||||
retn
|
||||
interface_error:
|
||||
stc
|
||||
retn
|
||||
grow_files_buffer:
|
||||
shl ecx,4
|
||||
test eax,eax
|
||||
jz allocate_files_buffer
|
||||
call realloc
|
||||
jmp allocated_files_buffer
|
||||
allocate_files_buffer:
|
||||
call malloc
|
||||
allocated_files_buffer:
|
||||
mov [files],eax
|
||||
shr ecx,3
|
||||
mov [files_maximum_count],ecx
|
||||
jmp store_file_entry
|
||||
adapt_path:
|
||||
xor ecx,ecx
|
||||
mov ebx,path_buffer
|
||||
copy_path:
|
||||
mov al,[edx+ecx]
|
||||
cmp al,'\'
|
||||
jne path_char_ok
|
||||
mov al,'/'
|
||||
path_char_ok:
|
||||
cmp ecx,1000h
|
||||
jae out_of_memory
|
||||
mov [ebx+ecx],al
|
||||
inc ecx
|
||||
test al,al
|
||||
jnz copy_path
|
||||
retn
|
||||
create:
|
||||
; in: edx - path to file
|
||||
; out: ebx = file handle, cf set on error
|
||||
; preserves: esi, edi
|
||||
push rsi rdi
|
||||
call adapt_path
|
||||
ccall libc.fopen,rbx,_create_mode
|
||||
jmp put_file_entry
|
||||
write:
|
||||
; in: ebx = file handle, edx - data, ecx = number of bytes
|
||||
; out: cf set on error
|
||||
; preserves: ebx, esi, edi
|
||||
push rbx rcx rsi rdi
|
||||
mov eax,[files]
|
||||
mov rax,[eax+ebx*8]
|
||||
ccall libc.fwrite,rdx,1,rcx,rax
|
||||
pop rdi rsi rcx rbx
|
||||
cmp eax,ecx
|
||||
jne interface_error
|
||||
clc
|
||||
ret
|
||||
read:
|
||||
; in: ebx = file handle, edx - buffer, ecx = number of bytes
|
||||
; out: cf set on error
|
||||
; preserves: ebx, esi, edi
|
||||
push rbx rcx rsi rdi
|
||||
mov eax,[files]
|
||||
mov rax,[eax+ebx*8]
|
||||
ccall libc.fread,rdx,1,rcx,rax
|
||||
pop rdi rsi rcx rbx
|
||||
cmp eax,ecx
|
||||
jne interface_error
|
||||
clc
|
||||
ret
|
||||
close:
|
||||
; in: ebx = file handle
|
||||
; preserves: ebx, esi, edi
|
||||
push rsi rdi
|
||||
mov edi,[files]
|
||||
mov rdi,[edi+ebx*8]
|
||||
ccall libc.fclose,rdi
|
||||
pop rdi rsi
|
||||
ret
|
||||
lseek:
|
||||
; in: ebx = file handle, cl = method, edx:eax = offset
|
||||
; out: edx:eax = new offset from the beginning of file, cf set on error
|
||||
; preserves: ebx, esi, edi
|
||||
push rsi rdi rbx
|
||||
shl rdx,32
|
||||
or rax,rdx
|
||||
movzx ecx,cl
|
||||
mov edi,[files]
|
||||
mov rdi,[edi+ebx*8]
|
||||
push rdi
|
||||
ccall libc.fseek,rdi,rax,rcx
|
||||
test eax,eax
|
||||
jnz lseek_error
|
||||
pop rdi
|
||||
ccall libc.ftell,rdi
|
||||
cmp rax,-1
|
||||
je lseek_error
|
||||
mov rdx,rax
|
||||
shr rdx,32
|
||||
mov eax,eax
|
||||
pop rbx rdi rsi
|
||||
clc
|
||||
ret
|
||||
lseek_error:
|
||||
pop rbx rdi rsi
|
||||
stc
|
||||
ret
|
||||
|
||||
get_timestamp:
|
||||
; out: edx:eax = timestamp
|
||||
; preserves: ebx, ecx, esi, edi
|
||||
; note: during the passes of a single assembly this function should always return the same value
|
||||
mov eax,dword [timestamp]
|
||||
mov edx,dword [timestamp+4]
|
||||
retn
|
||||
|
||||
display_string:
|
||||
; in:
|
||||
; esi - string
|
||||
; ecx = string length, zero for ASCIIZ string
|
||||
; preserves: ebx, esi
|
||||
push rbx rsi
|
||||
test ecx,ecx
|
||||
jnz write_string_to_stdout
|
||||
xor al,al
|
||||
mov edi,esi
|
||||
or ecx,-1
|
||||
repne scasb
|
||||
neg ecx
|
||||
sub ecx,2
|
||||
write_string_to_stdout:
|
||||
ccall libc.write,1,rsi,rcx
|
||||
pop rsi rbx
|
||||
retn
|
||||
|
||||
display_error_string:
|
||||
; in:
|
||||
; esi - string
|
||||
; ecx = string length, zero for ASCIIZ string
|
||||
; preserves: ebx, esi
|
||||
push rbx rsi
|
||||
test ecx,ecx
|
||||
jnz write_string_to_stderr
|
||||
xor al,al
|
||||
mov edi,esi
|
||||
or ecx,-1
|
||||
repne scasb
|
||||
neg ecx
|
||||
sub ecx,2
|
||||
write_string_to_stderr:
|
||||
ccall libc.write,2,rsi,rcx
|
||||
pop rsi rbx
|
||||
retn
|
||||
|
||||
get_environment_variable:
|
||||
; in:
|
||||
; esi - name
|
||||
; edi - buffer for value
|
||||
; ecx = size of buffer
|
||||
; out:
|
||||
; eax = length of value
|
||||
; preserves: ebx, esi, edi
|
||||
push rbx rcx rsi rdi
|
||||
ccall getenv,rsi
|
||||
pop rdi rsi rcx rbx
|
||||
test rax,rax
|
||||
jz no_environment_variable
|
||||
push rsi
|
||||
mov rsi,rax
|
||||
xor eax,eax
|
||||
copy_environment_variable:
|
||||
mov dl,[rsi+rax]
|
||||
cmp eax,ecx
|
||||
jae next_environment_variable_character
|
||||
mov [edi+eax],dl
|
||||
next_environment_variable_character:
|
||||
inc eax
|
||||
test dl,dl
|
||||
jnz copy_environment_variable
|
||||
pop rsi
|
||||
environment_variable_ok:
|
||||
ret
|
||||
no_environment_variable:
|
||||
mov eax,1
|
||||
jecxz environment_variable_ok
|
||||
and byte [edi],0
|
||||
ret
|
||||
|
||||
VALLOC_MINIMUM_SIZE = 100000h
|
||||
|
||||
valloc:
|
||||
; in: ecx = requested minimum size
|
||||
; out: eax - allocated block, ecx = allocated size, zero if failed
|
||||
; preserves: ebx, esi, edi
|
||||
cmp ecx,VALLOC_MINIMUM_SIZE
|
||||
jbe valloc_size_minimum
|
||||
dec ecx
|
||||
and ecx,(-1) shl 12
|
||||
add ecx,1 shl 12
|
||||
jmp valloc_size_ready
|
||||
valloc_size_minimum:
|
||||
mov ecx,VALLOC_MINIMUM_SIZE
|
||||
valloc_size_ready:
|
||||
push rbx rsi rdi
|
||||
cmp [local_heap_available],0
|
||||
je valloc_mmap
|
||||
cmp ecx,LOCAL_HEAP_SIZE
|
||||
ja valloc_mmap
|
||||
and [local_heap_available],0
|
||||
mov eax,local_heap
|
||||
mov ecx,LOCAL_HEAP_SIZE
|
||||
jmp valloc_ok
|
||||
valloc_mmap:
|
||||
push rcx
|
||||
ccall mmap,0,rcx, \
|
||||
3, \ ; PROT_READ + PROT_WRITE
|
||||
9002h, \ ; MAP_PRIVATE + MAP_ANONYMOUS + MAP_32BIT
|
||||
-1,0
|
||||
pop rsi
|
||||
cmp eax,-1
|
||||
je valloc_mmap_with_hint
|
||||
mov ecx,eax
|
||||
cmp rcx,rax
|
||||
jne valloc_mmap_unusable
|
||||
add ecx,esi
|
||||
jnc mmap_ok
|
||||
valloc_mmap_unusable:
|
||||
ccall munmap,rax,rsi
|
||||
valloc_mmap_with_hint:
|
||||
push rsi
|
||||
mov edi,[mmap_hint]
|
||||
ccall mmap,rdi,rsi, \
|
||||
3, \ ; PROT_READ + PROT_WRITE
|
||||
1002h, \ ; MAP_PRIVATE + MAP_ANONYMOUS
|
||||
-1,0
|
||||
pop rsi
|
||||
cmp eax,-1
|
||||
je valloc_failed
|
||||
mov ecx,eax
|
||||
cmp rcx,rax
|
||||
jne valloc_failed
|
||||
add ecx,esi
|
||||
jc valloc_failed
|
||||
mmap_ok:
|
||||
sub ecx,eax
|
||||
valloc_ok:
|
||||
lea edx,[eax+ecx]
|
||||
mov [mmap_hint],edx
|
||||
pop rdi rsi rbx
|
||||
retn
|
||||
valloc_failed:
|
||||
xor ecx,ecx
|
||||
pop rdi rsi rbx
|
||||
retn
|
343
toolchain/fasmg.kl0e/source/malloc.inc
Normal file
343
toolchain/fasmg.kl0e/source/malloc.inc
Normal file
@ -0,0 +1,343 @@
|
||||
|
||||
; a very basic implementation of malloc/realloc
|
||||
; for porting fasmg to systems that do not have such API natively
|
||||
|
||||
struct MemoryHeader
|
||||
size dd ? ; total size of this block, the lowest bit set for blocks in use
|
||||
preceding_size dd ? ; total size of the block that precedes this one in memory (zero if this is an initial block of address range)
|
||||
ends
|
||||
|
||||
struct FreeMemory
|
||||
header MemoryHeader
|
||||
right dd ? ; next free block in cyclic list
|
||||
left dd ? ; previous free block in cyclic list
|
||||
ends
|
||||
|
||||
assert defined valloc
|
||||
; in: ecx = requested minimum size
|
||||
; out: eax - allocated block, ecx = allocated size, zero if failed
|
||||
; preserves: ebx, esi, edi
|
||||
; note:
|
||||
; valloc is called to request raw memory from the OS;
|
||||
; it is encouraged to allocate more memory than requested (even entire available memory),
|
||||
; the obtained memory is kept indefinitely in the pool for malloc
|
||||
; and should be released by OS automatically when the process ends;
|
||||
; if the OS does not do it automatically, additional list of the memory areas
|
||||
; may need to be maintained to release them before exit
|
||||
|
||||
malloc:
|
||||
malloc_fixed:
|
||||
malloc_growable:
|
||||
; in: ecx = requested size
|
||||
; out: eax - allocated block, ecx = allocated size, on error jumps to out_of_memory (does not return)
|
||||
; preserves: ebx, esi, edi
|
||||
add ecx,sizeof.MemoryHeader-1
|
||||
jc out_of_memory
|
||||
and ecx,(-1) shl 2
|
||||
add ecx,1 shl 2
|
||||
jc out_of_memory
|
||||
cmp ecx,sizeof.FreeMemory
|
||||
jae malloc_size_ok
|
||||
mov ecx,sizeof.FreeMemory
|
||||
malloc_size_ok:
|
||||
mov eax,[malloc_freelist]
|
||||
test eax,eax
|
||||
jz malloc_new
|
||||
find_fit:
|
||||
cmp ecx,[eax+MemoryHeader.size]
|
||||
jbe malloc_use_block
|
||||
mov eax,[eax+FreeMemory.left]
|
||||
cmp eax,[malloc_freelist]
|
||||
jne find_fit
|
||||
malloc_new:
|
||||
push ecx
|
||||
add ecx,sizeof.MemoryHeader
|
||||
jc out_of_memory
|
||||
call valloc
|
||||
test ecx,ecx
|
||||
jz out_of_memory
|
||||
xor edx,edx
|
||||
mov [eax+MemoryHeader.preceding_size],edx
|
||||
pop edx
|
||||
push eax
|
||||
sub ecx,edx
|
||||
cmp ecx,sizeof.FreeMemory+sizeof.MemoryHeader
|
||||
jb no_space_for_free_block
|
||||
mov [eax+MemoryHeader.size],edx
|
||||
add eax,edx
|
||||
mov [eax+MemoryHeader.preceding_size],edx
|
||||
mov edx,ecx
|
||||
sub edx,sizeof.MemoryHeader
|
||||
dec edx
|
||||
and edx,(-1) shl 2
|
||||
add edx,1 shl 2
|
||||
mov [eax+MemoryHeader.size],edx
|
||||
mov ecx,[malloc_freelist]
|
||||
jecxz freelist_empty
|
||||
mov [eax+FreeMemory.left],ecx
|
||||
mov edx,eax
|
||||
xchg edx,[ecx+FreeMemory.right]
|
||||
mov [eax+FreeMemory.right],edx
|
||||
mov [edx+FreeMemory.left],eax
|
||||
mov edx,[eax+MemoryHeader.size]
|
||||
jmp free_block_ready
|
||||
no_space_for_free_block:
|
||||
sub ecx,sizeof.MemoryHeader
|
||||
add edx,ecx
|
||||
mov [eax+MemoryHeader.size],edx
|
||||
jmp append_limiter
|
||||
freelist_empty:
|
||||
mov [eax+FreeMemory.left],eax
|
||||
mov [eax+FreeMemory.right],eax
|
||||
free_block_ready:
|
||||
mov [malloc_freelist],eax
|
||||
append_limiter:
|
||||
add eax,edx
|
||||
mov [eax+MemoryHeader.preceding_size],edx
|
||||
mov [eax+MemoryHeader.size],sizeof.MemoryHeader or 1 ; cannot be freed
|
||||
pop eax
|
||||
finish_malloc:
|
||||
mov ecx,[eax+MemoryHeader.size]
|
||||
or [eax+MemoryHeader.size],1
|
||||
add eax,sizeof.MemoryHeader
|
||||
sub ecx,sizeof.MemoryHeader
|
||||
retn
|
||||
malloc_use_block:
|
||||
mov edx,[eax+MemoryHeader.size]
|
||||
sub edx,ecx
|
||||
cmp edx,sizeof.FreeMemory
|
||||
jb use_whole_block
|
||||
mov [eax+MemoryHeader.size],ecx
|
||||
mov [eax+ecx+MemoryHeader.preceding_size],ecx
|
||||
add ecx,eax
|
||||
mov [malloc_freelist],ecx
|
||||
mov [ecx+MemoryHeader.size],edx
|
||||
mov [ecx+edx+MemoryHeader.preceding_size],edx
|
||||
mov edx,[eax+FreeMemory.right]
|
||||
cmp edx,eax
|
||||
je update_free_singleton
|
||||
mov [ecx+FreeMemory.right],edx
|
||||
mov [edx+FreeMemory.left],ecx
|
||||
mov edx,[eax+FreeMemory.left]
|
||||
mov [ecx+FreeMemory.left],edx
|
||||
mov [edx+FreeMemory.right],ecx
|
||||
jmp finish_malloc
|
||||
update_free_singleton:
|
||||
mov [ecx+FreeMemory.left],ecx
|
||||
mov [ecx+FreeMemory.right],ecx
|
||||
jmp finish_malloc
|
||||
use_whole_block:
|
||||
mov edx,[eax+FreeMemory.right]
|
||||
cmp edx,eax
|
||||
je depleted_freelist
|
||||
mov ecx,[eax+FreeMemory.left]
|
||||
mov [ecx+FreeMemory.right],edx
|
||||
mov [edx+FreeMemory.left],ecx
|
||||
mov [malloc_freelist],edx
|
||||
jmp finish_malloc
|
||||
depleted_freelist:
|
||||
and [malloc_freelist],0
|
||||
jmp finish_malloc
|
||||
|
||||
mfree:
|
||||
; in: eax - memory block
|
||||
; out: cf set on error
|
||||
; preserves: ebx, esi, edi
|
||||
; note: eax may have value 0 or -1, it should be treated as invalid input then
|
||||
test eax,eax
|
||||
jz mfree_error
|
||||
cmp eax,-1
|
||||
je mfree_error
|
||||
sub eax,sizeof.MemoryHeader
|
||||
mov ecx,[eax+MemoryHeader.size]
|
||||
btr ecx,0
|
||||
jnc mfree_error
|
||||
cmp ecx,sizeof.FreeMemory
|
||||
jb mfree_error
|
||||
cmp [eax+ecx+MemoryHeader.preceding_size],ecx
|
||||
jne mfree_error
|
||||
mov [eax+MemoryHeader.size],ecx
|
||||
mov edx,eax
|
||||
sub edx,[eax+MemoryHeader.preceding_size]
|
||||
cmp edx,eax
|
||||
je no_preceding_block
|
||||
test [edx+MemoryHeader.size],1
|
||||
jz coalesce_with_preceding_block
|
||||
no_preceding_block:
|
||||
test [eax+ecx+MemoryHeader.size],1
|
||||
jz coalesce_with_following_block
|
||||
mov ecx,[malloc_freelist]
|
||||
jecxz mfree_init_freelist
|
||||
mov edx,[ecx+FreeMemory.right]
|
||||
mov [eax+FreeMemory.left],ecx
|
||||
mov [edx+FreeMemory.left],eax
|
||||
mov [eax+FreeMemory.right],edx
|
||||
mov [ecx+FreeMemory.right],eax
|
||||
mfree_ok:
|
||||
mov [malloc_freelist],eax
|
||||
clc
|
||||
retn
|
||||
mfree_init_freelist:
|
||||
mov [eax+FreeMemory.left],eax
|
||||
mov [eax+FreeMemory.right],eax
|
||||
jmp mfree_ok
|
||||
mfree_error:
|
||||
stc
|
||||
retn
|
||||
coalesce_with_preceding_block:
|
||||
add ecx,[edx+MemoryHeader.size]
|
||||
test [edx+ecx+MemoryHeader.size],1
|
||||
jz coalesce_on_both_ends
|
||||
mov [edx+MemoryHeader.size],ecx
|
||||
mov [edx+ecx+MemoryHeader.preceding_size],ecx
|
||||
clc
|
||||
retn
|
||||
coalesce_on_both_ends:
|
||||
lea eax,[edx+ecx]
|
||||
add ecx,[eax+MemoryHeader.size]
|
||||
mov [edx+MemoryHeader.size],ecx
|
||||
mov [edx+ecx+MemoryHeader.preceding_size],ecx
|
||||
mov [malloc_freelist],edx
|
||||
mov ecx,[eax+FreeMemory.left]
|
||||
mov edx,[eax+FreeMemory.right]
|
||||
mov [edx+FreeMemory.left],ecx
|
||||
mov [ecx+FreeMemory.right],edx
|
||||
clc
|
||||
retn
|
||||
coalesce_with_following_block:
|
||||
push ebx
|
||||
lea ebx,[eax+ecx]
|
||||
add ecx,[ebx+MemoryHeader.size]
|
||||
mov [eax+MemoryHeader.size],ecx
|
||||
mov [eax+ecx+MemoryHeader.preceding_size],ecx
|
||||
mov ecx,[ebx+FreeMemory.left]
|
||||
mov edx,[ebx+FreeMemory.right]
|
||||
mov [ecx+FreeMemory.right],eax
|
||||
mov [edx+FreeMemory.left],eax
|
||||
mov ecx,[ebx+FreeMemory.left]
|
||||
mov edx,[ebx+FreeMemory.right]
|
||||
mov [eax+FreeMemory.left],ecx
|
||||
mov [eax+FreeMemory.right],edx
|
||||
pop ebx
|
||||
jmp mfree_ok
|
||||
|
||||
realloc:
|
||||
; in: eax - memory block, ecx = requested size
|
||||
; out: eax - resized block, ecx = allocated size, on error jumps to out_of_memory (does not return)
|
||||
; preserves: ebx, esi, edi
|
||||
add ecx,sizeof.MemoryHeader-1
|
||||
jc out_of_memory
|
||||
and ecx,(-1) shl 2
|
||||
add ecx,1 shl 2
|
||||
jc out_of_memory
|
||||
sub eax,sizeof.MemoryHeader
|
||||
mov edx,[eax+MemoryHeader.size]
|
||||
and edx,not 1
|
||||
cmp ecx,edx
|
||||
jbe realloc_retain
|
||||
test [eax+edx+MemoryHeader.size],1
|
||||
jnz realloc_and_copy
|
||||
add edx,[eax+edx+MemoryHeader.size]
|
||||
cmp ecx,edx
|
||||
ja realloc_and_copy
|
||||
sub edx,ecx
|
||||
cmp edx,sizeof.FreeMemory
|
||||
jb append_whole_block
|
||||
push esi edi
|
||||
push ecx edx
|
||||
lea edi,[eax+ecx]
|
||||
xchg ecx,[eax+MemoryHeader.size]
|
||||
and ecx,not 1
|
||||
lea esi,[eax+ecx]
|
||||
mov ecx,[esi+FreeMemory.left]
|
||||
mov edx,[esi+FreeMemory.right]
|
||||
mov [edx+FreeMemory.left],edi
|
||||
mov [ecx+FreeMemory.right],edi
|
||||
mov ecx,[esi+FreeMemory.left]
|
||||
mov edx,[esi+FreeMemory.right]
|
||||
mov [edi+FreeMemory.left],ecx
|
||||
mov [edi+FreeMemory.right],edx
|
||||
mov [malloc_freelist],edi
|
||||
pop edx ecx
|
||||
mov [edi+MemoryHeader.size],edx
|
||||
mov [edi+edx+MemoryHeader.preceding_size],edx
|
||||
mov [edi+MemoryHeader.preceding_size],ecx
|
||||
pop edi esi
|
||||
jmp finish_malloc
|
||||
append_whole_block:
|
||||
add edx,ecx
|
||||
mov [eax+edx+MemoryHeader.preceding_size],edx
|
||||
xchg edx,[eax+MemoryHeader.size]
|
||||
and edx,not 1
|
||||
add edx,eax
|
||||
mov ecx,[edx+FreeMemory.left]
|
||||
cmp ecx,edx
|
||||
je depleted_freelist
|
||||
mov edx,[edx+FreeMemory.right]
|
||||
mov [ecx+FreeMemory.right],edx
|
||||
mov [edx+FreeMemory.left],ecx
|
||||
mov [malloc_freelist],ecx
|
||||
jmp finish_malloc
|
||||
realloc_retain:
|
||||
and [eax+MemoryHeader.size],not 1
|
||||
jmp finish_malloc
|
||||
realloc_and_copy:
|
||||
push esi edi
|
||||
lea esi,[eax+sizeof.MemoryHeader]
|
||||
call malloc_growable
|
||||
push eax ecx
|
||||
mov edi,eax
|
||||
mov eax,esi
|
||||
mov ecx,[esi-sizeof.MemoryHeader+MemoryHeader.size]
|
||||
shr ecx,2
|
||||
rep movsd
|
||||
call mfree
|
||||
pop ecx eax
|
||||
pop edi esi
|
||||
retn
|
||||
|
||||
if used mcheck
|
||||
|
||||
mcheck:
|
||||
pushf
|
||||
push eax ebx ecx edx
|
||||
mov eax,[malloc_freelist]
|
||||
test eax,eax
|
||||
jz integrity_verified
|
||||
verify_freelist:
|
||||
mov ebx,eax
|
||||
verify_preceding_blocks:
|
||||
mov ecx,[ebx+MemoryHeader.preceding_size]
|
||||
jecxz preceding_blocks_ok
|
||||
sub ebx,ecx
|
||||
mov edx,[ebx+MemoryHeader.size]
|
||||
and edx,not 1
|
||||
cmp ecx,edx
|
||||
je verify_preceding_blocks
|
||||
jmp internal_error
|
||||
preceding_blocks_ok:
|
||||
mov ebx,eax
|
||||
verify_following_blocks:
|
||||
mov ecx,[ebx+MemoryHeader.size]
|
||||
and ecx,not 1
|
||||
cmp ecx,sizeof.MemoryHeader
|
||||
je following_blocks_ok
|
||||
add ebx,ecx
|
||||
cmp ecx,[ebx+MemoryHeader.preceding_size]
|
||||
je verify_following_blocks
|
||||
jmp internal_error
|
||||
following_blocks_ok:
|
||||
mov edx,[eax+FreeMemory.right]
|
||||
cmp eax,[edx+FreeMemory.left]
|
||||
je verify_next
|
||||
jmp internal_error
|
||||
verify_next:
|
||||
mov eax,edx
|
||||
cmp eax,[malloc_freelist]
|
||||
jne verify_freelist
|
||||
integrity_verified:
|
||||
pop edx ecx ebx eax
|
||||
popf
|
||||
retn
|
||||
|
||||
end if
|
237
toolchain/fasmg.kl0e/source/map.inc
Normal file
237
toolchain/fasmg.kl0e/source/map.inc
Normal file
@ -0,0 +1,237 @@
|
||||
|
||||
; this is a simple map used primarily for the source cache
|
||||
|
||||
struct Map
|
||||
hash_mask dd ?
|
||||
linked_blocks dd ?
|
||||
free_space dd ?
|
||||
free_space_length dd ?
|
||||
ends
|
||||
|
||||
struct MapEntry
|
||||
name dd ?
|
||||
name_length dd ?
|
||||
value dd ?
|
||||
next_entry dd ?
|
||||
ends
|
||||
|
||||
create_string_map:
|
||||
; in: cl = number of hash bits
|
||||
; out: ebx - new map
|
||||
; preserves: esi
|
||||
mov ebx,1
|
||||
shl ebx,cl
|
||||
shl ebx,2
|
||||
lea ecx,[sizeof.Map+ebx*4]
|
||||
call malloc_fixed
|
||||
xchg ebx,eax
|
||||
mov ecx,eax
|
||||
dec eax
|
||||
mov [ebx+Map.hash_mask],eax
|
||||
lea edi,[ebx+sizeof.Map]
|
||||
xor eax,eax
|
||||
rep stosd
|
||||
mov ecx,1000h
|
||||
call malloc_fixed
|
||||
mov [ebx+Map.linked_blocks],eax
|
||||
xor edx,edx
|
||||
mov [eax],edx
|
||||
add eax,10h
|
||||
mov [ebx+Map.free_space],eax
|
||||
mov [ebx+Map.free_space_length],1000h-10h
|
||||
retn
|
||||
|
||||
destroy_string_map:
|
||||
; in: ebx - map
|
||||
; preserves: esi, edi
|
||||
mov eax,ebx
|
||||
mov ebx,[ebx+Map.linked_blocks]
|
||||
call mfree
|
||||
free_map_blocks:
|
||||
test ebx,ebx
|
||||
jz string_map_destroyed
|
||||
mov eax,ebx
|
||||
mov ebx,[ebx]
|
||||
call mfree
|
||||
jmp free_map_blocks
|
||||
string_map_destroyed:
|
||||
retn
|
||||
|
||||
get_from_map:
|
||||
; in:
|
||||
; ebx - map
|
||||
; esi - string
|
||||
; ecx = string length, zero for ASCIIZ string
|
||||
; out:
|
||||
; eax = value
|
||||
; cf set when no entry found
|
||||
; preserves: ebx, [esi], edi
|
||||
; note: when entry is found, esi is replaced with pointer to the same string in persistent storage
|
||||
call get_bucket
|
||||
test eax,eax
|
||||
jz not_found_in_map
|
||||
call find_map_entry
|
||||
jc not_found_in_map
|
||||
mov eax,[eax+MapEntry.value]
|
||||
retn
|
||||
get_bucket:
|
||||
call hash_string
|
||||
and edx,[ebx+Map.hash_mask]
|
||||
mov eax,[ebx+sizeof.Map+edx*4]
|
||||
retn
|
||||
find_map_entry:
|
||||
cmp [eax+MapEntry.name_length],ecx
|
||||
jne next_map_entry
|
||||
push edi
|
||||
mov edi,[eax+MapEntry.name]
|
||||
test edi,edi
|
||||
jz not_this_map_entry
|
||||
push ecx esi
|
||||
repe cmpsb
|
||||
pop esi ecx
|
||||
jne not_this_map_entry
|
||||
mov esi,edi
|
||||
sub esi,ecx
|
||||
pop edi
|
||||
clc
|
||||
retn
|
||||
not_this_map_entry:
|
||||
pop edi
|
||||
next_map_entry:
|
||||
mov eax,[eax+MapEntry.next_entry]
|
||||
test eax,eax
|
||||
jnz find_map_entry
|
||||
not_found_in_map:
|
||||
stc
|
||||
retn
|
||||
|
||||
put_into_map:
|
||||
; in:
|
||||
; ebx - map
|
||||
; esi - string
|
||||
; ecx = string length, zero for ASCIIZ string
|
||||
; eax = value
|
||||
; preserves: ebx, [esi], edi
|
||||
; note:
|
||||
; esi is replaced with pointer to the same string in persistent storage,
|
||||
; an ASCIIZ string is a key with length including the terminating zero
|
||||
; and when it is put into persistent storage, final zero is copied as well
|
||||
push eax
|
||||
call get_bucket
|
||||
test eax,eax
|
||||
jz new_bucket
|
||||
call find_map_entry
|
||||
jnc put_value_into_map_entry
|
||||
mov eax,[ebx+sizeof.Map+edx*4]
|
||||
find_free_map_entry:
|
||||
cmp [eax+MapEntry.name],0
|
||||
je fill_map_entry
|
||||
mov edx,eax
|
||||
mov eax,[eax+MapEntry.next_entry]
|
||||
test eax,eax
|
||||
jnz find_free_map_entry
|
||||
call allocate_map_entry
|
||||
mov [edx+MapEntry.next_entry],eax
|
||||
jmp new_map_entry
|
||||
new_bucket:
|
||||
call allocate_map_entry
|
||||
mov [ebx+sizeof.Map+edx*4],eax
|
||||
new_map_entry:
|
||||
mov [eax+MapEntry.next_entry],0
|
||||
fill_map_entry:
|
||||
mov [eax+MapEntry.name_length],ecx
|
||||
push eax
|
||||
call store_string
|
||||
pop eax
|
||||
mov [eax+MapEntry.name],esi
|
||||
put_value_into_map_entry:
|
||||
pop [eax+MapEntry.value]
|
||||
retn
|
||||
allocate_map_entry:
|
||||
mov eax,[ebx+Map.free_space]
|
||||
add [ebx+Map.free_space],sizeof.MapEntry
|
||||
sub [ebx+Map.free_space_length],sizeof.MapEntry
|
||||
jc map_out_of_free_space
|
||||
retn
|
||||
map_out_of_free_space:
|
||||
push ecx edx
|
||||
mov ecx,1000h
|
||||
call malloc_fixed
|
||||
mov edx,eax
|
||||
xchg [ebx+Map.linked_blocks],edx
|
||||
mov [eax],edx
|
||||
add eax,10h
|
||||
mov [ebx+Map.free_space],eax
|
||||
mov [ebx+Map.free_space_length],1000h-10h
|
||||
pop edx ecx
|
||||
jmp allocate_map_entry
|
||||
|
||||
remove_from_map:
|
||||
; in:
|
||||
; ebx - map
|
||||
; esi - string
|
||||
; ecx = string length, zero for ASCIIZ string
|
||||
; preserves: ebx, [esi], edi
|
||||
call get_bucket
|
||||
test eax,eax
|
||||
jz not_found_in_map
|
||||
call find_map_entry
|
||||
jc not_found_in_map
|
||||
mov dword [eax+MapEntry.name],0
|
||||
retn
|
||||
|
||||
iterate_through_map:
|
||||
; in:
|
||||
; ebx - map
|
||||
; edi - callback function
|
||||
; callback:
|
||||
; eax = value
|
||||
; esi - string
|
||||
; ecx = string length
|
||||
; edx - MapEntry
|
||||
mov ecx,[ebx+Map.hash_mask]
|
||||
inc ecx
|
||||
add ebx,sizeof.Map
|
||||
iterate_through_hash_table:
|
||||
mov edx,[ebx]
|
||||
iterate_through_bucket:
|
||||
test edx,edx
|
||||
jz end_of_bucket
|
||||
push ebx ecx edx edi
|
||||
mov eax,[edx+MapEntry.value]
|
||||
mov esi,[edx+MapEntry.name]
|
||||
mov ecx,[edx+MapEntry.name_length]
|
||||
call edi
|
||||
pop edi edx ecx ebx
|
||||
mov edx,[edx+MapEntry.next_entry]
|
||||
jmp iterate_through_bucket
|
||||
end_of_bucket:
|
||||
add ebx,4
|
||||
loop iterate_through_hash_table
|
||||
retn
|
||||
|
||||
hash_string:
|
||||
; in: esi - string, ecx = string length, zero for ASCIIZ string
|
||||
; out: ecx = string length, edx = 32-bit hash
|
||||
; preserves: ebx, esi, edi
|
||||
mov edx,FNV_OFFSET
|
||||
jecxz hash_asciiz
|
||||
mov eax,ecx
|
||||
hash_known_length:
|
||||
xor dl,[esi]
|
||||
inc esi
|
||||
imul edx,FNV_PRIME
|
||||
loop hash_known_length
|
||||
mov ecx,eax
|
||||
sub esi,ecx
|
||||
retn
|
||||
hash_asciiz:
|
||||
inc ecx
|
||||
lodsb
|
||||
xor dl,al
|
||||
imul edx,FNV_PRIME
|
||||
test al,al
|
||||
jnz hash_asciiz
|
||||
hash_ready:
|
||||
sub esi,ecx
|
||||
retn
|
52
toolchain/fasmg.kl0e/source/messages.inc
Normal file
52
toolchain/fasmg.kl0e/source/messages.inc
Normal file
@ -0,0 +1,52 @@
|
||||
|
||||
_macro_source db 'macro ',0
|
||||
_preprocessed_source db 'assemble ',0
|
||||
_unnamed_source db '?',0
|
||||
_memory_source db 'eval',0
|
||||
_space db ' ',0
|
||||
_line_number_prefix db ' [',0
|
||||
_line_number_suffix db ']',0
|
||||
_line_content_prefix db ':'
|
||||
_line_segment_prefix db LINE_FEED,9,0
|
||||
_calm_source db ' (CALM)',0
|
||||
_single_quote db 27h,0
|
||||
_preprocessed_text_prefix db 'Processed: ',0
|
||||
_error_prefix db 'Error: ',0
|
||||
_custom_error_prefix db 'Custom error: ',0
|
||||
_message_suffix db '.'
|
||||
_new_line db LINE_FEED,0
|
||||
|
||||
_source_file_not_found db "source file '%s' not found",0
|
||||
_error_reading_file db "error reading file '%s'",0
|
||||
_missing_end_quote db "missing end quote",0
|
||||
_illegal_instruction db "illegal instruction",0
|
||||
_invalid_argument db "invalid argument",0
|
||||
_missing_argument db "missing argument",0
|
||||
_extra_characters_on_line db "extra characters on line",0
|
||||
_invalid_identifier db "invalid identifier",0
|
||||
_invalid_number db "invalid number",0
|
||||
_undefined_symbol db "symbol '%i' is undefined or out of scope",0
|
||||
_invalid_symbol_value db "the value of symbol '%i' is not valid for this use",0
|
||||
_conflicting_definition db "definition of '%i' in conflict with already defined symbol",0
|
||||
_cannot_apply_to_constant db "cannot apply this operation to constant",0
|
||||
_symbolic_self_reference db "detected a circular reference of symbolic values",0
|
||||
_unexpected_instruction db "unexpected instruction",0
|
||||
_missing_end_directive db "missing end directive",0
|
||||
_missing_closing_chevron db "missing closing chevron",0
|
||||
_invalid_value db "value of type not allowed in this context",0
|
||||
_invalid_expression db "invalid expression",0
|
||||
_missing_closing_parenthesis db "missing closing parenthesis",0
|
||||
_excess_closing_parenthesis db "excess closing parenthesis",0
|
||||
_value_out_of_range db "value out of allowed range",0
|
||||
_indeterminate_result db "expression has indeterminate, infinite, or infinitesimal result",0
|
||||
_misused_variable_term db "variable term used where not expected",0
|
||||
_nonlinear_polynomial db "cannot multiply variable terms",0
|
||||
_subdivided_variable_term db "cannot subdivide variable term",0
|
||||
_values_not_comparable db "values not comparable",0
|
||||
_assertion_failed db "assertion failed",0
|
||||
_area_overflow db "exceeded the maximum allowed length of output area",0
|
||||
_address_out_of_range db "address out of range",0
|
||||
_invalid_area db "invalid or inaccessible addressing area",0
|
||||
_stack_limit_exceeded db "exceeded the maximum allowed depth of the stack",0
|
||||
_repeated_declaration db "choice has already been declared",0
|
||||
_undefined_jump_target db "the target of the jump is not defined in this instruction",0
|
883
toolchain/fasmg.kl0e/source/output.inc
Normal file
883
toolchain/fasmg.kl0e/source/output.inc
Normal file
@ -0,0 +1,883 @@
|
||||
|
||||
struct OutputArea
|
||||
cached_offset dq ?
|
||||
definition dd ? ; pointer to ValueDefinition
|
||||
ends
|
||||
|
||||
struct AreaHeader
|
||||
flags dd ? ; AREA_#
|
||||
base_address_length dd ?
|
||||
uninitialized_length dd ?
|
||||
ends
|
||||
|
||||
AREA_VIRTUAL = 1
|
||||
AREA_VARIABLE = 2
|
||||
AREA_SHIFT_TRACKING_DISABLED = 4
|
||||
|
||||
create_output_area:
|
||||
; in:
|
||||
; esi - base address in format of VALTYPE_NUMERIC value
|
||||
; ecx = length of base address value
|
||||
; out:
|
||||
; ebx - AreaHeader
|
||||
; edx - ValueDefinition
|
||||
mov eax,[current_output_area_entry]
|
||||
test eax,eax
|
||||
jz create_first_output_area
|
||||
push ecx
|
||||
lea ecx,[eax+sizeof.OutputArea*2]
|
||||
cmp ecx,[output_areas_list_end]
|
||||
jbe get_next_output_entry
|
||||
mov eax,[output_areas_list]
|
||||
sub ecx,eax
|
||||
sub [current_output_area_entry],eax
|
||||
sub [initial_output_area_entry],eax
|
||||
sub [output_areas_list_end],eax
|
||||
call grow_stack
|
||||
mov [output_areas_list],eax
|
||||
add [current_output_area_entry],eax
|
||||
add [initial_output_area_entry],eax
|
||||
add eax,ecx
|
||||
mov edi,eax
|
||||
xchg [output_areas_list_end],eax
|
||||
sub ecx,eax
|
||||
sub edi,ecx
|
||||
shr ecx,2
|
||||
xor eax,eax
|
||||
rep stosd
|
||||
mov eax,[current_output_area_entry]
|
||||
get_next_output_entry:
|
||||
add eax,sizeof.OutputArea
|
||||
cmp [initial_output_area_entry],0
|
||||
je another_initial_output_area
|
||||
mov edi,[eax-sizeof.OutputArea+OutputArea.definition]
|
||||
mov ecx,[edi+ValueDefinition.value_length]
|
||||
mov edi,[edi+ValueDefinition.value]
|
||||
mov ebx,[edi+AreaHeader.uninitialized_length]
|
||||
sub ecx,sizeof.AreaHeader
|
||||
sub ecx,[edi+AreaHeader.base_address_length]
|
||||
jz prior_uninitialized_length_ok
|
||||
and dword [prior_uninitialized_length],0
|
||||
and dword [prior_uninitialized_length+4],0
|
||||
prior_uninitialized_length_ok:
|
||||
add dword [prior_uninitialized_length],ebx
|
||||
adc dword [prior_uninitialized_length+4],0
|
||||
xor edx,edx
|
||||
add ecx,ebx
|
||||
adc edx,0
|
||||
add ecx,dword [eax-sizeof.OutputArea+OutputArea.cached_offset]
|
||||
adc edx,dword [eax-sizeof.OutputArea+OutputArea.cached_offset+4]
|
||||
mov dword [eax+OutputArea.cached_offset],ecx
|
||||
mov dword [eax+OutputArea.cached_offset+4],edx
|
||||
pop ecx
|
||||
jmp new_output_entry_ready
|
||||
another_initial_output_area:
|
||||
pop ecx
|
||||
jmp create_initial_output_area
|
||||
create_first_output_area:
|
||||
mov eax,[output_areas_list]
|
||||
create_initial_output_area:
|
||||
mov [initial_output_area_entry],eax
|
||||
and dword [eax+OutputArea.cached_offset],0
|
||||
and dword [eax+OutputArea.cached_offset+4],0
|
||||
and dword [prior_uninitialized_length],0
|
||||
and dword [prior_uninitialized_length+4],0
|
||||
new_output_entry_ready:
|
||||
mov [current_output_area_entry],eax
|
||||
lea ebx,[eax+OutputArea.definition]
|
||||
call create_area
|
||||
retn
|
||||
|
||||
create_area:
|
||||
; in:
|
||||
; ebx - where pointer to ValueDefinition should be stored, may already hold a previously used one (should contain null otherwise)
|
||||
; esi - base address in format of VALTYPE_NUMERIC value
|
||||
; ecx = length of base address value
|
||||
; out:
|
||||
; ebx - AreaHeader
|
||||
; edx - ValueDefinition
|
||||
mov [address_length],ecx
|
||||
mov edx,[ebx]
|
||||
test edx,edx
|
||||
jz current_area_definition_unusable
|
||||
cmp [edx+ValueDefinition.reference_count],1
|
||||
je area_definition_ready
|
||||
dec [edx+ValueDefinition.reference_count]
|
||||
current_area_definition_unusable:
|
||||
mov ecx,retired_definition
|
||||
retrieve_retired_detached_value:
|
||||
mov edx,[ecx]
|
||||
test edx,edx
|
||||
jz create_area_definition
|
||||
cmp [edx+ValueDefinition.reference_count],0
|
||||
jne retired_detached_value_immutable
|
||||
xor eax,eax
|
||||
xchg eax,[edx+ValueDefinition.previous]
|
||||
mov [ecx],eax
|
||||
jmp adopt_area_definition
|
||||
retired_detached_value_immutable:
|
||||
lea ecx,[edx+ValueDefinition.previous]
|
||||
jmp retrieve_retired_detached_value
|
||||
create_area_definition:
|
||||
mov ecx,sizeof.ValueDefinition
|
||||
call create_tree_element
|
||||
mov ecx,eax
|
||||
xchg ecx,[value_definition_chain]
|
||||
mov [eax+ValueDefinition.interlink],ecx
|
||||
mov edx,eax
|
||||
adopt_area_definition:
|
||||
mov [ebx],edx
|
||||
or [edx+ValueDefinition.flags],VAL_DETACHED
|
||||
inc [edx+ValueDefinition.reference_count]
|
||||
area_definition_ready:
|
||||
mov ecx,[address_length]
|
||||
add ecx,sizeof.AreaHeader
|
||||
mov eax,[edx+ValueDefinition.block_length]
|
||||
test eax,eax
|
||||
jz allocate_area_block
|
||||
cmp ecx,eax
|
||||
jbe initialize_area_block
|
||||
push ecx edx
|
||||
xor eax,eax
|
||||
xchg eax,[edx+ValueDefinition.value]
|
||||
call mfree
|
||||
pop edx ecx
|
||||
allocate_area_block:
|
||||
push edx
|
||||
call malloc_growable
|
||||
pop edx
|
||||
mov [edx+ValueDefinition.value],eax
|
||||
mov [edx+ValueDefinition.block_length],ecx
|
||||
initialize_area_block:
|
||||
mov ebx,[edx+ValueDefinition.value]
|
||||
lea edi,[ebx+sizeof.AreaHeader]
|
||||
mov ecx,[address_length]
|
||||
mov [ebx+AreaHeader.base_address_length],ecx
|
||||
rep movsb
|
||||
mov [ebx+AreaHeader.uninitialized_length],ecx
|
||||
mov [ebx+AreaHeader.flags],ecx
|
||||
sub edi,ebx
|
||||
mov [edx+ValueDefinition.value_length],edi
|
||||
mov [edx+ValueDefinition.type],VALTYPE_AREA
|
||||
mov ecx,[current_pass]
|
||||
mov [edx+ValueDefinition.pass],ecx
|
||||
retn
|
||||
|
||||
initialize_output:
|
||||
; in: ecx = number of bytes that should be added to output
|
||||
; out: edi - output buffer to be filled with data
|
||||
; preserves: esi
|
||||
mov edx,[current_area]
|
||||
mov ebx,[edx+ValueDefinition.value]
|
||||
add ecx,[ebx+AreaHeader.uninitialized_length]
|
||||
jc output_out_of_memory
|
||||
mov eax,[edx+ValueDefinition.value_length]
|
||||
lea edi,[ebx+eax]
|
||||
add ecx,eax
|
||||
jc output_out_of_memory
|
||||
mov [edx+ValueDefinition.value_length],ecx
|
||||
cmp ecx,[edx+ValueDefinition.block_length]
|
||||
jbe area_reserve_sufficient
|
||||
mov eax,[edx+ValueDefinition.value]
|
||||
sub edi,eax
|
||||
push edx
|
||||
push ecx
|
||||
bsr edx,ecx
|
||||
xchg ecx,edx
|
||||
dec cl
|
||||
shr edx,cl
|
||||
inc edx
|
||||
shl edx,cl
|
||||
pop ecx
|
||||
cmp edx,ecx
|
||||
jbe output_out_of_memory
|
||||
xchg ecx,edx
|
||||
call realloc
|
||||
pop edx
|
||||
mov ebx,eax
|
||||
add edi,eax
|
||||
mov [edx+ValueDefinition.value],ebx
|
||||
mov [edx+ValueDefinition.block_length],ecx
|
||||
area_reserve_sufficient:
|
||||
mov ecx,[ebx+AreaHeader.uninitialized_length]
|
||||
jecxz output_buffer_ready
|
||||
xor eax,eax
|
||||
rep stosb
|
||||
mov [ebx+AreaHeader.uninitialized_length],eax
|
||||
output_buffer_ready:
|
||||
retn
|
||||
output_out_of_memory:
|
||||
jmp out_of_memory
|
||||
|
||||
uninitialized_output:
|
||||
; in: ecx = number of uninitialized bytes to be added to output
|
||||
; preserves: ebx, ecx, esi, edi
|
||||
mov edx,[current_area]
|
||||
mov eax,[edx+ValueDefinition.value]
|
||||
add [eax+AreaHeader.uninitialized_length],ecx
|
||||
jc area_overflow
|
||||
mov edx,[edx+ValueDefinition.value_length]
|
||||
sub edx,sizeof.AreaHeader
|
||||
sub edx,[eax+AreaHeader.base_address_length]
|
||||
add edx,[eax+AreaHeader.uninitialized_length]
|
||||
jc area_overflow
|
||||
retn
|
||||
area_overflow:
|
||||
mov edx,_area_overflow
|
||||
call register_error
|
||||
mov edx,[current_area]
|
||||
or ecx,-1
|
||||
mov eax,[edx+ValueDefinition.value]
|
||||
sub ecx,[edx+ValueDefinition.value_length]
|
||||
add ecx,sizeof.AreaHeader
|
||||
add ecx,[eax+AreaHeader.base_address_length]
|
||||
mov [eax+AreaHeader.uninitialized_length],ecx
|
||||
retn
|
||||
|
||||
trim_output:
|
||||
; preserves: ecx, esi
|
||||
xor eax,eax
|
||||
mov dword [prior_uninitialized_length],eax
|
||||
mov dword [prior_uninitialized_length+4],eax
|
||||
mov edi,[current_output_area_entry]
|
||||
trim_current_output_area:
|
||||
mov edx,[edi+OutputArea.definition]
|
||||
mov eax,[edx+ValueDefinition.value]
|
||||
and [eax+AreaHeader.uninitialized_length],0
|
||||
mov ebx,[edx+ValueDefinition.value_length]
|
||||
sub ebx,sizeof.AreaHeader
|
||||
sub ebx,[eax+AreaHeader.base_address_length]
|
||||
jnz output_trimmed
|
||||
cmp edi,[initial_output_area_entry]
|
||||
je output_trimmed
|
||||
sub edi,sizeof.OutputArea
|
||||
jmp trim_current_output_area
|
||||
output_trimmed:
|
||||
mov [current_output_area_entry],edi
|
||||
retn
|
||||
|
||||
load_from_area:
|
||||
; in:
|
||||
; [value_length] = length of data to load
|
||||
; edi - buffer for loaded data
|
||||
; edx - ValueDefinition with VALTYPE_AREA
|
||||
; [data_area_symbol] - SymbolTree_Leaf linked to the same ValueDefinition with update_value_link (required only for predicted loads, can be null)
|
||||
; [data_offset] = offset within the area
|
||||
; out:
|
||||
; cf set when data could not be loaded
|
||||
; when cf = 0, buffer filled with loaded data
|
||||
; preserves: esi
|
||||
mov eax,[edx+ValueDefinition.value]
|
||||
mov ecx,[edx+ValueDefinition.pass]
|
||||
cmp ecx,[current_pass]
|
||||
je area_ok
|
||||
test [eax+AreaHeader.flags],AREA_VARIABLE
|
||||
jnz source_area_inaccessible
|
||||
area_ok:
|
||||
mov ebx,[data_offset]
|
||||
add ebx,[eax+AreaHeader.base_address_length]
|
||||
jc area_offset_unavailable
|
||||
add ebx,sizeof.AreaHeader
|
||||
jc area_offset_unavailable
|
||||
mov ecx,[edx+ValueDefinition.value_length]
|
||||
sub ecx,ebx
|
||||
jb load_out_of_initialized_data
|
||||
call prepare_load_length
|
||||
jc area_offset_unavailable
|
||||
xchg esi,ebx
|
||||
add esi,eax
|
||||
rep movsb
|
||||
mov esi,ebx
|
||||
cmp [value_length],0
|
||||
je load_ok
|
||||
mov ecx,[eax+AreaHeader.uninitialized_length]
|
||||
jmp load_uninitialized_data
|
||||
load_out_of_initialized_data:
|
||||
add ecx,[eax+AreaHeader.uninitialized_length]
|
||||
jc load_uninitialized_data
|
||||
xor ecx,ecx
|
||||
load_uninitialized_data:
|
||||
call prepare_load_length
|
||||
jc area_offset_unavailable
|
||||
xor al,al
|
||||
rep stosb
|
||||
cmp [value_length],0
|
||||
je load_ok
|
||||
xor ebx,ebx
|
||||
xchg ebx,[data_area_symbol]
|
||||
test ebx,ebx
|
||||
jz area_offset_unavailable
|
||||
mov edx,[ebx+SymbolTree_Leaf.retired_definition]
|
||||
test edx,edx
|
||||
jz area_with_no_history
|
||||
mov ecx,[current_pass]
|
||||
sub ecx,[edx+ValueDefinition.pass]
|
||||
cmp ecx,1
|
||||
ja area_with_no_history
|
||||
or [ebx+SymbolTree_Leaf.flags],SYM_LINK_PREDICTED
|
||||
mov eax,[edx+ValueDefinition.value]
|
||||
jmp load_from_area
|
||||
prepare_load_length:
|
||||
cmp ecx,[value_length]
|
||||
jbe value_length_ok
|
||||
mov ecx,[value_length]
|
||||
value_length_ok:
|
||||
add [data_offset],ecx
|
||||
jc load_length_ready
|
||||
sub [value_length],ecx
|
||||
load_length_ready:
|
||||
retn
|
||||
source_area_inaccessible:
|
||||
mov edx,_invalid_area
|
||||
jmp load_failed
|
||||
area_with_no_history:
|
||||
or [next_pass_needed],1
|
||||
area_offset_unavailable:
|
||||
mov edx,_address_out_of_range
|
||||
load_failed:
|
||||
call register_error
|
||||
stc
|
||||
retn
|
||||
load_ok:
|
||||
clc
|
||||
retn
|
||||
|
||||
prepare_area_to_write:
|
||||
; in:
|
||||
; [data_area] - ValueDefinition with VALTYPE_AREA
|
||||
; [data_offset] = offset within the area
|
||||
; [value_length] = length of data to be written
|
||||
; out:
|
||||
; cf set when writing specified length is not possible
|
||||
; when cf = 0:
|
||||
; edi - buffer for specified number of bytes directly within the area
|
||||
; preserves: esi
|
||||
mov edx,[data_area]
|
||||
mov eax,[edx+ValueDefinition.value]
|
||||
or [eax+AreaHeader.flags],AREA_VARIABLE
|
||||
mov ebx,[data_offset]
|
||||
xor ecx,ecx
|
||||
add ebx,[eax+AreaHeader.base_address_length]
|
||||
adc ecx,0
|
||||
add ebx,sizeof.AreaHeader
|
||||
adc ecx,0
|
||||
add ebx,[value_length]
|
||||
adc ecx,0
|
||||
jnz write_outside_initialized_area
|
||||
cmp ebx,[edx+ValueDefinition.value_length]
|
||||
ja write_outside_initialized_area
|
||||
lea edi,[eax+ebx]
|
||||
mov ecx,[value_length]
|
||||
sub edi,ecx
|
||||
retn
|
||||
area_to_write_not_accessible:
|
||||
stc
|
||||
retn
|
||||
write_outside_initialized_area:
|
||||
sub ebx,[edx+ValueDefinition.value_length]
|
||||
sbb ecx,0
|
||||
jnz write_outside_boundaries
|
||||
sub [eax+AreaHeader.uninitialized_length],ebx
|
||||
jnc extend_area
|
||||
add [eax+AreaHeader.uninitialized_length],ebx
|
||||
write_outside_boundaries:
|
||||
push edx
|
||||
mov edx,_address_out_of_range
|
||||
call register_error
|
||||
pop edx
|
||||
test ecx,ecx
|
||||
jnz area_to_write_not_accessible
|
||||
test [eax+AreaHeader.flags],AREA_VIRTUAL
|
||||
jz area_to_write_not_accessible
|
||||
test [edx+ValueDefinition.flags],VAL_IN_USE
|
||||
jnz area_to_write_not_accessible
|
||||
and [eax+AreaHeader.uninitialized_length],0
|
||||
extend_virtual_area:
|
||||
call expand_value
|
||||
jmp prepare_area_to_write
|
||||
extend_area:
|
||||
test [eax+AreaHeader.flags],AREA_VIRTUAL
|
||||
jnz extend_virtual_area
|
||||
call expand_value
|
||||
call update_output_offsets
|
||||
jmp prepare_area_to_write
|
||||
|
||||
find_output_area:
|
||||
; in:
|
||||
; [file_offset] = offset within the output
|
||||
; out:
|
||||
; cf set when not found an area that would contain a byte at specified offset
|
||||
; when cf = 0:
|
||||
; ebx - OutputArea
|
||||
; [file_offset] = offset relative to the beginning of the found area (upper 32 bits are zero)
|
||||
mov esi,[initial_output_area_entry]
|
||||
mov edi,[current_output_area_entry]
|
||||
add edi,sizeof.OutputArea
|
||||
search_areas:
|
||||
mov ebx,edi
|
||||
sub ebx,esi
|
||||
jz output_area_not_found
|
||||
test ebx,1 shl bsf sizeof.OutputArea
|
||||
jz bisect_areas_list
|
||||
sub ebx,sizeof.OutputArea
|
||||
bisect_areas_list:
|
||||
shr ebx,1
|
||||
add ebx,esi
|
||||
mov eax,dword [file_offset]
|
||||
mov edx,dword [file_offset+4]
|
||||
sub eax,dword [ebx+OutputArea.cached_offset]
|
||||
sbb edx,dword [ebx+OutputArea.cached_offset+4]
|
||||
jc search_earlier_areas
|
||||
jnz search_later_areas
|
||||
mov edx,[ebx+OutputArea.definition]
|
||||
mov ecx,[edx+ValueDefinition.value_length]
|
||||
mov edx,[edx+ValueDefinition.value]
|
||||
sub ecx,sizeof.AreaHeader
|
||||
sub ecx,[edx+AreaHeader.base_address_length]
|
||||
add ecx,[edx+AreaHeader.uninitialized_length]
|
||||
cmp eax,ecx
|
||||
jae search_later_areas
|
||||
output_area_found:
|
||||
mov dword [file_offset],eax
|
||||
and dword [file_offset+4],0
|
||||
; clc
|
||||
retn
|
||||
output_area_not_found:
|
||||
stc
|
||||
retn
|
||||
search_later_areas:
|
||||
lea esi,[ebx+sizeof.OutputArea]
|
||||
jmp search_areas
|
||||
search_earlier_areas:
|
||||
mov edi,ebx
|
||||
jmp search_areas
|
||||
|
||||
read_from_output:
|
||||
; in:
|
||||
; edi - buffer for read data
|
||||
; [value_length] = length of data to read
|
||||
; [file_offset] = offset within the output
|
||||
; out:
|
||||
; [value_length] = number of bytes that were not in the existing output and could not be read
|
||||
push edi
|
||||
call find_output_area
|
||||
pop edi
|
||||
jc output_reading_done
|
||||
read_output_areas:
|
||||
cmp [value_length],0
|
||||
je output_reading_done
|
||||
mov edx,[ebx+OutputArea.definition]
|
||||
mov ecx,[edx+ValueDefinition.value_length]
|
||||
mov eax,ecx
|
||||
mov edx,[edx+ValueDefinition.value]
|
||||
sub ecx,sizeof.AreaHeader
|
||||
sub ecx,[edx+AreaHeader.base_address_length]
|
||||
sub dword [file_offset],ecx
|
||||
jnc initialized_load_done
|
||||
lea esi,[edx+eax]
|
||||
mov ecx,dword [file_offset]
|
||||
add esi,ecx
|
||||
neg ecx
|
||||
cmp ecx,[value_length]
|
||||
jbe initialized_load_length_ok
|
||||
mov ecx,[value_length]
|
||||
initialized_load_length_ok:
|
||||
sub [value_length],ecx
|
||||
rep movsb
|
||||
mov dword [file_offset],ecx
|
||||
initialized_load_done:
|
||||
mov ecx,[edx+AreaHeader.uninitialized_length]
|
||||
sub dword [file_offset],ecx
|
||||
jnc uninitialized_load_done
|
||||
mov ecx,dword [file_offset]
|
||||
neg ecx
|
||||
cmp ecx,[value_length]
|
||||
jbe uninitialized_load_length_ok
|
||||
mov ecx,[value_length]
|
||||
uninitialized_load_length_ok:
|
||||
sub [value_length],ecx
|
||||
xor al,al
|
||||
rep stosb
|
||||
mov dword [file_offset],ecx
|
||||
uninitialized_load_done:
|
||||
cmp ebx,[current_output_area_entry]
|
||||
je output_reading_done
|
||||
add ebx,sizeof.OutputArea
|
||||
jmp read_output_areas
|
||||
output_reading_done:
|
||||
retn
|
||||
|
||||
rewrite_output:
|
||||
; in:
|
||||
; esi - data to write
|
||||
; [value_length] = length of data to write
|
||||
; [file_offset] = offset within the output
|
||||
; out:
|
||||
; [value_length] = number of bytes that were not in the existing output and could not be rewritten
|
||||
push esi
|
||||
call find_output_area
|
||||
pop esi
|
||||
jc output_rewriting_done
|
||||
rewrite_output_areas:
|
||||
cmp [value_length],0
|
||||
je output_rewriting_done
|
||||
mov edx,[ebx+OutputArea.definition]
|
||||
mov ecx,[edx+ValueDefinition.value_length]
|
||||
mov edx,[edx+ValueDefinition.value]
|
||||
sub ecx,sizeof.AreaHeader
|
||||
sub ecx,[edx+AreaHeader.base_address_length]
|
||||
mov edi,[edx+AreaHeader.uninitialized_length]
|
||||
add ecx,edi
|
||||
sub dword [file_offset],ecx
|
||||
jnc rewrite_next_area
|
||||
mov eax,[value_length]
|
||||
xor ecx,ecx
|
||||
add eax,edi
|
||||
adc ecx,ecx
|
||||
add eax,dword [file_offset]
|
||||
adc ecx,0
|
||||
jz rewrite_initialized_data
|
||||
cmp eax,edi
|
||||
jbe rewrite_uninitialized_data
|
||||
mov eax,edi
|
||||
rewrite_uninitialized_data:
|
||||
test eax,eax
|
||||
jz rewrite_initialized_data
|
||||
push ebx
|
||||
sub [edx+AreaHeader.uninitialized_length],eax
|
||||
mov edx,[ebx+OutputArea.definition]
|
||||
mov ebx,eax
|
||||
call expand_value
|
||||
call update_output_offsets
|
||||
pop ebx
|
||||
rewrite_initialized_data:
|
||||
mov edx,[ebx+OutputArea.definition]
|
||||
mov ecx,[edx+ValueDefinition.value_length]
|
||||
mov edi,[edx+ValueDefinition.value]
|
||||
or [edi+AreaHeader.flags],AREA_VARIABLE
|
||||
add edi,[edi+AreaHeader.uninitialized_length]
|
||||
add edi,ecx
|
||||
mov ecx,dword [file_offset]
|
||||
add edi,ecx
|
||||
neg ecx
|
||||
cmp ecx,[value_length]
|
||||
jbe rewrite_length_ok
|
||||
mov ecx,[value_length]
|
||||
rewrite_length_ok:
|
||||
sub [value_length],ecx
|
||||
rep movsb
|
||||
mov dword [file_offset],ecx
|
||||
rewrite_next_area:
|
||||
cmp ebx,[current_output_area_entry]
|
||||
je output_rewriting_done
|
||||
add ebx,sizeof.OutputArea
|
||||
jmp rewrite_output_areas
|
||||
output_rewriting_done:
|
||||
retn
|
||||
|
||||
update_output_offsets:
|
||||
; in:
|
||||
; edx - ValueDefinition of output area that had some of uninitialized data made initialized
|
||||
; preserves: esi
|
||||
mov eax,[current_output_area_entry]
|
||||
cmp edx,[eax+OutputArea.definition]
|
||||
je output_offsets_ok
|
||||
and dword [prior_uninitialized_length],0
|
||||
and dword [prior_uninitialized_length+4],0
|
||||
recount_prior_uninitialized_length:
|
||||
cmp eax,[initial_output_area_entry]
|
||||
je output_offsets_ok
|
||||
sub eax,sizeof.OutputArea
|
||||
mov edi,[eax+OutputArea.definition]
|
||||
mov ebx,[edi+ValueDefinition.value]
|
||||
mov ecx,[ebx+AreaHeader.uninitialized_length]
|
||||
add dword [prior_uninitialized_length],ecx
|
||||
adc dword [prior_uninitialized_length+4],0
|
||||
cmp edx,edi
|
||||
je output_offsets_ok
|
||||
mov ecx,[edi+ValueDefinition.value_length]
|
||||
sub ecx,sizeof.AreaHeader
|
||||
sub ecx,[ebx+AreaHeader.base_address_length]
|
||||
jz recount_prior_uninitialized_length
|
||||
output_offsets_ok:
|
||||
retn
|
||||
|
||||
get_current_address_value:
|
||||
; out:
|
||||
; esi - address in format of VALTYPE_NUMERIC value
|
||||
; ecx = length of address value
|
||||
; note: the returned value is placed in assembly workspace
|
||||
mov eax,[current_area]
|
||||
mov esi,[eax+ValueDefinition.value]
|
||||
mov ebx,[eax+ValueDefinition.value_length]
|
||||
mov edx,assembly_workspace
|
||||
mov edi,[edx+Workspace.memory_start]
|
||||
mov ecx,[esi+AreaHeader.base_address_length]
|
||||
add ecx,4
|
||||
call reserve_workspace
|
||||
mov ecx,[esi+AreaHeader.base_address_length]
|
||||
sub ebx,ecx
|
||||
sub ebx,sizeof.AreaHeader
|
||||
add ebx,[esi+AreaHeader.uninitialized_length]
|
||||
; jc internal_error
|
||||
add esi,sizeof.AreaHeader
|
||||
xor eax,eax
|
||||
stosd
|
||||
lodsd
|
||||
mov ecx,eax
|
||||
xor edx,edx
|
||||
jecxz offset_added_to_base_address
|
||||
add_offset_to_base_address:
|
||||
lodsb
|
||||
add al,bl
|
||||
setc dl
|
||||
stosb
|
||||
shr ebx,8
|
||||
add ebx,edx
|
||||
loop add_offset_to_base_address
|
||||
offset_added_to_base_address:
|
||||
mov edx,[assembly_workspace.memory_start]
|
||||
add edx,4
|
||||
mov eax,ebx
|
||||
cmp byte [esi-1],80h
|
||||
cmc
|
||||
sbb eax,0
|
||||
stosd
|
||||
optimize_base_address:
|
||||
movsx eax,byte [edi-2]
|
||||
cmp ah,[edi-1]
|
||||
jne base_address_ready
|
||||
dec edi
|
||||
cmp edi,edx
|
||||
jne optimize_base_address
|
||||
base_address_ready:
|
||||
mov ecx,edi
|
||||
sub ecx,edx
|
||||
mov [edx-4],ecx
|
||||
mov ecx,esi
|
||||
measure_variable_terms:
|
||||
lodsd
|
||||
test eax,eax
|
||||
jz variable_terms_measured
|
||||
lodsd
|
||||
add esi,eax
|
||||
jmp measure_variable_terms
|
||||
variable_terms_measured:
|
||||
xchg ecx,esi
|
||||
sub ecx,esi
|
||||
rep movsb
|
||||
mov esi,[assembly_workspace.memory_start]
|
||||
mov ecx,edi
|
||||
sub ecx,esi
|
||||
retn
|
||||
|
||||
get_output_length:
|
||||
; out:
|
||||
; edx:eax = length of current output (not counting uninitialized data)
|
||||
; preserves: esi
|
||||
mov ebx,[current_output_area_entry]
|
||||
mov eax,dword [ebx+OutputArea.cached_offset]
|
||||
mov edx,dword [ebx+OutputArea.cached_offset+4]
|
||||
mov edi,[ebx+OutputArea.definition]
|
||||
mov ecx,[edi+ValueDefinition.value_length]
|
||||
mov edi,[edi+ValueDefinition.value]
|
||||
sub ecx,sizeof.AreaHeader
|
||||
sub ecx,[edi+AreaHeader.base_address_length]
|
||||
jz current_area_entirely_uninitialized
|
||||
add eax,ecx
|
||||
adc edx,0
|
||||
retn
|
||||
current_area_entirely_uninitialized:
|
||||
sub eax,dword [prior_uninitialized_length]
|
||||
sbb edx,dword [prior_uninitialized_length+4]
|
||||
retn
|
||||
|
||||
get_output_position:
|
||||
; out:
|
||||
; edx:eax = current position in the output (including uninitialized data)
|
||||
; preserves: esi
|
||||
mov ebx,[current_output_area_entry]
|
||||
mov eax,dword [ebx+OutputArea.cached_offset]
|
||||
mov edx,dword [ebx+OutputArea.cached_offset+4]
|
||||
mov edi,[ebx+OutputArea.definition]
|
||||
mov ecx,[edi+ValueDefinition.value_length]
|
||||
mov edi,[edi+ValueDefinition.value]
|
||||
sub ecx,sizeof.AreaHeader
|
||||
sub ecx,[edi+AreaHeader.base_address_length]
|
||||
add ecx,[edi+AreaHeader.uninitialized_length]
|
||||
add eax,ecx
|
||||
adc edx,0
|
||||
retn
|
||||
|
||||
create_output_path:
|
||||
; in:
|
||||
; ebx - base path and name
|
||||
; esi - file extension
|
||||
; ecx = length of the extension
|
||||
; out:
|
||||
; edx - output path (generated in temporary storage)
|
||||
push ecx
|
||||
mov edi,ebx
|
||||
xor al,al
|
||||
or ecx,-1
|
||||
repne scasb
|
||||
dec edi
|
||||
mov ecx,edi
|
||||
locate_extension:
|
||||
cmp edi,ebx
|
||||
je copy_path_name
|
||||
dec edi
|
||||
mov al,[edi]
|
||||
cmp al,'\'
|
||||
je copy_path_name
|
||||
cmp al,'/'
|
||||
je copy_path_name
|
||||
cmp al,'.'
|
||||
jne locate_extension
|
||||
mov ecx,edi
|
||||
copy_path_name:
|
||||
sub ecx,ebx
|
||||
push ecx
|
||||
mov edi,[preprocessing_workspace.memory_start]
|
||||
inc ecx
|
||||
mov edx,preprocessing_workspace
|
||||
call reserve_workspace
|
||||
pop ecx
|
||||
xchg esi,ebx
|
||||
rep movsb
|
||||
mov esi,ebx
|
||||
pop ecx
|
||||
mov ebx,ecx
|
||||
add ecx,2
|
||||
call reserve_workspace
|
||||
mov ecx,ebx
|
||||
jecxz extension_attached
|
||||
mov al,'.'
|
||||
stosb
|
||||
rep movsb
|
||||
extension_attached:
|
||||
xor al,al
|
||||
stosb
|
||||
mov edx,[preprocessing_workspace.memory_start]
|
||||
retn
|
||||
|
||||
write_output_file:
|
||||
; in:
|
||||
; ebx - source path
|
||||
; edi - output path
|
||||
; out:
|
||||
; cf set when write failed
|
||||
; note:
|
||||
; when output path is null, source path is used with replaced or attached extension
|
||||
mov [base_path],edi
|
||||
xor eax,eax
|
||||
mov [output_failures],eax
|
||||
mov dword [uninitialized_length],eax
|
||||
mov dword [uninitialized_length+4],eax
|
||||
mov edx,edi
|
||||
test edx,edx
|
||||
jnz create_output_file
|
||||
mov [base_path],ebx
|
||||
mov esi,[output_extension]
|
||||
mov ecx,[output_extension_length]
|
||||
call create_output_path
|
||||
create_output_file:
|
||||
call create
|
||||
jc output_write_failed
|
||||
mov esi,[initial_output_area_entry]
|
||||
write_area:
|
||||
mov edx,[esi+OutputArea.definition]
|
||||
mov eax,[edx+ValueDefinition.value]
|
||||
mov ecx,[edx+ValueDefinition.value_length]
|
||||
sub ecx,[eax+AreaHeader.base_address_length]
|
||||
sub ecx,sizeof.AreaHeader
|
||||
jz write_next_area
|
||||
mov eax,dword [uninitialized_length]
|
||||
or eax,dword [uninitialized_length+4]
|
||||
jz write_initialized_data
|
||||
write_uninitialized_data:
|
||||
mov edi,[assembly_workspace.memory_start]
|
||||
mov ecx,1000h shr 2
|
||||
xor eax,eax
|
||||
rep stosd
|
||||
mov ecx,1000h
|
||||
cmp dword [uninitialized_length+4],0
|
||||
jne portion_length_ok
|
||||
cmp ecx,dword [uninitialized_length]
|
||||
jbe portion_length_ok
|
||||
mov ecx,dword [uninitialized_length]
|
||||
portion_length_ok:
|
||||
sub dword [uninitialized_length],ecx
|
||||
sbb dword [uninitialized_length+4],0
|
||||
mov edx,[assembly_workspace.memory_start]
|
||||
call write
|
||||
jc file_write_failed
|
||||
mov eax,dword [uninitialized_length]
|
||||
or eax,dword [uninitialized_length+4]
|
||||
jnz write_uninitialized_data
|
||||
write_initialized_data:
|
||||
mov edx,[esi+OutputArea.definition]
|
||||
mov eax,[edx+ValueDefinition.value]
|
||||
mov ecx,[edx+ValueDefinition.value_length]
|
||||
mov edx,[eax+AreaHeader.base_address_length]
|
||||
add edx,sizeof.AreaHeader
|
||||
sub ecx,edx
|
||||
add edx,eax
|
||||
call write
|
||||
jc file_write_failed
|
||||
write_next_area:
|
||||
mov edx,[esi+OutputArea.definition]
|
||||
mov eax,[edx+ValueDefinition.value]
|
||||
mov eax,[eax+AreaHeader.uninitialized_length]
|
||||
add dword [uninitialized_length],eax
|
||||
adc dword [uninitialized_length+4],0
|
||||
cmp esi,[current_output_area_entry]
|
||||
je close_output_file
|
||||
add esi,sizeof.OutputArea
|
||||
jmp write_area
|
||||
close_output_file:
|
||||
call close
|
||||
mov ebx,[auxiliary_output_areas]
|
||||
mov edi,write_auxiliary_output_area
|
||||
call iterate_through_map
|
||||
cmp [output_failures],0
|
||||
jne output_write_failed
|
||||
clc
|
||||
retn
|
||||
file_write_failed:
|
||||
call close
|
||||
output_write_failed:
|
||||
stc
|
||||
retn
|
||||
|
||||
write_auxiliary_output_area:
|
||||
; in:
|
||||
; eax = ValueDefinition, null for cached extension not used for auxiliary output
|
||||
; esi - file extension
|
||||
; ecx = length of the extension
|
||||
test eax,eax
|
||||
jz auxiliary_output_processed
|
||||
mov ebx,[base_path]
|
||||
test ebx,ebx
|
||||
jz auxiliary_output_processed
|
||||
push eax
|
||||
call create_output_path
|
||||
call create
|
||||
pop edx
|
||||
jc auxiliary_file_creation_failed
|
||||
mov eax,[edx+ValueDefinition.value]
|
||||
mov ecx,[edx+ValueDefinition.value_length]
|
||||
mov edx,[eax+AreaHeader.base_address_length]
|
||||
add edx,sizeof.AreaHeader
|
||||
sub ecx,edx
|
||||
add edx,eax
|
||||
call write
|
||||
jc auxiliary_file_write_failed
|
||||
call close
|
||||
auxiliary_output_processed:
|
||||
retn
|
||||
auxiliary_file_write_failed:
|
||||
call close
|
||||
auxiliary_file_creation_failed:
|
||||
inc [output_failures]
|
||||
retn
|
451
toolchain/fasmg.kl0e/source/reader.inc
Normal file
451
toolchain/fasmg.kl0e/source/reader.inc
Normal file
@ -0,0 +1,451 @@
|
||||
|
||||
; note:
|
||||
; to not interfere with code resolving, all external input must stay unchanged
|
||||
; in subsequent passes of the assembly; for this reason all data read from files is
|
||||
; permanently cached (source texts are cached in tokenized form)
|
||||
|
||||
struct FileData
|
||||
length dq ?
|
||||
cache dd ? ; pointer to FileCache
|
||||
ends
|
||||
|
||||
struct FileCache
|
||||
offset dq ?
|
||||
length dd ?
|
||||
next dd ? ; pointer to another FileCache
|
||||
ends
|
||||
|
||||
read_source:
|
||||
; in:
|
||||
; esi - source path
|
||||
; out:
|
||||
; eax - tokenized source, null when file not found
|
||||
; esi - source path in persistent storage
|
||||
mov ebx,[file_source_cache]
|
||||
xor ecx,ecx
|
||||
call get_from_map
|
||||
jc read_source_file
|
||||
cmp eax,-1
|
||||
je get_erroneous_source
|
||||
retn
|
||||
read_source_file:
|
||||
mov edx,esi
|
||||
call open
|
||||
jc source_file_not_found
|
||||
xor eax,eax
|
||||
mov edx,eax
|
||||
mov cl,2
|
||||
call lseek
|
||||
jc error_reading_file
|
||||
test edx,edx
|
||||
jnz out_of_memory
|
||||
push eax
|
||||
xor eax,eax
|
||||
mov edx,eax
|
||||
mov cl,al
|
||||
call lseek
|
||||
jc error_reading_file
|
||||
pop ecx
|
||||
inc ecx
|
||||
mov [source_text_length],ecx
|
||||
call malloc
|
||||
mov [source_text],eax
|
||||
mov edx,eax
|
||||
mov ecx,[source_text_length]
|
||||
dec ecx
|
||||
mov byte [edx+ecx],0
|
||||
call read
|
||||
jc error_reading_file
|
||||
call close
|
||||
push esi
|
||||
call tokenize_source
|
||||
mov eax,[source_text]
|
||||
call mfree
|
||||
pop esi
|
||||
mov eax,[tokenization_buffer]
|
||||
xor ecx,ecx
|
||||
mov ebx,[file_source_cache]
|
||||
call put_into_map
|
||||
mov eax,[tokenization_buffer]
|
||||
retn
|
||||
source_file_not_found:
|
||||
xor eax,eax
|
||||
xor ecx,ecx
|
||||
mov ebx,[file_source_cache]
|
||||
call put_into_map
|
||||
xor eax,eax
|
||||
retn
|
||||
error_reading_file:
|
||||
or eax,-1
|
||||
xor ecx,ecx
|
||||
mov ebx,[file_source_cache]
|
||||
call put_into_map
|
||||
get_erroneous_source:
|
||||
mov ebx,esi
|
||||
mov edx,_error_reading_file
|
||||
call register_error
|
||||
mov eax,zero_value
|
||||
retn
|
||||
|
||||
use_source:
|
||||
; in:
|
||||
; esi - ASCIIZ source string
|
||||
; out:
|
||||
; eax - tokenized source
|
||||
; esi - source text in persistent storage
|
||||
mov edi,esi
|
||||
xor al,al
|
||||
or ecx,-1
|
||||
repne scasb
|
||||
not ecx
|
||||
mov [source_text_length],ecx
|
||||
mov ebx,[memory_source_cache]
|
||||
xor eax,eax
|
||||
call get_from_map
|
||||
jc adapt_memory_source
|
||||
retn
|
||||
adapt_memory_source:
|
||||
mov [source_text],esi
|
||||
call tokenize_source
|
||||
mov eax,[tokenization_buffer]
|
||||
mov esi,[source_text]
|
||||
mov ecx,[source_text_length]
|
||||
mov ebx,[memory_source_cache]
|
||||
call put_into_map
|
||||
mov eax,[tokenization_buffer]
|
||||
retn
|
||||
|
||||
tokenize_source:
|
||||
; in:
|
||||
; [source_text] - ASCIIZ text
|
||||
; [source_text_length] = length of text (including terminating character)
|
||||
; out:
|
||||
; [tokenization_buffer] - tokenized source
|
||||
; [tokenization_buffer_length] = length of tokenized source
|
||||
mov ecx,[source_text_length]
|
||||
shl ecx,1
|
||||
add ecx,18
|
||||
call malloc_growable
|
||||
mov [tokenization_buffer],eax
|
||||
mov [tokenization_buffer_length],ecx
|
||||
add eax,ecx
|
||||
sub eax,[source_text]
|
||||
sub eax,[source_text_length]
|
||||
mov [buffer_end_offset],eax
|
||||
mov esi,[source_text]
|
||||
mov edi,[tokenization_buffer]
|
||||
mov [last_token],0Ah
|
||||
tokenize:
|
||||
mov eax,[buffer_end_offset]
|
||||
add eax,esi
|
||||
sub eax,edi
|
||||
cmp eax,18
|
||||
jae tokenization_buffer_reserve_ok
|
||||
mov ecx,esi
|
||||
sub ecx,[source_text]
|
||||
mov eax,[source_text_length]
|
||||
mul [tokenization_buffer_length]
|
||||
div ecx
|
||||
mov ecx,eax
|
||||
add ecx,18
|
||||
mov eax,[tokenization_buffer]
|
||||
call realloc
|
||||
sub edi,[tokenization_buffer]
|
||||
add edi,eax
|
||||
mov [tokenization_buffer],eax
|
||||
mov [tokenization_buffer_length],ecx
|
||||
add eax,ecx
|
||||
sub eax,[source_text]
|
||||
sub eax,[source_text_length]
|
||||
mov [buffer_end_offset],eax
|
||||
tokenization_buffer_reserve_ok:
|
||||
movzx eax,byte [esi]
|
||||
inc esi
|
||||
mov ah,[characters+eax]
|
||||
cmp ah,20h
|
||||
je control_character
|
||||
test ah,ah
|
||||
jnz make_name_token
|
||||
character_token:
|
||||
stosb
|
||||
mov [last_token],al
|
||||
jmp tokenize
|
||||
make_string_token:
|
||||
mov dl,al
|
||||
mov byte [edi],22h
|
||||
mov [last_token],22h
|
||||
add edi,5
|
||||
xor ecx,ecx
|
||||
copy_string:
|
||||
mov al,[esi]
|
||||
cmp al,0Dh
|
||||
je broken_string
|
||||
cmp al,0Ah
|
||||
je broken_string
|
||||
cmp al,1Ah
|
||||
je broken_string
|
||||
test al,al
|
||||
jz broken_string
|
||||
inc esi
|
||||
cmp al,dl
|
||||
jne copy_string_character
|
||||
cmp byte [esi],al
|
||||
jne finish_string_token
|
||||
inc esi
|
||||
copy_string_character:
|
||||
mov [edi+ecx],al
|
||||
inc ecx
|
||||
jmp copy_string
|
||||
broken_string:
|
||||
mov byte [edi-5],27h
|
||||
finish_string_token:
|
||||
mov al,[edi-5]
|
||||
mov [edi-4],ecx
|
||||
add edi,ecx
|
||||
jmp tokenize
|
||||
make_name_token:
|
||||
cmp al,22h
|
||||
je make_string_token
|
||||
cmp al,27h
|
||||
je make_string_token
|
||||
mov byte [edi],1Ah
|
||||
mov [last_token],1Ah
|
||||
add edi,5
|
||||
xor ebx,ebx
|
||||
mov ecx,FNV_OFFSET
|
||||
mov edx,ecx
|
||||
hash_name:
|
||||
mov [edi+ebx],al
|
||||
inc ebx
|
||||
xor cl,al
|
||||
xor dl,ah
|
||||
imul ecx,FNV_PRIME
|
||||
imul edx,FNV_PRIME
|
||||
movzx eax,byte [esi]
|
||||
inc esi
|
||||
mov ah,[characters+eax]
|
||||
cmp ah,20h
|
||||
je finish_name_token
|
||||
test ah,ah
|
||||
jnz hash_name
|
||||
finish_name_token:
|
||||
mov [edi-4],ebx
|
||||
add edi,ebx
|
||||
mov [edi],ecx
|
||||
mov [edi+4],edx
|
||||
xor ecx,ecx
|
||||
mov [edi+8],ecx
|
||||
add edi,12
|
||||
cmp ah,20h
|
||||
jne character_token
|
||||
control_character:
|
||||
cmp al,20h
|
||||
je whitespace
|
||||
cmp al,9
|
||||
je whitespace
|
||||
cmp [last_token],20h
|
||||
je mark_end_of_line
|
||||
inc edi
|
||||
mark_end_of_line:
|
||||
mov byte [edi-1],0Ah
|
||||
mov [last_token],0Ah
|
||||
cmp al,0Dh
|
||||
je cr
|
||||
cmp al,0Ah
|
||||
je lf
|
||||
xor al,al
|
||||
stosb
|
||||
mov ecx,edi
|
||||
mov eax,[tokenization_buffer]
|
||||
sub ecx,eax
|
||||
call realloc
|
||||
mov [tokenization_buffer],eax
|
||||
mov [tokenization_buffer_length],ecx
|
||||
retn
|
||||
cr:
|
||||
cmp byte [esi],0Ah
|
||||
jne tokenize
|
||||
inc esi
|
||||
jmp tokenize
|
||||
lf:
|
||||
cmp byte [esi],0Dh
|
||||
jne tokenize
|
||||
inc esi
|
||||
jmp tokenize
|
||||
whitespace:
|
||||
cmp [last_token],0Ah
|
||||
je tokenize
|
||||
cmp [last_token],20h
|
||||
je tokenize
|
||||
mov al,20h
|
||||
stosb
|
||||
mov [last_token],al
|
||||
jmp tokenize
|
||||
|
||||
get_file_data:
|
||||
; in:
|
||||
; esi - file path
|
||||
; out:
|
||||
; ebx - FileData, null when file not found
|
||||
; esi - file path in persistent storage
|
||||
; preserves: edi
|
||||
mov ebx,[file_data_cache]
|
||||
xor ecx,ecx
|
||||
call get_from_map
|
||||
jc initialize_file_data
|
||||
mov ebx,eax
|
||||
retn
|
||||
initialize_file_data:
|
||||
mov edx,esi
|
||||
call open
|
||||
jc remember_file_not_found
|
||||
push edi
|
||||
mov ecx,sizeof.FileData
|
||||
call malloc_fixed
|
||||
mov edi,eax
|
||||
xor eax,eax
|
||||
mov edx,eax
|
||||
mov cl,2
|
||||
call lseek
|
||||
jc file_not_seekable
|
||||
mov dword [edi+FileData.length],eax
|
||||
mov dword [edi+FileData.length+4],edx
|
||||
call close
|
||||
mov eax,edi
|
||||
xor ecx,ecx
|
||||
mov [eax+FileData.cache],ecx
|
||||
mov ebx,[file_data_cache]
|
||||
call put_into_map
|
||||
mov ebx,edi
|
||||
pop edi
|
||||
retn
|
||||
file_not_seekable:
|
||||
pop edi
|
||||
remember_file_not_found:
|
||||
xor eax,eax
|
||||
mov ecx,eax
|
||||
mov ebx,[file_data_cache]
|
||||
call put_into_map
|
||||
xor ebx,ebx
|
||||
retn
|
||||
|
||||
read_file_data:
|
||||
; in:
|
||||
; esi - file path
|
||||
; ebx - FileData
|
||||
; edi - buffer for data
|
||||
; [file_offset] = offset of data
|
||||
; [data_length] = length of data
|
||||
; out:
|
||||
; cf set when read failed
|
||||
; preserves: esi
|
||||
mov [file_data],ebx
|
||||
lea eax,[ebx+FileData.cache]
|
||||
mov [file_cache_pointer],eax
|
||||
mov ebx,[eax]
|
||||
read_from_file_cache:
|
||||
mov ecx,[data_length]
|
||||
test ecx,ecx
|
||||
jz file_data_read
|
||||
test ebx,ebx
|
||||
jz new_trailing_file_cache_entry
|
||||
mov eax,dword [file_offset]
|
||||
mov edx,dword [file_offset+4]
|
||||
sub eax,dword [ebx+FileCache.offset]
|
||||
sbb edx,dword [ebx+FileCache.offset+4]
|
||||
jc new_file_cache_entry
|
||||
jnz next_entry
|
||||
mov edx,[ebx+FileCache.length]
|
||||
sub edx,eax
|
||||
jbe next_entry
|
||||
cmp ecx,edx
|
||||
jbe length_to_read_ok
|
||||
mov ecx,edx
|
||||
length_to_read_ok:
|
||||
sub [data_length],ecx
|
||||
add dword [file_offset],ecx
|
||||
adc dword [file_offset+4],0
|
||||
mov edx,esi
|
||||
lea esi,[ebx+sizeof.FileCache+eax]
|
||||
rep movsb
|
||||
mov esi,edx
|
||||
next_entry:
|
||||
lea eax,[ebx+FileCache.next]
|
||||
mov [file_cache_pointer],eax
|
||||
mov ebx,[eax]
|
||||
jmp read_from_file_cache
|
||||
file_data_read:
|
||||
clc
|
||||
retn
|
||||
new_trailing_file_cache_entry:
|
||||
mov ebx,[file_data]
|
||||
mov ecx,dword [ebx+FileData.length]
|
||||
mov edx,dword [ebx+FileData.length+4]
|
||||
cmp ecx,dword [file_offset]
|
||||
jne measure_cache_gap
|
||||
cmp edx,dword [file_offset+4]
|
||||
jne measure_cache_gap
|
||||
stc
|
||||
retn
|
||||
new_file_cache_entry:
|
||||
mov ecx,dword [ebx+FileCache.offset]
|
||||
mov edx,dword [ebx+FileCache.offset+4]
|
||||
measure_cache_gap:
|
||||
mov eax,dword [file_offset]
|
||||
and eax,not 0FFFh
|
||||
sub ecx,eax
|
||||
sbb edx,dword [file_offset+4]
|
||||
jnz compute_aligned_length
|
||||
cmp ecx,[data_length]
|
||||
jbe read_into_cache
|
||||
compute_aligned_length:
|
||||
mov eax,dword [file_offset]
|
||||
and eax,0FFFh
|
||||
add eax,[data_length]
|
||||
dec eax
|
||||
shr eax,12
|
||||
inc eax
|
||||
shl eax,12
|
||||
test edx,edx
|
||||
jnz use_aligned_length
|
||||
cmp eax,ecx
|
||||
jae read_into_cache
|
||||
use_aligned_length:
|
||||
mov ecx,eax
|
||||
read_into_cache:
|
||||
push ecx
|
||||
add ecx,sizeof.FileCache
|
||||
call malloc_fixed
|
||||
mov ebx,eax
|
||||
mov eax,[file_cache_pointer]
|
||||
mov edx,ebx
|
||||
xchg edx,[eax]
|
||||
mov [ebx+FileCache.next],edx
|
||||
pop [ebx+FileCache.length]
|
||||
mov eax,dword [file_offset]
|
||||
and eax,not 0FFFh
|
||||
mov edx,dword [file_offset+4]
|
||||
mov dword [ebx+FileCache.offset],eax
|
||||
mov dword [ebx+FileCache.offset+4],edx
|
||||
push ebx edi
|
||||
mov edi,ebx
|
||||
mov edx,esi
|
||||
call open
|
||||
jc file_access_error
|
||||
mov eax,dword [edi+FileCache.offset]
|
||||
mov edx,dword [edi+FileCache.offset+4]
|
||||
xor cl,cl
|
||||
call lseek
|
||||
jc file_access_error
|
||||
lea edx,[edi+sizeof.FileCache]
|
||||
mov ecx,[edi+FileCache.length]
|
||||
call read
|
||||
jc file_access_error
|
||||
call close
|
||||
pop edi ebx
|
||||
jmp read_from_file_cache
|
||||
file_access_error:
|
||||
pop edi ebx
|
||||
stc
|
||||
retn
|
||||
|
1547
toolchain/fasmg.kl0e/source/symbols.inc
Normal file
1547
toolchain/fasmg.kl0e/source/symbols.inc
Normal file
File diff suppressed because it is too large
Load Diff
649
toolchain/fasmg.kl0e/source/tables.inc
Normal file
649
toolchain/fasmg.kl0e/source/tables.inc
Normal file
@ -0,0 +1,649 @@
|
||||
|
||||
OPERATOR_PRECEDENCE_MASK = 3Fh
|
||||
OPERATOR_UNARY = 40h
|
||||
OPERATOR_RIGHT_ASSOCIATIVE = 80h
|
||||
|
||||
SIZE_BYTE = 1
|
||||
SIZE_WORD = 2
|
||||
SIZE_DWORD = 4
|
||||
SIZE_PWORD = 6
|
||||
SIZE_QWORD = 8
|
||||
SIZE_TWORD = 10
|
||||
SIZE_DQWORD = 16
|
||||
SIZE_QQWORD = 32
|
||||
SIZE_DQQWORD = 64
|
||||
|
||||
PREPOSITION_AT = 0
|
||||
PREPOSITION_FROM = 1
|
||||
PREPOSITION_AS = 2
|
||||
PREPOSITION_DUP = 3
|
||||
|
||||
control_characters db 0,9,0Ah,0Dh,1Ah,20h
|
||||
.count = $-control_characters
|
||||
|
||||
syntactical_characters db '+-/*=<>()[]{}:?!,.|&~#`\;'
|
||||
.count = $-syntactical_characters
|
||||
|
||||
include_variable db 'INCLUDE',0
|
||||
|
||||
separating_operators:
|
||||
|
||||
db '+',VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,1 + OPERATOR_UNARY
|
||||
dd calculate_to_number
|
||||
|
||||
db '-',VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,1 + OPERATOR_UNARY
|
||||
dd calculate_neg
|
||||
|
||||
db '+',VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,1
|
||||
dd calculate_add
|
||||
|
||||
db '-',VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,1
|
||||
dd calculate_sub
|
||||
|
||||
db '*',VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,2
|
||||
dd calculate_mul
|
||||
|
||||
db '/',VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,2
|
||||
dd calculate_div
|
||||
|
||||
db 0
|
||||
|
||||
symbols:
|
||||
|
||||
db 3,'not',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,6 + OPERATOR_UNARY
|
||||
dd calculate_not
|
||||
|
||||
db 3,'mod',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,3
|
||||
dd calculate_mod
|
||||
|
||||
db 3,'xor',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,4
|
||||
dd calculate_xor
|
||||
|
||||
db 3,'and',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,4
|
||||
dd calculate_and
|
||||
|
||||
db 2,'or',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,4
|
||||
dd calculate_or
|
||||
|
||||
db 3,'shl',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,5
|
||||
dd calculate_shl
|
||||
|
||||
db 3,'shr',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,5
|
||||
dd calculate_shr
|
||||
|
||||
db 3,'bsf',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,6 + OPERATOR_UNARY
|
||||
dd calculate_bsf
|
||||
|
||||
db 3,'bsr',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,6 + OPERATOR_UNARY
|
||||
dd calculate_bsr
|
||||
|
||||
db 5,'bswap',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,5
|
||||
dd calculate_bswap
|
||||
|
||||
db 7,'bappend',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,4
|
||||
dd calculate_bappend
|
||||
|
||||
db 6,'string',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0 + OPERATOR_UNARY
|
||||
dd calculate_to_string
|
||||
|
||||
db 5,'float',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,10 + OPERATOR_UNARY
|
||||
dd calculate_to_float
|
||||
|
||||
db 5,'trunc',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,10 + OPERATOR_UNARY
|
||||
dd extract_integer_part
|
||||
|
||||
db 6,'sizeof',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,10 + OPERATOR_UNARY
|
||||
dd extract_size
|
||||
|
||||
db 8,'lengthof',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,10 + OPERATOR_UNARY
|
||||
dd count_bytes
|
||||
|
||||
db 10,'elementsof',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,10 + OPERATOR_UNARY
|
||||
dd count_elements
|
||||
|
||||
db 7,'element',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,7
|
||||
dd extract_element
|
||||
|
||||
db 5,'scale',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,7
|
||||
dd extract_scale
|
||||
|
||||
db 8,'metadata',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,7
|
||||
dd extract_metadata
|
||||
|
||||
db 9,'elementof',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,8 + OPERATOR_RIGHT_ASSOCIATIVE
|
||||
dd extract_element_reverse
|
||||
|
||||
db 7,'scaleof',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,8 + OPERATOR_RIGHT_ASSOCIATIVE
|
||||
dd extract_scale_reverse
|
||||
|
||||
db 10,'metadataof',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,8 + OPERATOR_RIGHT_ASSOCIATIVE
|
||||
dd extract_metadata_reverse
|
||||
|
||||
db 7,'element',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd define_element
|
||||
|
||||
db 3,'equ',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd define_symbolic_variable
|
||||
|
||||
db 5,'reequ',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd redefine_symbolic_variable
|
||||
|
||||
db 6,'define',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd define_raw_symbolic_variable
|
||||
|
||||
db 8,'redefine',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd redefine_raw_symbolic_variable
|
||||
|
||||
db 7,'restore',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SYMCLASS_EXPRESSION
|
||||
dd restore_variables
|
||||
|
||||
db 9,'namespace',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd set_namespace
|
||||
|
||||
db 7,'display',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd display_data
|
||||
|
||||
db 3,'err',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd custom_error
|
||||
|
||||
db 7,'include',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd include_source
|
||||
|
||||
db 4,'eval',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd evaluate_string
|
||||
|
||||
db 6,'assert',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd assert_condition
|
||||
|
||||
db 7,'defined',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMPARATOR,VAL_INTERNAL,0
|
||||
dd check_if_defined
|
||||
|
||||
db 4,'used',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMPARATOR,VAL_INTERNAL,0
|
||||
dd check_if_used
|
||||
|
||||
db 8,'definite',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMPARATOR,VAL_INTERNAL,0
|
||||
dd check_if_defined_earlier
|
||||
|
||||
db 6,'eqtype',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMPARATOR,VAL_INTERNAL,0
|
||||
dd check_if_type_equal
|
||||
|
||||
db 2,'eq',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMPARATOR,VAL_INTERNAL,0
|
||||
dd check_if_value_equal
|
||||
|
||||
db 10,'relativeto',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_COMPARATOR,VAL_INTERNAL,0
|
||||
dd check_if_relative
|
||||
|
||||
db 2,'if',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd conditional_block
|
||||
|
||||
db 5,'match',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd match_block
|
||||
|
||||
db 6,'rmatch',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd raw_match_block
|
||||
|
||||
db 8,'rawmatch',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd raw_match_block
|
||||
|
||||
db 5,'while',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd conditionally_repeated_block
|
||||
|
||||
db 6,'repeat',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd repeated_block
|
||||
|
||||
db 7,'iterate',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd iterator_block
|
||||
|
||||
db 4,'rept',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd repeated_block
|
||||
|
||||
db 3,'irp',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd iterator_block
|
||||
|
||||
db 4,'irpv',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd variable_iterator_block
|
||||
|
||||
db 4,'indx',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd set_iterator_index
|
||||
|
||||
db 5,'break',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd break_directive
|
||||
|
||||
db 4,'else',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd else_directive
|
||||
|
||||
db 3,'end',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd end_directive
|
||||
|
||||
db 8,'postpone',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd postponed_block
|
||||
|
||||
db 5,'macro',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd define_macro
|
||||
|
||||
db 5,'struc',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd define_struc
|
||||
|
||||
db 3,'esc',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd escape_directive
|
||||
|
||||
db 5,'local',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd local_directive
|
||||
|
||||
db 8,'outscope',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd outscope_directive
|
||||
|
||||
db 5,'purge',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SYMCLASS_INSTRUCTION
|
||||
dd restore_variables
|
||||
|
||||
db 7,'restruc',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SYMCLASS_STRUCTURE
|
||||
dd restore_variables
|
||||
|
||||
db 7,'mvmacro',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SYMCLASS_INSTRUCTION
|
||||
dd move_variable_values
|
||||
|
||||
db 7,'mvstruc',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SYMCLASS_STRUCTURE
|
||||
dd move_variable_values
|
||||
|
||||
db 15,'calminstruction',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd define_calm_instruction
|
||||
|
||||
db 14,'removecomments',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd choose_to_remove_comments
|
||||
|
||||
db 14,'retaincomments',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd choose_to_retain_comments
|
||||
|
||||
db 12,'combinelines',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd choose_to_combine_lines
|
||||
|
||||
db 12,'isolatelines',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd choose_to_isolate_lines
|
||||
|
||||
db 3,'org',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd set_base_address
|
||||
|
||||
db 7,'section',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd begin_new_section
|
||||
|
||||
db 10,'restartout',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd restart_output
|
||||
|
||||
db 6,'format',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd format_directive
|
||||
|
||||
db 4,'emit',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd define_data
|
||||
|
||||
db 4,'emit',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd define_labeled_data
|
||||
|
||||
db 3,'dbx',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd define_data
|
||||
|
||||
db 3,'dbx',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd define_labeled_data
|
||||
|
||||
db 2,'db',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_BYTE
|
||||
dd define_data
|
||||
|
||||
db 2,'db',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_BYTE
|
||||
dd define_labeled_data
|
||||
|
||||
db 2,'dw',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_WORD
|
||||
dd define_data
|
||||
|
||||
db 2,'dw',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_WORD
|
||||
dd define_labeled_data
|
||||
|
||||
db 2,'dd',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_DWORD
|
||||
dd define_data
|
||||
|
||||
db 2,'dd',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_DWORD
|
||||
dd define_labeled_data
|
||||
|
||||
db 2,'dp',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_PWORD
|
||||
dd define_data
|
||||
|
||||
db 2,'dp',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_PWORD
|
||||
dd define_labeled_data
|
||||
|
||||
db 2,'dq',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_QWORD
|
||||
dd define_data
|
||||
|
||||
db 2,'dq',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_QWORD
|
||||
dd define_labeled_data
|
||||
|
||||
db 2,'dt',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_TWORD
|
||||
dd define_data
|
||||
|
||||
db 2,'dt',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_TWORD
|
||||
dd define_labeled_data
|
||||
|
||||
db 3,'ddq',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_DQWORD
|
||||
dd define_data
|
||||
|
||||
db 3,'ddq',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_DQWORD
|
||||
dd define_labeled_data
|
||||
|
||||
db 3,'dqq',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_QQWORD
|
||||
dd define_data
|
||||
|
||||
db 3,'dqq',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_QQWORD
|
||||
dd define_labeled_data
|
||||
|
||||
db 4,'ddqq',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_DQQWORD
|
||||
dd define_data
|
||||
|
||||
db 4,'ddqq',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_DQQWORD
|
||||
dd define_labeled_data
|
||||
|
||||
db 2,'rb',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_BYTE
|
||||
dd reserve_data
|
||||
|
||||
db 2,'rb',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_BYTE
|
||||
dd reserve_labeled_data
|
||||
|
||||
db 2,'rw',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_WORD
|
||||
dd reserve_data
|
||||
|
||||
db 2,'rw',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_WORD
|
||||
dd reserve_labeled_data
|
||||
|
||||
db 2,'rd',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_DWORD
|
||||
dd reserve_data
|
||||
|
||||
db 2,'rd',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_DWORD
|
||||
dd reserve_labeled_data
|
||||
|
||||
db 2,'rp',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_PWORD
|
||||
dd reserve_data
|
||||
|
||||
db 2,'rp',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_PWORD
|
||||
dd reserve_labeled_data
|
||||
|
||||
db 2,'rq',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_QWORD
|
||||
dd reserve_data
|
||||
|
||||
db 2,'rq',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_QWORD
|
||||
dd reserve_labeled_data
|
||||
|
||||
db 2,'rt',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_TWORD
|
||||
dd reserve_data
|
||||
|
||||
db 2,'rt',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_TWORD
|
||||
dd reserve_labeled_data
|
||||
|
||||
db 3,'rdq',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_DQWORD
|
||||
dd reserve_data
|
||||
|
||||
db 3,'rdq',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_DQWORD
|
||||
dd reserve_labeled_data
|
||||
|
||||
db 3,'rqq',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_QQWORD
|
||||
dd reserve_data
|
||||
|
||||
db 3,'rqq',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_QQWORD
|
||||
dd reserve_labeled_data
|
||||
|
||||
db 4,'rdqq',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_DQQWORD
|
||||
dd reserve_data
|
||||
|
||||
db 4,'rdqq',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,SIZE_DQQWORD
|
||||
dd reserve_labeled_data
|
||||
|
||||
db 4,'file',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd include_data
|
||||
|
||||
db 4,'file',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd include_labeled_data
|
||||
|
||||
db 1,'$',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_FUNCTION,VAL_INTERNAL,0
|
||||
dd current_address_value
|
||||
|
||||
db 2,'$$',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_FUNCTION,VAL_INTERNAL,0
|
||||
dd base_address_value
|
||||
|
||||
db 2,'$@',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_FUNCTION,VAL_INTERNAL,0
|
||||
dd truncated_address_value
|
||||
|
||||
db 2,'$%',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_FUNCTION,VAL_INTERNAL,0
|
||||
dd current_position_value
|
||||
|
||||
db 3,'$%%',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_FUNCTION,VAL_INTERNAL,0
|
||||
dd truncated_position_value
|
||||
|
||||
db 2,'%t',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_FUNCTION,VAL_INTERNAL,0
|
||||
dd current_time_value
|
||||
|
||||
db 8,'__time__',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_FUNCTION,VAL_INTERNAL,0
|
||||
dd current_time_value
|
||||
|
||||
db 10,'__source__',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_FUNCTION,VAL_INTERNAL,0
|
||||
dd main_file_name_value
|
||||
|
||||
db 8,'__file__',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_FUNCTION,VAL_INTERNAL,0
|
||||
dd current_file_name_value
|
||||
|
||||
db 8,'__line__',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_FUNCTION,VAL_INTERNAL,0
|
||||
dd current_line_number_value
|
||||
|
||||
db 4,'byte',SYMCLASS_EXPRESSION,VALTYPE_PLAIN,VAL_INTERNAL,0
|
||||
dd SIZE_BYTE
|
||||
|
||||
db 4,'word',SYMCLASS_EXPRESSION,VALTYPE_PLAIN,VAL_INTERNAL,0
|
||||
dd SIZE_WORD
|
||||
|
||||
db 5,'dword',SYMCLASS_EXPRESSION,VALTYPE_PLAIN,VAL_INTERNAL,0
|
||||
dd SIZE_DWORD
|
||||
|
||||
db 5,'pword',SYMCLASS_EXPRESSION,VALTYPE_PLAIN,VAL_INTERNAL,0
|
||||
dd SIZE_PWORD
|
||||
|
||||
db 5,'fword',SYMCLASS_EXPRESSION,VALTYPE_PLAIN,VAL_INTERNAL,0
|
||||
dd SIZE_PWORD
|
||||
|
||||
db 5,'qword',SYMCLASS_EXPRESSION,VALTYPE_PLAIN,VAL_INTERNAL,0
|
||||
dd SIZE_QWORD
|
||||
|
||||
db 5,'tword',SYMCLASS_EXPRESSION,VALTYPE_PLAIN,VAL_INTERNAL,0
|
||||
dd SIZE_TWORD
|
||||
|
||||
db 5,'tbyte',SYMCLASS_EXPRESSION,VALTYPE_PLAIN,VAL_INTERNAL,0
|
||||
dd SIZE_TWORD
|
||||
|
||||
db 6,'dqword',SYMCLASS_EXPRESSION,VALTYPE_PLAIN,VAL_INTERNAL,0
|
||||
dd SIZE_DQWORD
|
||||
|
||||
db 5,'xword',SYMCLASS_EXPRESSION,VALTYPE_PLAIN,VAL_INTERNAL,0
|
||||
dd SIZE_DQWORD
|
||||
|
||||
db 6,'qqword',SYMCLASS_EXPRESSION,VALTYPE_PLAIN,VAL_INTERNAL,0
|
||||
dd SIZE_QQWORD
|
||||
|
||||
db 5,'yword',SYMCLASS_EXPRESSION,VALTYPE_PLAIN,VAL_INTERNAL,0
|
||||
dd SIZE_QQWORD
|
||||
|
||||
db 7,'dqqword',SYMCLASS_EXPRESSION,VALTYPE_PLAIN,VAL_INTERNAL,0
|
||||
dd SIZE_DQQWORD
|
||||
|
||||
db 5,'zword',SYMCLASS_EXPRESSION,VALTYPE_PLAIN,VAL_INTERNAL,0
|
||||
dd SIZE_DQQWORD
|
||||
|
||||
db 5,'label',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd label_directive
|
||||
|
||||
db 7,'virtual',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd virtual_block
|
||||
|
||||
db 4,'load',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd load_value
|
||||
|
||||
db 5,'store',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd store_value
|
||||
|
||||
db 2,'at',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_PREPOSITION,VAL_INTERNAL,0
|
||||
dd PREPOSITION_AT
|
||||
|
||||
db 4,'from',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_PREPOSITION,VAL_INTERNAL,0
|
||||
dd PREPOSITION_FROM
|
||||
|
||||
db 2,'as',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_PREPOSITION,VAL_INTERNAL,0
|
||||
dd PREPOSITION_AS
|
||||
|
||||
db 3,'dup',SYMCLASS_EXPRESSION,VALTYPE_NATIVE_PREPOSITION,VAL_INTERNAL,0
|
||||
dd PREPOSITION_DUP
|
||||
|
||||
db 0
|
||||
|
||||
db 3,'end'
|
||||
|
||||
db 9,'namespace',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd end_namespace
|
||||
|
||||
db 2,'if',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd end_conditional_block
|
||||
|
||||
db 5,'match',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd end_match_block
|
||||
|
||||
db 6,'rmatch',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd end_raw_match_block
|
||||
|
||||
db 8,'rawmatch',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd end_raw_match_block
|
||||
|
||||
db 5,'while',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd end_conditionally_repeated_block
|
||||
|
||||
db 6,'repeat',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd end_repeated_block
|
||||
|
||||
db 7,'iterate',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd end_iterator_block
|
||||
|
||||
db 4,'rept',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd end_repeated_block
|
||||
|
||||
db 3,'irp',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd end_iterator_block
|
||||
|
||||
db 4,'irpv',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd end_variable_iterator_block
|
||||
|
||||
db 8,'postpone',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd end_postponed_block
|
||||
|
||||
db 5,'macro',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd end_macro
|
||||
|
||||
db 5,'struc',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd end_struc
|
||||
|
||||
db 7,'virtual',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd end_virtual_block
|
||||
|
||||
db 0
|
||||
|
||||
db 4,'else'
|
||||
|
||||
db 2,'if',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd else_conditional_block
|
||||
|
||||
db 5,'match',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd else_match_block
|
||||
|
||||
db 6,'rmatch',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd else_raw_match_block
|
||||
|
||||
db 8,'rawmatch',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd else_raw_match_block
|
||||
|
||||
db 0
|
||||
|
||||
db 6,'format'
|
||||
|
||||
db 6,'binary',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd format_binary
|
||||
|
||||
db 0
|
||||
|
||||
db 15,'calminstruction'
|
||||
|
||||
db 5,'local',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd alm_local
|
||||
|
||||
db 7,'arrange',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd alm_arrange
|
||||
|
||||
db 5,'match',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd alm_match
|
||||
|
||||
db 8,'assemble',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd alm_assemble
|
||||
|
||||
db 9,'transform',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd alm_transform
|
||||
|
||||
db 9,'stringify',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd alm_stringify
|
||||
|
||||
db 7,'publish',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd alm_publish
|
||||
|
||||
db 4,'take',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd alm_take
|
||||
|
||||
db 7,'compute',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd alm_compute
|
||||
|
||||
db 5,'check',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd alm_check
|
||||
|
||||
db 4,'emit',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd alm_emit
|
||||
|
||||
db 4,'load',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd alm_load
|
||||
|
||||
db 5,'store',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd alm_store
|
||||
|
||||
db 7,'display',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd alm_display
|
||||
|
||||
db 3,'err',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd alm_err
|
||||
|
||||
db 4,'jyes',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd alm_jyes
|
||||
|
||||
db 3,'jno',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd alm_jno
|
||||
|
||||
db 4,'jump',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd alm_jump
|
||||
|
||||
db 4,'call',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd alm_call
|
||||
|
||||
db 4,'exit',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd alm_exit
|
||||
|
||||
db 3,'end',SYMCLASS_INSTRUCTION,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL + VAL_UNCONDITIONAL,0
|
||||
dd alm_end
|
||||
|
||||
db 15,'calminstruction',SYMCLASS_STRUCTURE,VALTYPE_NATIVE_COMMAND,VAL_INTERNAL,0
|
||||
dd alm_end
|
||||
|
||||
db 0
|
||||
|
||||
zero_value dd 0
|
||||
dd 0
|
||||
|
||||
singular_value dd 1
|
||||
db 1
|
||||
dd 0
|
||||
|
||||
subtraction_operator dd EXPR_OPERATOR,calculate_sub
|
||||
dd 0
|
314
toolchain/fasmg.kl0e/source/variables.inc
Normal file
314
toolchain/fasmg.kl0e/source/variables.inc
Normal file
@ -0,0 +1,314 @@
|
||||
|
||||
characters db 256 dup ?
|
||||
|
||||
maximum_number_of_errors dd ?
|
||||
maximum_depth_of_stack dd ?
|
||||
|
||||
variables:
|
||||
|
||||
temporary_value dd 4 dup ?
|
||||
accumulator dd 3 dup ?
|
||||
|
||||
source_file dd ?
|
||||
|
||||
include_paths dd ?
|
||||
|
||||
storage_blocks dd ?
|
||||
storage_free_space dd ?
|
||||
storage_free_space_length dd ?
|
||||
|
||||
tree_blocks dd ?
|
||||
tree_reserve dd ?
|
||||
tree_reserve_length dd ?
|
||||
|
||||
value_definition_chain dd ?
|
||||
retired_definition dd ?
|
||||
|
||||
file_source_cache dd ?
|
||||
memory_source_cache dd ?
|
||||
file_data_cache dd ?
|
||||
|
||||
operator_table dd ?
|
||||
root_namespace dd ?
|
||||
root_parameter_namespace dd ?
|
||||
local_parameter_namespace dd ?
|
||||
interceptor_symbol dd ?
|
||||
label_interceptor_symbol dd ?
|
||||
other_interceptor_symbol dd ?
|
||||
proxy_number dd ?
|
||||
|
||||
source_context dd ?
|
||||
source_context_maximum_length dd ?
|
||||
current_pass dd ?
|
||||
current_context RecognitionContext
|
||||
local_namespace dd ?
|
||||
parameter_namespace dd ?
|
||||
|
||||
directives_stack dd ?
|
||||
directives_stack_base dd ?
|
||||
directives_stack_end dd ?
|
||||
|
||||
current_counter dd ?
|
||||
counters_stack_base dd ?
|
||||
counters_stack_end dd ?
|
||||
|
||||
first_error dd ?
|
||||
|
||||
current_area dd ?
|
||||
output_areas_list dd ?
|
||||
output_areas_list_end dd ?
|
||||
initial_output_area_entry dd ?
|
||||
current_output_area_entry dd ?
|
||||
prior_uninitialized_length dq ?
|
||||
virtual_area dd ?
|
||||
auxiliary_output_areas dd ?
|
||||
void_symbol dd ?
|
||||
|
||||
base_path dd ?
|
||||
output_extension dd ?
|
||||
output_extension_length dd ?
|
||||
output_failures dd ?
|
||||
|
||||
preprocessing_workspace Workspace
|
||||
assembly_workspace Workspace
|
||||
identifier_workspace Workspace
|
||||
value_workspace Workspace
|
||||
expression_workspace Workspace
|
||||
calculation_workspace Workspace
|
||||
auxiliary_workspace Workspace
|
||||
|
||||
line_start dd ?
|
||||
line_end dd ?
|
||||
line_embeddings dd ?
|
||||
line_embeddings_maximum_length dd ?
|
||||
number_of_line_embeddings dd ?
|
||||
preprocessed_context dd ?
|
||||
line_context dd ?
|
||||
embedded_context dd ?
|
||||
number_of_enclosings dd ?
|
||||
|
||||
recognition_context RecognitionContext
|
||||
name_token dd ?
|
||||
case_sensitive_hash dd ?
|
||||
case_insensitive_hash dd ?
|
||||
kept_symbol dd ?
|
||||
current_symbol dd ?
|
||||
tree_stack_base dd ?
|
||||
tree_stack_end dd ?
|
||||
symbol_root dd ?
|
||||
symbol_branch dd ?
|
||||
minor_identifier dd ?
|
||||
|
||||
source_end dd ?
|
||||
symbol_start dd ?
|
||||
symbol_data dd ?
|
||||
symbol_value_start dd ?
|
||||
symbol_value_end dd ?
|
||||
|
||||
interceptor dd ?
|
||||
label_branch dd ?
|
||||
label_leaf dd ?
|
||||
label_interceptor dd ?
|
||||
label_instruction_start dd ?
|
||||
label_instruction_context dd ?
|
||||
|
||||
display_buffer dd ?
|
||||
display_buffer_length dd ?
|
||||
display_data_length dd ?
|
||||
|
||||
macro_buffer dd ?
|
||||
macro_buffer_length dd ?
|
||||
macro_leaf dd ?
|
||||
macro_end_position dd ?
|
||||
|
||||
constituent_symbol dd ?
|
||||
constituent_value dd ?
|
||||
constituent_whitespace dd ?
|
||||
|
||||
alm_namespace dd ?
|
||||
alm_adjusted_context RecognitionContext
|
||||
calm_code_buffer Workspace
|
||||
calm_code_cursor dd ?
|
||||
calm_literals_buffer Workspace
|
||||
calm_literals_cursor dd ?
|
||||
calm_auxiliary_buffer Workspace
|
||||
calm_auxiliary_cursor dd ?
|
||||
calm_line_number dd ?
|
||||
calm_instruction_number dd ?
|
||||
calm_value dd ?
|
||||
calm_literals dd ?
|
||||
calm_source_pointer dd ?
|
||||
calm_rollback_offset dd ?
|
||||
|
||||
value_position dd ?
|
||||
kept_value dd ?
|
||||
converter_position dd ?
|
||||
expression_position dd ?
|
||||
expression_end dd ?
|
||||
operator_stack dd ?
|
||||
operator_stack_position dd ?
|
||||
operator_stack_base dd ?
|
||||
operator_stack_end dd ?
|
||||
calculation_position dd ?
|
||||
source_term dd ?
|
||||
destination_term dd ?
|
||||
temporary_terms dd ?
|
||||
free_temporary_terms dd ?
|
||||
temporary_floats dd ?
|
||||
iterations dd ?
|
||||
exponent dd ?
|
||||
multiplier dd ?
|
||||
divisor dd ?
|
||||
long_dividend_term dd ?
|
||||
long_divisor_term dd ?
|
||||
long_divisor_length dd ?
|
||||
division_temporary_terms dd ?
|
||||
mantissa_tail dd ?
|
||||
predicted_shift dd ?
|
||||
subexpression_end dd ?
|
||||
|
||||
condition_stack dd ?
|
||||
condition_stack_base dd ?
|
||||
condition_stack_end dd ?
|
||||
initial_parentheses dd ?
|
||||
comparator dd ?
|
||||
outer_expression dd ?
|
||||
|
||||
assembly_stack_base dd ?
|
||||
assembly_stack_end dd ?
|
||||
previous_symbol_end dd ?
|
||||
further_whitespace dd ?
|
||||
zero_digits dd ?
|
||||
decimal_places dd ?
|
||||
literal_exponent dd ?
|
||||
update_function dd ?
|
||||
argument_start dd ?
|
||||
macro_parameters_context dd ?
|
||||
new_local_namespace dd ?
|
||||
file_name dd ?
|
||||
string_end dd ?
|
||||
message_end dd ?
|
||||
data_area_symbol dd ?
|
||||
data_area dd ?
|
||||
data_offset dd ?
|
||||
file_offset dq ?
|
||||
data_length dd ?
|
||||
local_path dd ?
|
||||
|
||||
error_line_start dd ?
|
||||
error_line_end dd ?
|
||||
error_symbol dd ?
|
||||
last_source_entry dd ?
|
||||
last_file_source_entry dd ?
|
||||
preprocessed_text_end dd ?
|
||||
|
||||
source_text dd ?
|
||||
source_text_length dd ?
|
||||
tokenization_buffer dd ?
|
||||
tokenization_buffer_length dd ?
|
||||
buffer_end_offset dd ?
|
||||
file_data dd ?
|
||||
file_cache_pointer dd ?
|
||||
|
||||
address_length dd ?
|
||||
data_unit_length dd ?
|
||||
uninitialized_length dq ?
|
||||
|
||||
directive_block dd ?
|
||||
number_of_iterations dd ?
|
||||
number_of_parameters dd ?
|
||||
number_of_values dd ?
|
||||
parameter_index dd ?
|
||||
value_index dd ?
|
||||
value dd ?
|
||||
value_length dd ?
|
||||
metadata_length dd ?
|
||||
sequence_header_cursor dd ?
|
||||
sequence_header_length dd ?
|
||||
expression_sequence_cursor dd ?
|
||||
expression_sequence_end dd ?
|
||||
context_boundary dd ?
|
||||
whitespace_boundary dd ?
|
||||
transforming_namespace dd ?
|
||||
|
||||
pattern_start dd ?
|
||||
pattern_end dd ?
|
||||
matched_context dd ?
|
||||
substitutions_end dd ?
|
||||
stored_position dd ?
|
||||
stored_substitution dd ?
|
||||
stored_context dd ?
|
||||
stored_pattern dd ?
|
||||
brackets dd ?
|
||||
|
||||
instruction_value dd ?
|
||||
instruction_branch dd ?
|
||||
instruction_body dd ?
|
||||
|
||||
number_of_lines dd ?
|
||||
|
||||
preprocessing_mode db ?
|
||||
assembly_mode db ?
|
||||
next_pass_needed db ?
|
||||
shift_tracking db ?
|
||||
|
||||
name_kind db ?
|
||||
name_volatile db ?
|
||||
symbol_class db ?
|
||||
symbol_required db ?
|
||||
symbol_expected db ?
|
||||
kept_symbol_flags db ?
|
||||
chosen_class db ?
|
||||
expected_class db ?
|
||||
symbol_definition db ?
|
||||
symbol_independent db ?
|
||||
recognizer_setting db ?
|
||||
label_independent db ?
|
||||
value_type db ?
|
||||
waiting_for_digit db ?
|
||||
literal_exponent_sign db ?
|
||||
literal_fractional_part db ?
|
||||
float_literal_status db ?
|
||||
use_raw_values db ?
|
||||
|
||||
last_token db ?
|
||||
breakpoint_token db ?
|
||||
current_constituent db ?
|
||||
kept_value_in_workspace db ?
|
||||
leave_opening_parentheses db ?
|
||||
operator_argument_expected db ?
|
||||
term_type db ?
|
||||
bit_shift db ?
|
||||
shift_overflow db ?
|
||||
multiplier_sign db ?
|
||||
high_bits_count db ?
|
||||
first_sign db ?
|
||||
second_sign db ?
|
||||
comparator_priority db ?
|
||||
result_type db ?
|
||||
defined_element db ?
|
||||
|
||||
source_context_affected db ?
|
||||
raw_value db ?
|
||||
substitution_active db ?
|
||||
stored_substitution_activity db ?
|
||||
unprocessed_matching db ?
|
||||
whitespace_matching db ?
|
||||
macro_definition_active db ?
|
||||
macro_flags db ?
|
||||
macro_greedy db ?
|
||||
calm_definition_active db ?
|
||||
|
||||
size_specified db ?
|
||||
|
||||
message_volatile db ?
|
||||
displayed_byte db ?
|
||||
|
||||
alm_statement db ?
|
||||
calm_result db ?
|
||||
hidden_context db ?
|
||||
contextless_processing db ?
|
||||
|
||||
variables_end:
|
||||
|
||||
trace_mode db ?
|
1
toolchain/fasmg.kl0e/source/version.inc
Normal file
1
toolchain/fasmg.kl0e/source/version.inc
Normal file
@ -0,0 +1 @@
|
||||
VERSION equ "kl0e"
|
254
toolchain/fasmg.kl0e/source/windows/dll/fasmg.asm
Normal file
254
toolchain/fasmg.kl0e/source/windows/dll/fasmg.asm
Normal file
@ -0,0 +1,254 @@
|
||||
|
||||
match ,{
|
||||
|
||||
include 'win32a.inc'
|
||||
include 'localptr.inc'
|
||||
|
||||
} match -,{
|
||||
else
|
||||
|
||||
include 'selfhost.inc'
|
||||
|
||||
end match
|
||||
_ equ }
|
||||
|
||||
format PE large NX DLL
|
||||
entry DllEntryPoint
|
||||
|
||||
include '../../version.inc'
|
||||
|
||||
struct MEMORY_REGION
|
||||
address dd ?
|
||||
size dd ?
|
||||
ends
|
||||
|
||||
section '.text' code executable
|
||||
|
||||
include '../../assembler.inc'
|
||||
include '../../symbols.inc'
|
||||
include '../../expressions.inc'
|
||||
include '../../conditions.inc'
|
||||
include '../../floats.inc'
|
||||
include '../../directives.inc'
|
||||
include '../../calm.inc'
|
||||
include '../../errors.inc'
|
||||
include '../../map.inc'
|
||||
include '../../reader.inc'
|
||||
include '../../output.inc'
|
||||
include '../../console.inc'
|
||||
|
||||
DllEntryPoint:
|
||||
mov eax,1
|
||||
retn 12
|
||||
|
||||
fasmg_GetVersion:
|
||||
mov eax,version_string
|
||||
retn
|
||||
|
||||
fasmg_Assemble:
|
||||
|
||||
virtual at ebp - LOCAL_VARIABLES_SIZE
|
||||
|
||||
LocalVariables:
|
||||
|
||||
include '../../variables.inc'
|
||||
|
||||
maximum_number_of_passes dd ?
|
||||
|
||||
timestamp dq ?
|
||||
systemtime SYSTEMTIME
|
||||
filetime FILETIME
|
||||
|
||||
memory dd ?
|
||||
systmp dd ?
|
||||
|
||||
rb (LocalVariables - $) and 11b
|
||||
|
||||
LOCAL_VARIABLES_SIZE = $ - LocalVariables
|
||||
|
||||
assert $ - ebp = 0
|
||||
|
||||
previous_frame dd ?
|
||||
stored_edi dd ?
|
||||
stored_esi dd ?
|
||||
stored_ebx dd ?
|
||||
return_address dd ?
|
||||
|
||||
FunctionParameters:
|
||||
|
||||
source_string dd ?
|
||||
source_path dd ?
|
||||
output_region dd ?
|
||||
output_path dd ?
|
||||
stdout dd ?
|
||||
stderr dd ?
|
||||
|
||||
FUNCTION_PARAMETERS_SIZE = $ - FunctionParameters
|
||||
|
||||
end virtual
|
||||
|
||||
push ebx esi edi
|
||||
enter LOCAL_VARIABLES_SIZE,0
|
||||
|
||||
call system_init
|
||||
|
||||
mov [maximum_number_of_passes],100
|
||||
mov [maximum_number_of_errors],1000
|
||||
mov [maximum_depth_of_stack],10000
|
||||
|
||||
xor al,al
|
||||
call assembly_init
|
||||
|
||||
assemble:
|
||||
mov esi,[source_string]
|
||||
mov edx,[source_path]
|
||||
call assembly_pass
|
||||
jc assembly_done
|
||||
|
||||
mov eax,[current_pass]
|
||||
cmp eax,[maximum_number_of_passes]
|
||||
jb assemble
|
||||
|
||||
call show_display_data
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
mov eax,-2
|
||||
leave
|
||||
pop edi esi ebx
|
||||
retn FUNCTION_PARAMETERS_SIZE
|
||||
|
||||
assembly_done:
|
||||
|
||||
call show_display_data
|
||||
|
||||
cmp [first_error],0
|
||||
jne assembly_failed
|
||||
|
||||
mov esi,[output_region]
|
||||
test esi,esi
|
||||
jz output_copied
|
||||
call get_output_length
|
||||
test edx,edx
|
||||
jnz out_of_memory
|
||||
mov [value_length],eax
|
||||
xchg eax,[esi+MEMORY_REGION.size]
|
||||
cmp [esi+MEMORY_REGION.address],0
|
||||
je new_region_for_output
|
||||
cmp eax,[value_length]
|
||||
jae copy_output
|
||||
invoke VirtualAlloc,[esi+MEMORY_REGION.address],[esi+MEMORY_REGION.size],MEM_COMMIT,PAGE_READWRITE
|
||||
test eax,eax
|
||||
jnz copy_output
|
||||
invoke VirtualFree,[esi+MEMORY_REGION.address],0,MEM_RELEASE
|
||||
new_region_for_output:
|
||||
invoke VirtualAlloc,0,[esi+MEMORY_REGION.size],MEM_COMMIT,PAGE_READWRITE
|
||||
test eax,eax
|
||||
jz out_of_memory
|
||||
mov [esi+MEMORY_REGION.address],eax
|
||||
copy_output:
|
||||
mov edi,[esi+MEMORY_REGION.address]
|
||||
xor eax,eax
|
||||
mov dword [file_offset],eax
|
||||
mov dword [file_offset+4],eax
|
||||
call read_from_output
|
||||
output_copied:
|
||||
|
||||
mov ebx,[source_path]
|
||||
mov edi,[output_path]
|
||||
mov eax,ebx
|
||||
or eax,edi
|
||||
jz output_written
|
||||
call write_output_file
|
||||
jc write_failed
|
||||
output_written:
|
||||
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
xor eax,eax
|
||||
leave
|
||||
pop edi esi ebx
|
||||
retn FUNCTION_PARAMETERS_SIZE
|
||||
|
||||
assembly_failed:
|
||||
mov eax,[first_error]
|
||||
xor ecx,ecx
|
||||
count_errors:
|
||||
inc ecx
|
||||
mov eax,[eax+Error.next]
|
||||
test eax,eax
|
||||
jnz count_errors
|
||||
push ecx
|
||||
call show_errors
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
pop eax
|
||||
leave
|
||||
pop edi esi ebx
|
||||
retn FUNCTION_PARAMETERS_SIZE
|
||||
|
||||
write_failed:
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
mov eax,-3
|
||||
leave
|
||||
pop edi esi ebx
|
||||
retn FUNCTION_PARAMETERS_SIZE
|
||||
|
||||
out_of_memory:
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
mov eax,-1
|
||||
leave
|
||||
pop edi esi ebx
|
||||
retn FUNCTION_PARAMETERS_SIZE
|
||||
|
||||
include 'system.inc'
|
||||
|
||||
section '.rdata' data readable
|
||||
|
||||
data import
|
||||
|
||||
library kernel32,'KERNEL32.DLL'
|
||||
|
||||
import kernel32,\
|
||||
CloseHandle,'CloseHandle',\
|
||||
CreateFile,'CreateFileA',\
|
||||
ExitProcess,'ExitProcess',\
|
||||
GetCommandLine,'GetCommandLineA',\
|
||||
GetEnvironmentVariable,'GetEnvironmentVariableA',\
|
||||
GetStdHandle,'GetStdHandle',\
|
||||
GetSystemTime,'GetSystemTime',\
|
||||
GetTickCount,'GetTickCount',\
|
||||
HeapAlloc,'HeapAlloc',\
|
||||
HeapCreate,'HeapCreate',\
|
||||
HeapDestroy,'HeapDestroy',\
|
||||
HeapFree,'HeapFree',\
|
||||
HeapReAlloc,'HeapReAlloc',\
|
||||
HeapSize,'HeapSize',\
|
||||
VirtualAlloc,'VirtualAlloc',\
|
||||
VirtualFree,'VirtualFree',\
|
||||
ReadFile,'ReadFile',\
|
||||
SetFilePointer,'SetFilePointer',\
|
||||
SystemTimeToFileTime,'SystemTimeToFileTime',\
|
||||
WriteFile,'WriteFile',\
|
||||
GetLastError,'GetLastError'
|
||||
|
||||
end data
|
||||
|
||||
align 4
|
||||
|
||||
data export
|
||||
|
||||
export 'FASMG.DLL',\
|
||||
fasmg_GetVersion,'fasmg_GetVersion',\
|
||||
fasmg_Assemble,'fasmg_Assemble'
|
||||
|
||||
end data
|
||||
|
||||
include '../../tables.inc'
|
||||
include '../../messages.inc'
|
||||
|
||||
version_string db VERSION,0
|
||||
|
||||
section '.reloc' fixups data readable discardable
|
||||
|
28
toolchain/fasmg.kl0e/source/windows/dll/localptr.inc
Normal file
28
toolchain/fasmg.kl0e/source/windows/dll/localptr.inc
Normal file
@ -0,0 +1,28 @@
|
||||
|
||||
macro pushd arg
|
||||
{
|
||||
if arg eqtype +ebp & arg relativeto ebp
|
||||
if arg - ebp
|
||||
push eax
|
||||
lea eax,[arg]
|
||||
xchg eax,[esp]
|
||||
else
|
||||
push ebp
|
||||
end if
|
||||
else if ~ arg eq
|
||||
pushd arg
|
||||
end if
|
||||
}
|
||||
|
||||
macro mov dest,src
|
||||
{
|
||||
if src eqtype +ebp & src relativeto ebp
|
||||
if src - ebp
|
||||
lea dest,[src]
|
||||
else
|
||||
mov dest,ebp
|
||||
end if
|
||||
else
|
||||
mov dest,src
|
||||
end if
|
||||
}
|
266
toolchain/fasmg.kl0e/source/windows/dll/selfhost.inc
Normal file
266
toolchain/fasmg.kl0e/source/windows/dll/selfhost.inc
Normal file
@ -0,0 +1,266 @@
|
||||
|
||||
include '../../../examples/x86/include/80386.inc'
|
||||
|
||||
macro format?.PE? settings
|
||||
PE.Settings.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE or IMAGE_FILE_32BIT_MACHINE or IMAGE_FILE_LINE_NUMS_STRIPPED or IMAGE_FILE_LOCAL_SYMS_STRIPPED
|
||||
PE.Settings.DllCharacteristics = 0
|
||||
PE.Settings.Stamp = +VERSION
|
||||
PE.Settings.LegacyHeaders = 0
|
||||
local seq
|
||||
define seq settings:
|
||||
while 1
|
||||
match :, seq
|
||||
break
|
||||
else match =DLL? more, seq
|
||||
PE.Settings.Characteristics = PE.Settings.Characteristics or IMAGE_FILE_DLL
|
||||
redefine seq more
|
||||
else match =large? more, seq
|
||||
PE.Settings.Characteristics = PE.Settings.Characteristics or IMAGE_FILE_LARGE_ADDRESS_AWARE
|
||||
redefine seq more
|
||||
else match =WDM? more, seq
|
||||
PE.Settings.DllCharacteristics = PE.Settings.DllCharacteristics or IMAGE_DLLCHARACTERISTICS_WDM_DRIVER
|
||||
redefine seq more
|
||||
else match =NX? more, seq
|
||||
PE.Settings.DllCharacteristics = PE.Settings.DllCharacteristics or IMAGE_DLLCHARACTERISTICS_NX_COMPAT
|
||||
redefine seq more
|
||||
else match =at? base =on? stub :, seq
|
||||
PE.Settings.ImageBase = base
|
||||
PE.Settings.Stub = stub
|
||||
break
|
||||
else match =at? base :, seq
|
||||
PE.Settings.ImageBase = base
|
||||
break
|
||||
else match =on? stub :, seq
|
||||
PE.Settings.Stub = stub
|
||||
break
|
||||
else
|
||||
match =GUI? more, seq
|
||||
PE.Settings.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI
|
||||
redefine seq more
|
||||
else match =console? more, seq
|
||||
PE.Settings.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI
|
||||
redefine seq more
|
||||
else match =native? more, seq
|
||||
PE.Settings.Subsystem = IMAGE_SUBSYSTEM_NATIVE
|
||||
PE.Settings.SectionAlignment = 32
|
||||
PE.Settings.FileAlignment = 32
|
||||
redefine seq more
|
||||
else match =EFI? more, seq
|
||||
PE.Settings.Magic = 0x20B
|
||||
PE.Settings.Subsystem = IMAGE_SUBSYSTEM_EFI_APPLICATION
|
||||
redefine seq more
|
||||
else match =EFIboot? more, seq
|
||||
PE.Settings.Magic = 0x20B
|
||||
PE.Settings.Subsystem = IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
|
||||
redefine seq more
|
||||
else match =EFIruntime? more, seq
|
||||
PE.Settings.Magic = 0x20B
|
||||
PE.Settings.Subsystem = IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
|
||||
redefine seq more
|
||||
else
|
||||
err 'invalid argument'
|
||||
break
|
||||
end match
|
||||
match V.v more, seq
|
||||
PE.Settings.MajorSubsystemVersion = V
|
||||
PE.Settings.MinorSubsystemVersion = v
|
||||
redefine seq more
|
||||
end match
|
||||
end match
|
||||
end while
|
||||
if PE.Settings.Characteristics and IMAGE_FILE_DLL
|
||||
format binary as 'dll'
|
||||
else
|
||||
format binary as 'exe'
|
||||
end if
|
||||
include '../../../examples/x86/include/format/pe.inc'
|
||||
use32
|
||||
end macro
|
||||
|
||||
macro struct? name
|
||||
macro ends?!
|
||||
end namespace
|
||||
esc end struc
|
||||
virtual at 0
|
||||
name name
|
||||
sizeof.name = $
|
||||
end virtual
|
||||
purge ends?
|
||||
end macro
|
||||
esc struc name
|
||||
label . : sizeof.name
|
||||
namespace .
|
||||
end macro
|
||||
|
||||
calminstruction invoke? proc*,args&
|
||||
local tmp, tmpst, stack
|
||||
match , args
|
||||
jyes go
|
||||
collect:
|
||||
match tmpst=,args, args
|
||||
take stack, tmpst
|
||||
jyes collect
|
||||
push:
|
||||
match tmp], args
|
||||
jyes regular
|
||||
check args relativeto ebp & args - ebp
|
||||
jno regular
|
||||
arrange tmp, =push =eax
|
||||
assemble tmp
|
||||
arrange tmp, =lea =eax,[args]
|
||||
assemble tmp
|
||||
arrange tmp, =xchg =eax,[=esp]
|
||||
assemble tmp
|
||||
jump next
|
||||
regular:
|
||||
arrange tmp, =pushd args
|
||||
assemble tmp
|
||||
next:
|
||||
take args, stack
|
||||
jyes push
|
||||
go:
|
||||
arrange tmp, =call [proc]
|
||||
assemble tmp
|
||||
end calminstruction
|
||||
|
||||
calminstruction mov? dest*,src*
|
||||
local tmp
|
||||
match tmp], src
|
||||
jyes regular
|
||||
check src relativeto ebp & src - ebp
|
||||
jno regular
|
||||
arrange tmp, =lea dest,[src]
|
||||
assemble tmp
|
||||
exit
|
||||
regular:
|
||||
arrange tmp, =mov dest,src
|
||||
assemble tmp
|
||||
end calminstruction
|
||||
|
||||
macro library? definitions&
|
||||
PE.Imports:
|
||||
iterate <name,string>, definitions
|
||||
if ~ name.redundant
|
||||
dd RVA name.lookup,0,0,RVA name.str,RVA name.address
|
||||
end if
|
||||
name.referred = 1
|
||||
end iterate
|
||||
dd 0,0,0,0,0
|
||||
iterate <name,string>, definitions
|
||||
if ~ name.redundant
|
||||
name.str db string,0
|
||||
align 2
|
||||
end if
|
||||
end iterate
|
||||
end macro
|
||||
|
||||
macro import? name,definitions&
|
||||
align 4
|
||||
if defined name.referred
|
||||
name.lookup:
|
||||
iterate <label,string>, definitions
|
||||
if used label
|
||||
if string eqtype ''
|
||||
dd RVA name.label
|
||||
else
|
||||
dd 80000000h + string
|
||||
end if
|
||||
end if
|
||||
end iterate
|
||||
if $ > name.lookup
|
||||
name.redundant = 0
|
||||
dd 0
|
||||
else
|
||||
name.redundant = 1
|
||||
end if
|
||||
name.address:
|
||||
iterate <label,string>, definitions
|
||||
if used label
|
||||
if string eqtype ''
|
||||
label dd RVA name.label
|
||||
else
|
||||
label dd 80000000h + string
|
||||
end if
|
||||
end if
|
||||
end iterate
|
||||
if ~ name.redundant
|
||||
dd 0
|
||||
end if
|
||||
iterate <label,string>, definitions
|
||||
if used label & string eqtype ''
|
||||
name.label dw 0
|
||||
db string,0
|
||||
align 2
|
||||
end if
|
||||
end iterate
|
||||
end if
|
||||
end macro
|
||||
|
||||
macro export dllname,exports&
|
||||
iterate <label,string>, exports
|
||||
|
||||
local module,addresses,names,ordinal,count
|
||||
count = %%
|
||||
dd 0,0,0,RVA module,1
|
||||
dd count,count,RVA addresses,RVA names,RVA ordinal
|
||||
addresses:
|
||||
repeat count
|
||||
indx %
|
||||
dd RVA label
|
||||
end repeat
|
||||
names:
|
||||
repeat count
|
||||
dd RVA names.name#%
|
||||
end repeat
|
||||
ordinal:
|
||||
repeat count
|
||||
dw %-1
|
||||
end repeat
|
||||
module db dllname,0
|
||||
repeat count
|
||||
indx %
|
||||
names.name#% db string,0
|
||||
end repeat
|
||||
|
||||
local x,y,z,str1,str2,v1,v2
|
||||
x = count shr 1
|
||||
while x > 0
|
||||
y = x
|
||||
while y < count
|
||||
z = y
|
||||
while z-x >= 0
|
||||
load v1:dword from names+z*4
|
||||
str1 = ($-(RVA $))+v1
|
||||
load v2:dword from names+(z-x)*4
|
||||
str2 = ($-(RVA $))+v2
|
||||
while v1 > 0
|
||||
load v1:byte from str1+%-1
|
||||
load v2:byte from str2+%-1
|
||||
if v1 <> v2
|
||||
break
|
||||
end if
|
||||
end while
|
||||
if v1 < v2
|
||||
load v1:dword from names+z*4
|
||||
load v2:dword from names+(z-x)*4
|
||||
store v1:dword at names+(z-x)*4
|
||||
store v2:dword at names+z*4
|
||||
load v1:word from ordinal+z*2
|
||||
load v2:word from ordinal+(z-x)*2
|
||||
store v1:word at ordinal+(z-x)*2
|
||||
store v2:word at ordinal+z*2
|
||||
else
|
||||
break
|
||||
end if
|
||||
z = z-x
|
||||
end while
|
||||
y = y+1
|
||||
end while
|
||||
x = x shr 1
|
||||
end while
|
||||
|
||||
break
|
||||
end iterate
|
||||
end macro
|
||||
|
||||
include '../kernel32.inc'
|
214
toolchain/fasmg.kl0e/source/windows/dll/system.inc
Normal file
214
toolchain/fasmg.kl0e/source/windows/dll/system.inc
Normal file
@ -0,0 +1,214 @@
|
||||
|
||||
LINE_FEED equ 13,10
|
||||
|
||||
system_init:
|
||||
invoke HeapCreate,0,20000h,0
|
||||
mov [memory],eax
|
||||
test eax,eax
|
||||
jz out_of_memory
|
||||
invoke GetSystemTime,systemtime
|
||||
invoke SystemTimeToFileTime,systemtime,filetime
|
||||
mov ebx,[filetime.dwLowDateTime]
|
||||
mov eax,[filetime.dwHighDateTime]
|
||||
sub ebx,116444736000000000 and 0FFFFFFFFh
|
||||
sbb eax,116444736000000000 shr 32
|
||||
xor edx,edx
|
||||
mov ecx,10000000
|
||||
div ecx
|
||||
mov dword [timestamp+4],eax
|
||||
mov eax,ebx
|
||||
div ecx
|
||||
mov dword [timestamp],eax
|
||||
retn
|
||||
|
||||
system_shutdown:
|
||||
cmp [memory],0
|
||||
je memory_released
|
||||
invoke HeapDestroy,[memory]
|
||||
memory_released:
|
||||
retn
|
||||
|
||||
malloc:
|
||||
malloc_fixed:
|
||||
malloc_growable:
|
||||
; in: ecx = requested size
|
||||
; out: eax - allocated block, ecx = allocated size, on error jumps to out_of_memory (does not return)
|
||||
; preserves: ebx, esi, edi
|
||||
; note:
|
||||
; use of malloc_fixed hints that block will be kept as is until the end of assembly
|
||||
; use of malloc_growable hints that block is likely to be resized
|
||||
invoke HeapAlloc,[memory],0,ecx
|
||||
test eax,eax
|
||||
jz out_of_memory
|
||||
memory_allocated:
|
||||
push eax
|
||||
invoke HeapSize,[memory],0,eax
|
||||
mov ecx,eax
|
||||
pop eax
|
||||
cmp ecx,-1
|
||||
je out_of_memory
|
||||
retn
|
||||
realloc:
|
||||
; in: eax - memory block, ecx = requested size
|
||||
; out: eax - resized block, ecx = allocated size, on error jumps to out_of_memory (does not return)
|
||||
; preserves: ebx, esi, edi
|
||||
invoke HeapReAlloc,[memory],0,eax,ecx
|
||||
test eax,eax
|
||||
jnz memory_allocated
|
||||
jmp out_of_memory
|
||||
mfree:
|
||||
; in: eax - memory block
|
||||
; out: cf set on error
|
||||
; preserves: ebx, esi, edi
|
||||
; note: eax may have value 0 or -1, it should be treated as invalid input then
|
||||
test eax,eax
|
||||
jz interface_error
|
||||
cmp eax,-1
|
||||
je interface_error
|
||||
invoke HeapFree,[memory],0,eax
|
||||
test eax,eax
|
||||
jz interface_error
|
||||
clc
|
||||
retn
|
||||
interface_error:
|
||||
stc
|
||||
retn
|
||||
|
||||
open:
|
||||
; in: edx - path to file
|
||||
; out: ebx = file handle, cf set on error
|
||||
; preserves: esi, edi
|
||||
invoke CreateFile,edx,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0
|
||||
cmp eax,-1
|
||||
je interface_error
|
||||
mov ebx,eax
|
||||
clc
|
||||
retn
|
||||
create:
|
||||
; in: edx - path to file
|
||||
; out: ebx = file handle, cf set on error
|
||||
; preserves: esi, edi
|
||||
invoke CreateFile,edx,GENERIC_WRITE,0,0,CREATE_ALWAYS,0,0
|
||||
cmp eax,-1
|
||||
je interface_error
|
||||
mov ebx,eax
|
||||
clc
|
||||
retn
|
||||
write:
|
||||
; in: ebx = file handle, edx - data, ecx = number of bytes
|
||||
; out: cf set on error
|
||||
; preserves: ebx, esi, edi
|
||||
push ecx
|
||||
invoke WriteFile,ebx,edx,ecx,systmp,0
|
||||
pop ecx
|
||||
test eax,eax
|
||||
jz interface_error
|
||||
cmp ecx,[systmp]
|
||||
jne interface_error
|
||||
clc
|
||||
retn
|
||||
read:
|
||||
; in: ebx = file handle, edx - buffer, ecx = number of bytes
|
||||
; out: cf set on error
|
||||
; preserves: ebx, esi, edi
|
||||
push ecx
|
||||
invoke ReadFile,ebx,edx,ecx,systmp,0
|
||||
pop ecx
|
||||
test eax,eax
|
||||
jz interface_error
|
||||
cmp ecx,[systmp]
|
||||
jne interface_error
|
||||
clc
|
||||
retn
|
||||
close:
|
||||
; in: ebx = file handle
|
||||
; preserves: ebx, esi, edi
|
||||
invoke CloseHandle,ebx
|
||||
retn
|
||||
lseek:
|
||||
; in: ebx = file handle, cl = method, edx:eax = offset
|
||||
; out: edx:eax = new offset from the beginning of file, cf set on error
|
||||
; preserves: ebx, esi, edi
|
||||
movzx ecx,cl
|
||||
mov [systmp],edx
|
||||
invoke SetFilePointer,ebx,eax,systmp,ecx
|
||||
cmp eax,-1
|
||||
jne lseek_ok
|
||||
invoke GetLastError
|
||||
test eax,eax
|
||||
jnz interface_error
|
||||
not eax
|
||||
lseek_ok:
|
||||
mov edx,[systmp]
|
||||
clc
|
||||
retn
|
||||
|
||||
get_timestamp:
|
||||
; out: edx:eax = timestamp
|
||||
; preserves: ebx, ecx, esi, edi
|
||||
; note: during the passes of a single assembly this function should always return the same value
|
||||
mov eax,dword [timestamp]
|
||||
mov edx,dword [timestamp+4]
|
||||
retn
|
||||
|
||||
display_string:
|
||||
; in:
|
||||
; esi - string
|
||||
; ecx = string length, zero for ASCIIZ string
|
||||
; preserves: ebx, esi
|
||||
push ebx
|
||||
mov ebx,[stdout]
|
||||
jmp write_string
|
||||
display_error_string:
|
||||
; in:
|
||||
; esi - string
|
||||
; ecx = string length, zero for ASCIIZ string
|
||||
; preserves: ebx, esi
|
||||
push ebx
|
||||
mov ebx,[stderr]
|
||||
write_string:
|
||||
test ebx,ebx
|
||||
jz hidden_display
|
||||
test ecx,ecx
|
||||
jnz write_string_to_stdout
|
||||
xor al,al
|
||||
mov edi,esi
|
||||
or ecx,-1
|
||||
repne scasb
|
||||
neg ecx
|
||||
sub ecx,2
|
||||
write_string_to_stdout:
|
||||
mov edx,esi
|
||||
write_portion_to_stdout:
|
||||
mov eax,51200
|
||||
cmp ecx,eax
|
||||
jbe final_write_to_stdout
|
||||
sub ecx,eax
|
||||
add eax,edx
|
||||
push eax ecx
|
||||
invoke WriteFile,ebx,edx,51200,systmp,0
|
||||
pop ecx edx
|
||||
jmp write_portion_to_stdout
|
||||
final_write_to_stdout:
|
||||
invoke WriteFile,ebx,edx,ecx,systmp,0
|
||||
hidden_display:
|
||||
pop ebx
|
||||
retn
|
||||
|
||||
get_environment_variable:
|
||||
; in:
|
||||
; esi - name
|
||||
; edi - buffer for value
|
||||
; ecx = size of buffer
|
||||
; out:
|
||||
; eax = length of value
|
||||
; preserves: ebx, esi, edi
|
||||
push ecx
|
||||
invoke GetEnvironmentVariable,esi,edi,ecx
|
||||
pop ecx
|
||||
cmp eax,ecx
|
||||
jae environment_variable_ready
|
||||
mov byte [edi+eax],0
|
||||
environment_variable_ready:
|
||||
inc eax
|
||||
retn
|
529
toolchain/fasmg.kl0e/source/windows/fasmg.asm
Normal file
529
toolchain/fasmg.kl0e/source/windows/fasmg.asm
Normal file
@ -0,0 +1,529 @@
|
||||
|
||||
match ,{
|
||||
|
||||
include 'win32a.inc'
|
||||
|
||||
} match -,{
|
||||
else
|
||||
|
||||
include 'selfhost.inc'
|
||||
|
||||
end match
|
||||
_ equ }
|
||||
|
||||
|
||||
format PE large NX console 4.0
|
||||
entry start
|
||||
|
||||
include '../version.inc'
|
||||
|
||||
section '.text' code executable
|
||||
|
||||
include 'system.inc'
|
||||
|
||||
start:
|
||||
|
||||
call system_init
|
||||
|
||||
call get_arguments
|
||||
mov bl,al
|
||||
cmp [no_logo],0
|
||||
jne logo_ok
|
||||
mov esi,_logo
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
logo_ok:
|
||||
test bl,bl
|
||||
jnz display_usage_information
|
||||
|
||||
xor al,al
|
||||
movzx ecx,[verbosity_level]
|
||||
jecxz init
|
||||
or al,TRACE_ERROR_STACK
|
||||
dec ecx
|
||||
jz init
|
||||
or al,TRACE_DISPLAY
|
||||
init:
|
||||
call assembly_init
|
||||
|
||||
invoke GetTickCount
|
||||
mov [timer],eax
|
||||
|
||||
assemble:
|
||||
mov esi,[initial_commands]
|
||||
mov edx,[source_path]
|
||||
call assembly_pass
|
||||
jc assembly_done
|
||||
|
||||
mov eax,[current_pass]
|
||||
cmp eax,[maximum_number_of_passes]
|
||||
jb assemble
|
||||
|
||||
call show_display_data
|
||||
|
||||
mov esi,_error_prefix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,_code_cannot_be_generated
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,_message_suffix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
|
||||
jmp assembly_failed
|
||||
|
||||
assembly_done:
|
||||
|
||||
call show_display_data
|
||||
|
||||
cmp [first_error],0
|
||||
jne assembly_failed
|
||||
|
||||
cmp [no_logo],0
|
||||
jne summary_done
|
||||
mov eax,[current_pass]
|
||||
xor edx,edx
|
||||
call itoa
|
||||
call display_string
|
||||
mov esi,_passes
|
||||
cmp [current_pass],1
|
||||
jne display_passes_suffix
|
||||
mov esi,_pass
|
||||
display_passes_suffix:
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
invoke GetTickCount
|
||||
sub eax,[timer]
|
||||
xor edx,edx
|
||||
add eax,50
|
||||
mov ecx,1000
|
||||
div ecx
|
||||
mov ebx,eax
|
||||
mov eax,edx
|
||||
xor edx,edx
|
||||
mov ecx,100
|
||||
div ecx
|
||||
mov [timer],eax
|
||||
xchg eax,ebx
|
||||
or ebx,eax
|
||||
jz display_output_length
|
||||
xor edx,edx
|
||||
call itoa
|
||||
call display_string
|
||||
mov esi,_message_suffix
|
||||
mov ecx,1
|
||||
call display_string
|
||||
mov eax,[timer]
|
||||
xor edx,edx
|
||||
call itoa
|
||||
call display_string
|
||||
mov esi,_seconds
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
display_output_length:
|
||||
call get_output_length
|
||||
push eax edx
|
||||
call itoa
|
||||
call display_string
|
||||
pop edx eax
|
||||
mov esi,_bytes
|
||||
cmp eax,1
|
||||
jne display_bytes_suffix
|
||||
test edx,edx
|
||||
jnz display_bytes_suffix
|
||||
mov esi,_byte
|
||||
display_bytes_suffix:
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
mov esi,_new_line
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
summary_done:
|
||||
|
||||
mov ebx,[source_path]
|
||||
mov edi,[output_path]
|
||||
call write_output_file
|
||||
jc write_failed
|
||||
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
|
||||
invoke ExitProcess,0
|
||||
|
||||
assembly_failed:
|
||||
|
||||
call show_errors
|
||||
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
|
||||
invoke ExitProcess,2
|
||||
|
||||
write_failed:
|
||||
mov ebx,_write_failed
|
||||
jmp fatal_error
|
||||
|
||||
out_of_memory:
|
||||
mov ebx,_out_of_memory
|
||||
jmp fatal_error
|
||||
|
||||
fatal_error:
|
||||
|
||||
mov esi,_error_prefix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,ebx
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
mov esi,_message_suffix
|
||||
xor ecx,ecx
|
||||
call display_error_string
|
||||
|
||||
call assembly_shutdown
|
||||
call system_shutdown
|
||||
|
||||
invoke ExitProcess,3
|
||||
|
||||
display_usage_information:
|
||||
|
||||
mov esi,_usage
|
||||
xor ecx,ecx
|
||||
call display_string
|
||||
|
||||
call system_shutdown
|
||||
|
||||
invoke ExitProcess,1
|
||||
|
||||
get_arguments:
|
||||
xor eax,eax
|
||||
mov [initial_commands],eax
|
||||
mov [source_path],eax
|
||||
mov [output_path],eax
|
||||
mov [no_logo],al
|
||||
mov [verbosity_level],al
|
||||
mov [maximum_number_of_passes],100
|
||||
mov [maximum_number_of_errors],1
|
||||
mov [maximum_depth_of_stack],10000
|
||||
invoke GetCommandLine
|
||||
mov esi,eax
|
||||
mov edi,eax
|
||||
or ecx,-1
|
||||
xor al,al
|
||||
repne scasb
|
||||
sub edi,esi
|
||||
mov ecx,edi
|
||||
call malloc
|
||||
mov edi,eax
|
||||
get_argument:
|
||||
xor ah,ah
|
||||
read_character:
|
||||
lodsb
|
||||
test al,al
|
||||
jz no_more_arguments
|
||||
cmp al,22h
|
||||
je switch_quote
|
||||
cmp ax,20h
|
||||
je end_argument
|
||||
stosb
|
||||
jmp read_character
|
||||
end_argument:
|
||||
xor al,al
|
||||
stosb
|
||||
find_next_argument:
|
||||
mov al,[esi]
|
||||
test al,al
|
||||
jz no_more_arguments
|
||||
cmp al,20h
|
||||
jne next_argument_found
|
||||
inc esi
|
||||
jmp find_next_argument
|
||||
switch_quote:
|
||||
xor ah,1
|
||||
jmp read_character
|
||||
next_argument_found:
|
||||
cmp al,'-'
|
||||
je get_option
|
||||
cmp al,'/'
|
||||
je get_option
|
||||
cmp [source_path],0
|
||||
je get_source_path
|
||||
cmp [output_path],0
|
||||
je get_output_path
|
||||
error_in_arguments:
|
||||
or al,-1
|
||||
retn
|
||||
get_source_path:
|
||||
mov [source_path],edi
|
||||
jmp get_argument
|
||||
get_output_path:
|
||||
mov [output_path],edi
|
||||
jmp get_argument
|
||||
no_more_arguments:
|
||||
cmp [source_path],0
|
||||
je error_in_arguments
|
||||
xor al,al
|
||||
stosb
|
||||
retn
|
||||
get_option:
|
||||
inc esi
|
||||
lodsb
|
||||
cmp al,'e'
|
||||
je set_errors_limit
|
||||
cmp al,'E'
|
||||
je set_errors_limit
|
||||
cmp al,'i'
|
||||
je insert_initial_command
|
||||
cmp al,'I'
|
||||
je insert_initial_command
|
||||
cmp al,'p'
|
||||
je set_passes_limit
|
||||
cmp al,'P'
|
||||
je set_passes_limit
|
||||
cmp al,'r'
|
||||
je set_recursion_limit
|
||||
cmp al,'R'
|
||||
je set_recursion_limit
|
||||
cmp al,'v'
|
||||
je set_verbose_mode
|
||||
cmp al,'V'
|
||||
je set_verbose_mode
|
||||
cmp al,'n'
|
||||
je set_no_logo
|
||||
cmp al,'N'
|
||||
jne error_in_arguments
|
||||
set_no_logo:
|
||||
or [no_logo],-1
|
||||
mov al,[esi]
|
||||
cmp al,20h
|
||||
je find_next_argument
|
||||
test al,al
|
||||
jnz error_in_arguments
|
||||
jmp find_next_argument
|
||||
set_verbose_mode:
|
||||
call get_option_value
|
||||
jc error_in_arguments
|
||||
cmp edx,2
|
||||
ja error_in_arguments
|
||||
mov [verbosity_level],dl
|
||||
jmp find_next_argument
|
||||
set_errors_limit:
|
||||
call get_option_value
|
||||
jc error_in_arguments
|
||||
test edx,edx
|
||||
jz error_in_arguments
|
||||
mov [maximum_number_of_errors],edx
|
||||
jmp find_next_argument
|
||||
set_recursion_limit:
|
||||
call get_option_value
|
||||
jc error_in_arguments
|
||||
test edx,edx
|
||||
jz error_in_arguments
|
||||
mov [maximum_depth_of_stack],edx
|
||||
jmp find_next_argument
|
||||
set_passes_limit:
|
||||
call get_option_value
|
||||
jc error_in_arguments
|
||||
test edx,edx
|
||||
jz error_in_arguments
|
||||
mov [maximum_number_of_passes],edx
|
||||
jmp find_next_argument
|
||||
get_option_value:
|
||||
xor eax,eax
|
||||
mov edx,eax
|
||||
find_option_value:
|
||||
cmp byte [esi],20h
|
||||
jne get_option_digit
|
||||
inc esi
|
||||
jmp find_option_value
|
||||
get_option_digit:
|
||||
lodsb
|
||||
cmp al,20h
|
||||
je option_value_ok
|
||||
test al,al
|
||||
jz option_value_ok
|
||||
sub al,30h
|
||||
jc invalid_option_value
|
||||
cmp al,9
|
||||
ja invalid_option_value
|
||||
imul edx,10
|
||||
jo invalid_option_value
|
||||
add edx,eax
|
||||
jc invalid_option_value
|
||||
jmp get_option_digit
|
||||
option_value_ok:
|
||||
dec esi
|
||||
clc
|
||||
ret
|
||||
invalid_option_value:
|
||||
stc
|
||||
ret
|
||||
insert_initial_command:
|
||||
push edi
|
||||
find_command_segment:
|
||||
cmp byte [esi],20h
|
||||
jne command_segment_found
|
||||
inc esi
|
||||
jmp find_command_segment
|
||||
command_segment_found:
|
||||
xor ah,ah
|
||||
cmp byte [esi],22h
|
||||
jne measure_command_segment
|
||||
inc esi
|
||||
inc ah
|
||||
measure_command_segment:
|
||||
mov ebx,esi
|
||||
scan_command_segment:
|
||||
mov ecx,esi
|
||||
mov al,[esi]
|
||||
test al,al
|
||||
jz command_segment_measured
|
||||
cmp ax,20h
|
||||
je command_segment_measured
|
||||
cmp ax,22h
|
||||
je command_segment_measured
|
||||
inc esi
|
||||
cmp al,22h
|
||||
jne scan_command_segment
|
||||
command_segment_measured:
|
||||
sub ecx,ebx
|
||||
mov edi,[initial_commands]
|
||||
lea eax,[ecx+2]
|
||||
test edi,edi
|
||||
jz allocate_initial_commands_buffer
|
||||
mov edx,[initial_commands_length]
|
||||
add edi,edx
|
||||
add eax,edx
|
||||
cmp eax,[initial_commands_maximum_length]
|
||||
ja grow_initial_commands_buffer
|
||||
copy_initial_command:
|
||||
xchg esi,ebx
|
||||
rep movsb
|
||||
mov esi,ebx
|
||||
sub edi,[initial_commands]
|
||||
mov [initial_commands_length],edi
|
||||
mov al,[esi]
|
||||
test al,al
|
||||
jz initial_command_ready
|
||||
cmp al,20h
|
||||
jne command_segment_found
|
||||
initial_command_ready:
|
||||
mov edi,[initial_commands]
|
||||
add edi,[initial_commands_length]
|
||||
mov ax,0Ah
|
||||
stosw
|
||||
inc [initial_commands_length]
|
||||
pop edi
|
||||
jmp find_next_argument
|
||||
allocate_initial_commands_buffer:
|
||||
push ecx
|
||||
mov ecx,eax
|
||||
call malloc
|
||||
mov [initial_commands],eax
|
||||
mov [initial_commands_maximum_length],ecx
|
||||
mov edi,eax
|
||||
pop ecx
|
||||
jmp copy_initial_command
|
||||
grow_initial_commands_buffer:
|
||||
push ecx
|
||||
mov ecx,eax
|
||||
mov eax,[initial_commands]
|
||||
call realloc
|
||||
mov [initial_commands],eax
|
||||
mov [initial_commands_maximum_length],ecx
|
||||
mov edi,eax
|
||||
add edi,[initial_commands_length]
|
||||
pop ecx
|
||||
jmp copy_initial_command
|
||||
|
||||
include '../symbols.inc'
|
||||
include '../assembler.inc'
|
||||
include '../expressions.inc'
|
||||
include '../conditions.inc'
|
||||
include '../floats.inc'
|
||||
include '../directives.inc'
|
||||
include '../calm.inc'
|
||||
include '../errors.inc'
|
||||
include '../map.inc'
|
||||
include '../reader.inc'
|
||||
include '../output.inc'
|
||||
include '../console.inc'
|
||||
|
||||
section '.bss' readable writeable
|
||||
|
||||
include '../variables.inc'
|
||||
|
||||
source_path dd ?
|
||||
output_path dd ?
|
||||
maximum_number_of_passes dd ?
|
||||
|
||||
initial_commands dd ?
|
||||
initial_commands_length dd ?
|
||||
initial_commands_maximum_length dd ?
|
||||
|
||||
stdout dd ?
|
||||
stderr dd ?
|
||||
memory dd ?
|
||||
timestamp dq ?
|
||||
systemtime SYSTEMTIME
|
||||
filetime FILETIME
|
||||
systmp dd ?
|
||||
|
||||
timer dd ?
|
||||
verbosity_level db ?
|
||||
no_logo db ?
|
||||
|
||||
section '.rdata' data readable
|
||||
|
||||
data import
|
||||
|
||||
library kernel32,'KERNEL32.DLL'
|
||||
|
||||
import kernel32,\
|
||||
CloseHandle,'CloseHandle',\
|
||||
CreateFile,'CreateFileA',\
|
||||
ExitProcess,'ExitProcess',\
|
||||
GetCommandLine,'GetCommandLineA',\
|
||||
GetEnvironmentVariable,'GetEnvironmentVariableA',\
|
||||
GetStdHandle,'GetStdHandle',\
|
||||
GetSystemTime,'GetSystemTime',\
|
||||
GetTickCount,'GetTickCount',\
|
||||
HeapAlloc,'HeapAlloc',\
|
||||
HeapCreate,'HeapCreate',\
|
||||
HeapDestroy,'HeapDestroy',\
|
||||
HeapFree,'HeapFree',\
|
||||
HeapReAlloc,'HeapReAlloc',\
|
||||
HeapSize,'HeapSize',\
|
||||
ReadFile,'ReadFile',\
|
||||
SetFilePointer,'SetFilePointer',\
|
||||
SystemTimeToFileTime,'SystemTimeToFileTime',\
|
||||
WriteFile,'WriteFile',\
|
||||
GetLastError,'GetLastError'
|
||||
|
||||
end data
|
||||
|
||||
_logo db 'flat assembler version g.',VERSION,13,10,0
|
||||
|
||||
_usage db 'Usage: fasmg source [output]',13,10
|
||||
db 'Optional settings:',13,10
|
||||
db ' -e limit Set the maximum number of displayed errors (default 1)',13,10
|
||||
db ' -p limit Set the maximum allowed number of passes (default 100)',13,10
|
||||
db ' -r limit Set the maximum depth of the stack (default 10000)',13,10
|
||||
db ' -v flag Enable or disable showing all lines from the stack (default 0)',13,10
|
||||
db ' -i command Insert instruction at the beginning of source',13,10
|
||||
db ' -n Do not show logo nor summary',13,10
|
||||
db 0
|
||||
|
||||
_pass db ' pass, ',0
|
||||
_passes db ' passes, ',0
|
||||
_dot db '.'
|
||||
_seconds db ' seconds, ',0
|
||||
_byte db ' byte.',0
|
||||
_bytes db ' bytes.',0
|
||||
|
||||
_write_failed db 'failed to write the output file',0
|
||||
_out_of_memory db 'not enough memory to complete the assembly',0
|
||||
_code_cannot_be_generated db 'could not generate code within the allowed number of passes',0
|
||||
|
||||
include '../tables.inc'
|
||||
include '../messages.inc'
|
96
toolchain/fasmg.kl0e/source/windows/kernel32.inc
Normal file
96
toolchain/fasmg.kl0e/source/windows/kernel32.inc
Normal file
@ -0,0 +1,96 @@
|
||||
|
||||
struct FILETIME
|
||||
dwLowDateTime dd ?
|
||||
dwHighDateTime dd ?
|
||||
ends
|
||||
|
||||
struct SYSTEMTIME
|
||||
wYear dw ?
|
||||
wMonth dw ?
|
||||
wDayOfWeek dw ?
|
||||
wDay dw ?
|
||||
wHour dw ?
|
||||
wMinute dw ?
|
||||
wSecond dw ?
|
||||
wMilliseconds dw ?
|
||||
ends
|
||||
|
||||
; Page access flags
|
||||
|
||||
PAGE_NOACCESS = 001h
|
||||
PAGE_READONLY = 002h
|
||||
PAGE_READWRITE = 004h
|
||||
PAGE_WRITECOPY = 008h
|
||||
PAGE_EXECUTE = 010h
|
||||
PAGE_EXECUTE_READ = 020h
|
||||
PAGE_EXECUTE_READWRITE = 040h
|
||||
PAGE_EXECUTE_WRITECOPY = 080h
|
||||
PAGE_GUARD = 100h
|
||||
PAGE_NOCACHE = 200h
|
||||
|
||||
; Memory allocation flags
|
||||
|
||||
MEM_COMMIT = 001000h
|
||||
MEM_RESERVE = 002000h
|
||||
MEM_DECOMMIT = 004000h
|
||||
MEM_RELEASE = 008000h
|
||||
MEM_FREE = 010000h
|
||||
MEM_PRIVATE = 020000h
|
||||
MEM_MAPPED = 040000h
|
||||
MEM_RESET = 080000h
|
||||
MEM_TOP_DOWN = 100000h
|
||||
|
||||
; Heap allocation flags
|
||||
|
||||
HEAP_NO_SERIALIZE = 1
|
||||
HEAP_GENERATE_EXCEPTIONS = 4
|
||||
HEAP_ZERO_MEMORY = 8
|
||||
|
||||
; Device handles
|
||||
|
||||
INVALID_HANDLE_VALUE = -1
|
||||
STD_INPUT_HANDLE = -10
|
||||
STD_OUTPUT_HANDLE = -11
|
||||
STD_ERROR_HANDLE = -12
|
||||
|
||||
; Access rights
|
||||
|
||||
DELETE_RIGHT = 00010000h
|
||||
READ_CONTROL = 00020000h
|
||||
WRITE_DAC = 00040000h
|
||||
WRITE_OWNER = 00080000h
|
||||
SYNCHRONIZE = 00100000h
|
||||
STANDARD_RIGHTS_READ = READ_CONTROL
|
||||
STANDARD_RIGHTS_WRITE = READ_CONTROL
|
||||
STANDARD_RIGHTS_EXECUTE = READ_CONTROL
|
||||
STANDARD_RIGHTS_REQUIRED = 000F0000h
|
||||
STANDARD_RIGHTS_ALL = 001F0000h
|
||||
SPECIFIC_RIGHTS_ALL = 0000FFFFh
|
||||
ACCESS_SYSTEM_SECURITY = 01000000h
|
||||
MAXIMUM_ALLOWED = 02000000h
|
||||
GENERIC_READ = 80000000h
|
||||
GENERIC_WRITE = 40000000h
|
||||
GENERIC_EXECUTE = 20000000h
|
||||
GENERIC_ALL = 10000000h
|
||||
PROCESS_TERMINATE = 00000001h
|
||||
PROCESS_CREATE_THREAD = 00000002h
|
||||
PROCESS_VM_OPERATION = 00000008h
|
||||
PROCESS_VM_READ = 00000010h
|
||||
PROCESS_VM_WRITE = 00000020h
|
||||
PROCESS_DUP_HANDLE = 00000040h
|
||||
PROCESS_CREATE_PROCESS = 00000080h
|
||||
PROCESS_SET_QUOTA = 00000100h
|
||||
PROCESS_SET_INFORMATION = 00000200h
|
||||
PROCESS_QUERY_INFORMATION = 00000400h
|
||||
PROCESS_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED or SYNCHRONIZE or 0FFFh
|
||||
FILE_SHARE_READ = 00000001h
|
||||
FILE_SHARE_WRITE = 00000002h
|
||||
FILE_SHARE_DELETE = 00000004h
|
||||
|
||||
; CreateFile actions
|
||||
|
||||
CREATE_NEW = 1
|
||||
CREATE_ALWAYS = 2
|
||||
OPEN_EXISTING = 3
|
||||
OPEN_ALWAYS = 4
|
||||
TRUNCATE_EXISTING = 5
|
171
toolchain/fasmg.kl0e/source/windows/selfhost.inc
Normal file
171
toolchain/fasmg.kl0e/source/windows/selfhost.inc
Normal file
@ -0,0 +1,171 @@
|
||||
|
||||
include '../../examples/x86/include/80386.inc'
|
||||
|
||||
macro format?.PE? settings
|
||||
PE.Settings.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE or IMAGE_FILE_32BIT_MACHINE or IMAGE_FILE_LINE_NUMS_STRIPPED or IMAGE_FILE_LOCAL_SYMS_STRIPPED
|
||||
PE.Settings.DllCharacteristics = 0
|
||||
PE.Settings.Stamp = +VERSION
|
||||
local seq
|
||||
define seq settings:
|
||||
while 1
|
||||
match :, seq
|
||||
break
|
||||
else match =DLL? more, seq
|
||||
PE.Settings.Characteristics = PE.Settings.Characteristics or IMAGE_FILE_DLL
|
||||
redefine seq more
|
||||
else match =large? more, seq
|
||||
PE.Settings.Characteristics = PE.Settings.Characteristics or IMAGE_FILE_LARGE_ADDRESS_AWARE
|
||||
redefine seq more
|
||||
else match =WDM? more, seq
|
||||
PE.Settings.DllCharacteristics = PE.Settings.DllCharacteristics or IMAGE_DLLCHARACTERISTICS_WDM_DRIVER
|
||||
redefine seq more
|
||||
else match =NX? more, seq
|
||||
PE.Settings.DllCharacteristics = PE.Settings.DllCharacteristics or IMAGE_DLLCHARACTERISTICS_NX_COMPAT
|
||||
redefine seq more
|
||||
else match =at? base =on? stub :, seq
|
||||
PE.Settings.ImageBase = base
|
||||
PE.Settings.Stub = stub
|
||||
break
|
||||
else match =at? base :, seq
|
||||
PE.Settings.ImageBase = base
|
||||
break
|
||||
else match =on? stub :, seq
|
||||
PE.Settings.Stub = stub
|
||||
break
|
||||
else
|
||||
match =GUI? more, seq
|
||||
PE.Settings.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI
|
||||
redefine seq more
|
||||
else match =console? more, seq
|
||||
PE.Settings.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI
|
||||
redefine seq more
|
||||
else match =native? more, seq
|
||||
PE.Settings.Subsystem = IMAGE_SUBSYSTEM_NATIVE
|
||||
PE.Settings.SectionAlignment = 32
|
||||
PE.Settings.FileAlignment = 32
|
||||
redefine seq more
|
||||
else match =EFI? more, seq
|
||||
PE.Settings.Magic = 0x20B
|
||||
PE.Settings.Subsystem = IMAGE_SUBSYSTEM_EFI_APPLICATION
|
||||
redefine seq more
|
||||
else match =EFIboot? more, seq
|
||||
PE.Settings.Magic = 0x20B
|
||||
PE.Settings.Subsystem = IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
|
||||
redefine seq more
|
||||
else match =EFIruntime? more, seq
|
||||
PE.Settings.Magic = 0x20B
|
||||
PE.Settings.Subsystem = IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
|
||||
redefine seq more
|
||||
else
|
||||
err 'invalid argument'
|
||||
break
|
||||
end match
|
||||
match V.v more, seq
|
||||
PE.Settings.MajorSubsystemVersion = V
|
||||
PE.Settings.MinorSubsystemVersion = v
|
||||
redefine seq more
|
||||
end match
|
||||
end match
|
||||
end while
|
||||
if PE.Settings.Characteristics and IMAGE_FILE_DLL
|
||||
format binary as 'dll'
|
||||
else
|
||||
format binary as 'exe'
|
||||
end if
|
||||
include '../../examples/x86/include/format/pe.inc'
|
||||
use32
|
||||
end macro
|
||||
|
||||
macro struct? name
|
||||
macro ends?!
|
||||
end namespace
|
||||
esc end struc
|
||||
virtual at 0
|
||||
name name
|
||||
sizeof.name = $
|
||||
end virtual
|
||||
purge ends?
|
||||
end macro
|
||||
esc struc name
|
||||
label . : sizeof.name
|
||||
namespace .
|
||||
end macro
|
||||
|
||||
calminstruction invoke? proc*,args&
|
||||
local tmp, stack
|
||||
match , args
|
||||
jyes go
|
||||
collect:
|
||||
match tmp=,args, args
|
||||
take stack, tmp
|
||||
jyes collect
|
||||
push:
|
||||
arrange args, =pushd args
|
||||
assemble args
|
||||
take args, stack
|
||||
jyes push
|
||||
go:
|
||||
arrange proc, =call [proc]
|
||||
assemble proc
|
||||
end calminstruction
|
||||
|
||||
macro library? definitions&
|
||||
PE.Imports:
|
||||
iterate <name,string>, definitions
|
||||
if ~ name.redundant
|
||||
dd RVA name.lookup,0,0,RVA name.str,RVA name.address
|
||||
end if
|
||||
name.referred = 1
|
||||
end iterate
|
||||
dd 0,0,0,0,0
|
||||
iterate <name,string>, definitions
|
||||
if ~ name.redundant
|
||||
name.str db string,0
|
||||
align 2
|
||||
end if
|
||||
end iterate
|
||||
end macro
|
||||
|
||||
macro import? name,definitions&
|
||||
align 4
|
||||
if defined name.referred
|
||||
name.lookup:
|
||||
iterate <label,string>, definitions
|
||||
if used label
|
||||
if string eqtype ''
|
||||
dd RVA name.label
|
||||
else
|
||||
dd 80000000h + string
|
||||
end if
|
||||
end if
|
||||
end iterate
|
||||
if $ > name.lookup
|
||||
name.redundant = 0
|
||||
dd 0
|
||||
else
|
||||
name.redundant = 1
|
||||
end if
|
||||
name.address:
|
||||
iterate <label,string>, definitions
|
||||
if used label
|
||||
if string eqtype ''
|
||||
label dd RVA name.label
|
||||
else
|
||||
label dd 80000000h + string
|
||||
end if
|
||||
end if
|
||||
end iterate
|
||||
if ~ name.redundant
|
||||
dd 0
|
||||
end if
|
||||
iterate <label,string>, definitions
|
||||
if used label & string eqtype ''
|
||||
name.label dw 0
|
||||
db string,0
|
||||
align 2
|
||||
end if
|
||||
end iterate
|
||||
end if
|
||||
end macro
|
||||
|
||||
include 'kernel32.inc'
|
218
toolchain/fasmg.kl0e/source/windows/system.inc
Normal file
218
toolchain/fasmg.kl0e/source/windows/system.inc
Normal file
@ -0,0 +1,218 @@
|
||||
|
||||
LINE_FEED equ 13,10
|
||||
|
||||
system_init:
|
||||
invoke GetStdHandle,STD_OUTPUT_HANDLE
|
||||
mov [stdout],eax
|
||||
invoke GetStdHandle,STD_ERROR_HANDLE
|
||||
mov [stderr],eax
|
||||
invoke HeapCreate,0,20000h,0
|
||||
mov [memory],eax
|
||||
test eax,eax
|
||||
jz out_of_memory
|
||||
invoke GetSystemTime,systemtime
|
||||
invoke SystemTimeToFileTime,systemtime,filetime
|
||||
mov ebx,[filetime.dwLowDateTime]
|
||||
mov eax,[filetime.dwHighDateTime]
|
||||
sub ebx,116444736000000000 and 0FFFFFFFFh
|
||||
sbb eax,116444736000000000 shr 32
|
||||
xor edx,edx
|
||||
mov ecx,10000000
|
||||
div ecx
|
||||
mov dword [timestamp+4],eax
|
||||
mov eax,ebx
|
||||
div ecx
|
||||
mov dword [timestamp],eax
|
||||
retn
|
||||
|
||||
system_shutdown:
|
||||
cmp [memory],0
|
||||
je memory_released
|
||||
invoke HeapDestroy,[memory]
|
||||
memory_released:
|
||||
invoke CloseHandle,[stdout]
|
||||
invoke CloseHandle,[stderr]
|
||||
retn
|
||||
|
||||
malloc:
|
||||
malloc_fixed:
|
||||
malloc_growable:
|
||||
; in: ecx = requested size
|
||||
; out: eax - allocated block, ecx = allocated size, on error jumps to out_of_memory (does not return)
|
||||
; preserves: ebx, esi, edi
|
||||
; note:
|
||||
; use of malloc_fixed hints that block will be kept as is until the end of assembly
|
||||
; use of malloc_growable hints that block is likely to be resized
|
||||
invoke HeapAlloc,[memory],0,ecx
|
||||
test eax,eax
|
||||
jz out_of_memory
|
||||
memory_allocated:
|
||||
push eax
|
||||
invoke HeapSize,[memory],0,eax
|
||||
mov ecx,eax
|
||||
pop eax
|
||||
cmp ecx,-1
|
||||
je out_of_memory
|
||||
retn
|
||||
realloc:
|
||||
; in: eax - memory block, ecx = requested size
|
||||
; out: eax - resized block, ecx = allocated size, on error jumps to out_of_memory (does not return)
|
||||
; preserves: ebx, esi, edi
|
||||
invoke HeapReAlloc,[memory],0,eax,ecx
|
||||
test eax,eax
|
||||
jnz memory_allocated
|
||||
jmp out_of_memory
|
||||
mfree:
|
||||
; in: eax - memory block
|
||||
; out: cf set on error
|
||||
; preserves: ebx, esi, edi
|
||||
; note: eax may have value 0 or -1, it should be treated as invalid input then
|
||||
test eax,eax
|
||||
jz interface_error
|
||||
cmp eax,-1
|
||||
je interface_error
|
||||
invoke HeapFree,[memory],0,eax
|
||||
test eax,eax
|
||||
jz interface_error
|
||||
clc
|
||||
retn
|
||||
interface_error:
|
||||
stc
|
||||
retn
|
||||
|
||||
open:
|
||||
; in: edx - path to file
|
||||
; out: ebx = file handle, cf set on error
|
||||
; preserves: esi, edi
|
||||
invoke CreateFile,edx,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0
|
||||
cmp eax,-1
|
||||
je interface_error
|
||||
mov ebx,eax
|
||||
clc
|
||||
retn
|
||||
create:
|
||||
; in: edx - path to file
|
||||
; out: ebx = file handle, cf set on error
|
||||
; preserves: esi, edi
|
||||
invoke CreateFile,edx,GENERIC_WRITE,0,0,CREATE_ALWAYS,0,0
|
||||
cmp eax,-1
|
||||
je interface_error
|
||||
mov ebx,eax
|
||||
clc
|
||||
retn
|
||||
write:
|
||||
; in: ebx = file handle, edx - data, ecx = number of bytes
|
||||
; out: cf set on error
|
||||
; preserves: ebx, esi, edi
|
||||
push ecx
|
||||
invoke WriteFile,ebx,edx,ecx,systmp,0
|
||||
pop ecx
|
||||
test eax,eax
|
||||
jz interface_error
|
||||
cmp ecx,[systmp]
|
||||
jne interface_error
|
||||
clc
|
||||
retn
|
||||
read:
|
||||
; in: ebx = file handle, edx - buffer, ecx = number of bytes
|
||||
; out: cf set on error
|
||||
; preserves: ebx, esi, edi
|
||||
push ecx
|
||||
invoke ReadFile,ebx,edx,ecx,systmp,0
|
||||
pop ecx
|
||||
test eax,eax
|
||||
jz interface_error
|
||||
cmp ecx,[systmp]
|
||||
jne interface_error
|
||||
clc
|
||||
retn
|
||||
close:
|
||||
; in: ebx = file handle
|
||||
; preserves: ebx, esi, edi
|
||||
invoke CloseHandle,ebx
|
||||
retn
|
||||
lseek:
|
||||
; in: ebx = file handle, cl = method, edx:eax = offset
|
||||
; out: edx:eax = new offset from the beginning of file, cf set on error
|
||||
; preserves: ebx, esi, edi
|
||||
movzx ecx,cl
|
||||
mov [systmp],edx
|
||||
invoke SetFilePointer,ebx,eax,systmp,ecx
|
||||
cmp eax,-1
|
||||
jne lseek_ok
|
||||
invoke GetLastError
|
||||
test eax,eax
|
||||
jnz interface_error
|
||||
not eax
|
||||
lseek_ok:
|
||||
mov edx,[systmp]
|
||||
clc
|
||||
retn
|
||||
|
||||
get_timestamp:
|
||||
; out: edx:eax = timestamp
|
||||
; preserves: ebx, ecx, esi, edi
|
||||
; note: during the passes of a single assembly this function should always return the same value
|
||||
mov eax,dword [timestamp]
|
||||
mov edx,dword [timestamp+4]
|
||||
retn
|
||||
|
||||
display_string:
|
||||
; in:
|
||||
; esi - string
|
||||
; ecx = string length, zero for ASCIIZ string
|
||||
; preserves: ebx, esi
|
||||
push ebx
|
||||
mov ebx,[stdout]
|
||||
jmp write_string
|
||||
display_error_string:
|
||||
; in:
|
||||
; esi - string
|
||||
; ecx = string length, zero for ASCIIZ string
|
||||
; preserves: ebx, esi
|
||||
push ebx
|
||||
mov ebx,[stderr]
|
||||
write_string:
|
||||
test ecx,ecx
|
||||
jnz write_string_to_stdout
|
||||
xor al,al
|
||||
mov edi,esi
|
||||
or ecx,-1
|
||||
repne scasb
|
||||
neg ecx
|
||||
sub ecx,2
|
||||
write_string_to_stdout:
|
||||
mov edx,esi
|
||||
write_portion_to_stdout:
|
||||
mov eax,51200
|
||||
cmp ecx,eax
|
||||
jbe final_write_to_stdout
|
||||
sub ecx,eax
|
||||
add eax,edx
|
||||
push eax ecx
|
||||
invoke WriteFile,ebx,edx,51200,systmp,0
|
||||
pop ecx edx
|
||||
jmp write_portion_to_stdout
|
||||
final_write_to_stdout:
|
||||
invoke WriteFile,ebx,edx,ecx,systmp,0
|
||||
pop ebx
|
||||
retn
|
||||
|
||||
get_environment_variable:
|
||||
; in:
|
||||
; esi - name
|
||||
; edi - buffer for value
|
||||
; ecx = size of buffer
|
||||
; out:
|
||||
; eax = length of value
|
||||
; preserves: ebx, esi, edi
|
||||
push ecx
|
||||
invoke GetEnvironmentVariable,esi,edi,ecx
|
||||
pop ecx
|
||||
cmp eax,ecx
|
||||
jae environment_variable_ready
|
||||
mov byte [edi+eax],0
|
||||
environment_variable_ready:
|
||||
inc eax
|
||||
retn
|
||||
|
Reference in New Issue
Block a user