flat assembler
Message board for the users of flat assembler.

Index > DOS > Enable unREAL by disabling AVX: fasm lite

Author
Thread Post new topic Reply to topic
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 7489
Location: Kraków, Poland
Tomasz Grysztar
It has been a tradition for the DOS version of fasm to use unREAL mode when possible (with DPMI as only a safety fall-back). This, however, required code segment to fit in 65536 bytes, and it fasm has broken that barrier a long time ago.

My temporary solution was to split the code into two segments, one for preprocessor stage and one for the main assembly stage. They share some of the code, thus the segments overlap, with the code needed in both stages being placed in the middle (and addressed only through relative jumps that work correctly in either segment).

But still finally stopped being enough in the 1.73 line. With the introduction of AVX-512 extensions the code of the assembly stage grew so much that it is no longer possible to fit it into that second segment. This switched a condition in the source text that causes the fasm to start relying exclusively on DPMI and the unREAL code is no longer there.

Therefore the only available option to get latest fasm working in unREAL mode is to remove some features. And since AVX family of extensions is the main offender, and AVX is not easily usable in DOS anyway, I have prepared a "lite" version for DOS, which does not include AVX.INC and removes the AVX-related entries from the tables with help of a few strategically placed macros:
Code:
; flat assembler lite interface for DOS
; Copyright (c) 1999-2019, Tomasz Grysztar.
; All rights reserved.

        format  MZ
        heap    0
        stack   8000h
        entry   main:start

include 'modes.inc'

segment main use16

start:

        mov     ax,ds
        mov     dx,[2Ch]
        push    cs cs
        pop     ds es
        mov     [psp_segment],ax
        mov     [environment_segment],dx

        mov     dx,_logo
        mov     ah,9
        int     21h

        cld

        call    go32
        use32

        call    get_params
        jc      information

        call    init_memory

        mov     esi,_memory_prefix
        call    display_string
        mov     eax,[memory_end]
        sub     eax,[memory_start]
        add     eax,[additional_memory_end]
        sub     eax,[additional_memory]
        shr     eax,10
        call    display_number
        mov     esi,_memory_suffix
        call    display_string

        xor     ah,ah
        int     1Ah
        mov     ax,cx
        shl     eax,16
        mov     ax,dx
        mov     [start_time],eax

        cmp     [mode],dpmi
        je      compile
        jmp     main+(first_segment shr 4):first_gate-first_segment

compile:
        and     [preprocessing_done],0
        call    preprocessor
        or      [preprocessing_done],-1
        call    parser
        call    assembler
        call    formatter

finish:
        call    display_user_messages
        movzx   eax,[current_pass]
        inc     eax
        call    display_number
        mov     esi,_passes_suffix
        call    display_string
        xor     ah,ah
        int     1Ah
        mov     ax,cx
        shl     eax,16
        mov     ax,dx
        sub     eax,[start_time]
        mov     ebx,100
        mul     ebx
        mov     ebx,182
        div     ebx
        or      eax,eax
        jz      display_bytes_count
        xor     edx,edx
        mov     ebx,10
        div     ebx
        push    edx
        call    display_number
        mov     ah,2
        mov     dl,'.'
        int     21h
        pop     eax
        call    display_number
        mov     esi,_seconds_suffix
        call    display_string
      display_bytes_count:
        mov     eax,[written_size]
        call    display_number
        mov     esi,_bytes_suffix
        call    display_string
        xor     al,al
        jmp     exit_program

information:
        mov     esi,_usage
        call    display_string
        mov     al,1
        jmp     exit_program

get_params:
        mov     [input_file],0
        mov     [output_file],0
        mov     [symbols_file],0
        mov     [memory_setting],0
        mov     [passes_limit],100
        mov     [definitions_pointer],predefinitions
        push    ds
        mov     ds,[psp_segment]
        mov     esi,81h
        mov     edi,params
    find_param:
        lodsb
        cmp     al,20h
        je      find_param
        cmp     al,'-'
        je      option_param
        cmp     al,0Dh
        je      all_params
        or      al,al
        jz      all_params
        cmp     [es:input_file],0
        jne     get_output_file
        mov     [es:input_file],edi
        jmp     process_param
      get_output_file:
        cmp     [es:output_file],0
        jne     bad_params
        mov     [es:output_file],edi
    process_param:
        cmp     al,22h
        je      string_param
    copy_param:
        stosb
        lodsb
        cmp     al,20h
        je      param_end
        cmp     al,0Dh
        je      param_end
        or      al,al
        jz      param_end
        jmp     copy_param
    string_param:
        lodsb
        cmp     al,22h
        je      string_param_end
        cmp     al,0Dh
        je      param_end
        or      al,al
        jz      param_end
        stosb
        jmp     string_param
    option_param:
        lodsb
        cmp     al,'m'
        je      memory_option
        cmp     al,'M'
        je      memory_option
        cmp     al,'p'
        je      passes_option
        cmp     al,'P'
        je      passes_option
        cmp     al,'d'
        je      definition_option
        cmp     al,'D'
        je      definition_option
        cmp     al,'s'
        je      symbols_option
        cmp     al,'S'
        je      symbols_option
    invalid_option:
        pop     ds
        stc
        ret
    get_option_value:
        xor     eax,eax
        mov     edx,eax
    get_option_digit:
        lodsb
        cmp     al,20h
        je      option_value_ok
        cmp     al,0Dh
        je      option_value_ok
        or      al,al
        jz      option_value_ok
        sub     al,30h
        jc      bad_params_value
        cmp     al,9
        ja      bad_params_value
        imul    edx,10
        jo      bad_params_value
        add     edx,eax
        jc      bad_params_value
        jmp     get_option_digit
    option_value_ok:
        dec     esi
        clc
        ret
    bad_params_value:
        stc
        ret
    memory_option:
        lodsb
        cmp     al,20h
        je      memory_option
        cmp     al,0Dh
        je      invalid_option
        or      al,al
        jz      invalid_option
        dec     esi
        call    get_option_value
        jc      invalid_option
        or      edx,edx
        jz      invalid_option
        cmp     edx,1 shl (32-10)
        jae     invalid_option
        mov     [es:memory_setting],edx
        jmp     find_param
    passes_option:
        lodsb
        cmp     al,20h
        je      passes_option
        cmp     al,0Dh
        je      invalid_option
        or      al,al
        jz      invalid_option
        dec     esi
        call    get_option_value
        jc      bad_params
        or      edx,edx
        jz      invalid_option
        cmp     edx,10000h
        ja      invalid_option
        mov     [es:passes_limit],dx
        jmp     find_param
    definition_option:
        lodsb
        cmp     al,20h
        je      definition_option
        cmp     al,0Dh
        je      bad_params
        or      al,al
        jz      bad_params
        dec     esi
        push    edi
        mov     edi,[es:definitions_pointer]
        call    convert_definition_option
        mov     [es:definitions_pointer],edi
        pop     edi
        jc      invalid_option
        jmp     find_param
    symbols_option:
        mov     [es:symbols_file],edi
      find_symbols_file_name:
        lodsb
        cmp     al,20h
        jne     process_param
        jmp     find_symbols_file_name
    param_end:
        dec     esi
    string_param_end:
        xor     al,al
        stosb
        jmp     find_param
    all_params:
        xor     al,al
        stosb
        pop     ds
        cmp     [input_file],0
        je      no_input_file
        mov     eax,[definitions_pointer]
        mov     byte [eax],0
        mov     [initial_definitions],predefinitions
        clc
        ret
    bad_params:
        pop     ds
    no_input_file:
        stc
        ret
    convert_definition_option:
        mov     ecx,edi
        xor     al,al
        stosb
      copy_definition_name:
        lodsb
        cmp     al,'='
        je      copy_definition_value
        cmp     al,20h
        je      bad_definition_option
        cmp     al,0Dh
        je      bad_definition_option
        or      al,al
        jz      bad_definition_option
        stosb
        inc     byte [es:ecx]
        jnz     copy_definition_name
      bad_definition_option:
        stc
        ret
      copy_definition_value:
        lodsb
        cmp     al,20h
        je      definition_value_end
        cmp     al,0Dh
        je      definition_value_end
        or      al,al
        jz      definition_value_end
        cmp     al,'\'
        jne     definition_value_character
        cmp     byte [esi],20h
        jne     definition_value_character
        lodsb
      definition_value_character:
        stosb
        jmp     copy_definition_value
      definition_value_end:
        dec     esi
        xor     al,al
        stosb
        clc
        ret

include '..\version.inc'

_logo db 'flat assembler  version ',VERSION_STRING,' lite',24h
_copyright db 'Copyright (c) 1999-2019, Tomasz Grysztar',0Dh,0Ah,0

_usage db 0Dh,0Ah
       db 'usage: fasm <source> [output]',0Dh,0Ah
       db 'optional settings:',0Dh,0Ah
       db ' -m <limit>         set the limit in kilobytes for the available memory',0Dh,0Ah
       db ' -p <limit>         set the maximum allowed number of passes',0Dh,0Ah
       db ' -d <name>=<value>  define symbolic variable',0Dh,0Ah
       db ' -s <file>          dump symbolic information for debugging',0Dh,0Ah
       db 0
_memory_prefix db '  (',0
_memory_suffix db ' kilobytes memory)',0Dh,0Ah,0
_passes_suffix db ' passes, ',0
_seconds_suffix db ' seconds, ',0
_bytes_suffix db ' bytes.',0Dh,0Ah,0

error_prefix db 'error: ',0
error_suffix db '.'
cr_lf db 0Dh,0Ah,0
line_number_start db ' [',0
line_data_start db ':',0Dh,0Ah,0
preprocessed_instruction_prefix db 'processed: ',0

include 'dpmi.inc'

align 16
first_segment:

include '..\preproce.inc'
include '..\parser.inc'
include '..\exprpars.inc'

align 16
second_segment:

include '..\exprcalc.inc'
include '..\errors.inc'
include '..\symbdump.inc'

include 'system.inc'

first_gate:
        and     [preprocessing_done],0
        call    preprocessor
        or      [preprocessing_done],-1
        call    parser
        jmp     main+(second_segment shr 4):second_gate-second_segment
first_segment_top = $ - first_segment

store_vex_instruction_code equ illegal_instruction

include '..\assemble.inc'
include '..\formats.inc'
include '..\x86_64.inc'

second_gate:
        call    assembler
        call    formatter
        jmp     main:finish

second_segment_top = $ - second_segment

if first_segment_top>=10000h | second_segment_top>=10000h
 if UNREAL_ENABLED>0
  UNREAL_ENABLED = -1
 else
  UNREAL_ENABLED = 0
 end if
else
 if UNREAL_ENABLED<0
  UNREAL_ENABLED = -1
 else
  UNREAL_ENABLED = 1
 end if
end if

macro db values&
{
        local CUT
        define __CUT CUT
        match name=,class=,id, values
        \{
                if name eqtype 'ax'
                        if class = 1Fh | ( class = 10h & ( id and 0F0h > 0C0h | id and 0E0h = 60h) )
                                __CUT = 1
                        end if
                end if
        \}
        if ~ defined __CUT
                db values
        end if
}
macro dw values&
{
        if values eqtype basic_instruction-instruction_handler & ~ defined values
                __CUT = 1
        else
                dw values
        end if
}

include '..\tables.inc'

purge db,dw

include '..\messages.inc'

align 4

include '..\variable.inc'

memory_setting dd ?
start_time dd ?
definitions_pointer dd ?
params rb 100h
predefinitions rb 100h

mode dw ?
real_mode_segment dw ?
displayed_count dd ?
last_displayed rb 2
preprocessing_done db ?

segment buffer

rb 1000h

assert first_segment_top<10000h & second_segment_top<10000h

macro display_hex value,bits
{
    repeat bits/4
        d = '0' + value shr (bits-%*4) and 0Fh
        if d > '9'
            d = d + 'A'-'9'-1
        end if
        display d
    end repeat
}

display 'first segment: '
display_hex first_segment_top,20
display 13,10,'second segment: '
display_hex second_segment_top,20
display 13,10    
Should I include it in the official DOS package? Smile
Post 28 Nov 2019, 18:55
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 16890
Location: In your JS exploiting you and your system
revolution
Would it be possible to make call and jmp macros to generate near or far addresses automatically? Then the code could be any size.

Maybe Jcc would be tricky, but it can be converted into a Jncc/jmp combo.
Post 28 Nov 2019, 22:07
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 7489
Location: Kraków, Poland
Tomasz Grysztar
The same machine code needs to run under DPMI with no segmentation, so no such tricks allowed.
Post 29 Nov 2019, 06:53
View user's profile Send private message Visit poster's website Reply with quote
CandyMan



Joined: 04 Sep 2009
Posts: 301
Location: film "CandyMan" directed through Bernard Rose OR Candy Shop
CandyMan
I've been using my own version with d3x dos extender for a long time.

You can download it from here:
https://board.flatassembler.net/topic.php?p=145936#145936

_________________
smaller is better
Post 29 Nov 2019, 15:08
View user's profile Send private message Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 7489
Location: Kraków, Poland
Tomasz Grysztar
Yeah, but extender is not unREAL. Wink

To run fasm in protected mode my official recommendation is HX extender. It works great, and even gives you ability to run Win32 console versions of fasm and fasmg in DOS (this is how I run fasmg on my DOS machine; though I also have another option in Win32s).
Post 29 Nov 2019, 15:09
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2019, Tomasz Grysztar.

Powered by rwasa.