flat assembler
Message board for the users of flat assembler.
Index
> DOS > Enable unREAL by disabling AVX: fasm lite |
Author |
|
Tomasz Grysztar 28 Nov 2019, 18:55
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 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 it 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 |
|||
28 Nov 2019, 18:55 |
|
Tomasz Grysztar 29 Nov 2019, 06:53
The same machine code needs to run under DPMI with no segmentation, so no such tricks allowed.
|
|||
29 Nov 2019, 06:53 |
|
CandyMan 29 Nov 2019, 15:08
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 |
|||
29 Nov 2019, 15:08 |
|
Tomasz Grysztar 29 Nov 2019, 15:09
Yeah, but extender is not unREAL.
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). |
|||
29 Nov 2019, 15:09 |
|
guignol 31 Dec 2019, 00:54
just as I thought that Tomasz improved his English...
|
|||
31 Dec 2019, 00:54 |
|
bubach 13 Jul 2020, 01:40
I stumbled onto this text file while roaming some dark forgotten corners of the web - which might be of some interest.
http://dgi_il.tripod.com/gemmis.txt If I'm not confusing the issues here, the services mentioned goes under the name DOSX - or "Windows Global EMM Import Specification" & "Windows/386 Paging Import Specification". Relevant calls listed: Code: Windows Memory Manager (a) INT 2Fh AX=1605h Set device name to "EMMXXXX0". Return mode-switch entry-point address. IOCTL-read "EMMXXXX0" Return physical address of EMM import structure. Call mode-switch entry-point (AX=0) Set CPU to real mode. Windows runs_ (b) Set CPU to real mode Call mode-switch entry-point (AX=1) Setup the EMM import structure. Regain protected mode. INT 2Fh AX=1606h Restore device name. And full C listing with example usage Code: /* dumping the EMM import structure */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <dos.h> #include <io.h> #include <fcntl.h> #include "emmimp.h" #include "moveext.h" #ifndef __TURBOC__ #define asm _asm #endif static int for_386max = 0; static int raw_dump = 0; static int machine; static void emulate_win_init(uint16 ver, void (far **entryp)(void)) { void (far *entry)(void); asm push ds asm push es asm mov dx, 0 asm mov ax, 0 asm mov es, ax asm mov ds, ax asm mov di, ver asm mov si, 0 asm mov cx, 0 asm mov bx, 0 asm mov ax, 1605h asm int 2fh asm mov word ptr entry, si asm mov word ptr entry + 2, ds asm pop es asm pop ds *entryp = entry; } static void emulate_win_term(void) { asm mov ax, 1606h asm int 2fh } static uint32 get_emm_imp_addr(void) { uint8 buf[6]; int fd; fd = open("EMMXXXX0", O_RDONLY | O_BINARY); if (fd < 0) { printf("can't open EMMXXXX0\n"); return 0; } memset(buf, 0, sizeof buf); buf[0] = 1; asm lea dx, word ptr buf asm mov cx, 6 asm mov bx, fd asm mov ax, 4402h asm int 21h asm jc fail printf("emm import structure address:%08lx\n", *(uint32 *) buf); printf("emm import structure version:%d.%02d\n", buf[4], buf[5]); close(fd); return *(uint32 *) buf; fail: printf("emm import struct address get failed\n"); close(fd); return 0; } static void switch_to_real(void (far *entry)(void)) { asm push ds asm push es asm push di asm push si asm push bp asm mov ax, 0 asm call dword ptr entry; asm pop bp asm pop si asm pop di asm pop es asm pop ds } static void switch_to_prot(void (far *entry)(void)) { asm push ds asm push es asm push di asm push si asm push bp asm mov ax, 1 asm call dword ptr entry; asm pop bp asm pop si asm pop di asm pop es asm pop ds } static uint16 winver = 0x30a; /* Windows version */ main(int ac, uint8 **av) { void (far *entry)(void); int i; uint32 emm_imp_addr; static uint8 buf[8192]; get_options(ac, av); // not shown if (!for_386max) machine = machine_type(); emulate_win_init(winver, &entry); if (!entry) { printf("illegal mode switch entry\n"); emulate_win_term(); return 1; } printf("mode switch entry:%08lx\n", entry); emm_imp_addr = get_emm_imp_addr(); if (!emm_imp_addr) { emulate_win_term(); return 1; } if (!for_386max) { disable(); /* disable interrupts while in real mode */ switch_to_real(entry); switch_to_prot(entry); enable(); /* now Ok to enable interrupts */ emulate_win_term(); if (machine == MC_98) move_ext_mem_98(emm_imp_addr, buf, sizeof buf); else move_ext_mem_pc(emm_imp_addr, buf, sizeof buf); dump_emm_imp(emm_imp_addr, buf); } else { disable(); switch_to_real(entry); move_ext_mem_real(emm_imp_addr, buf, sizeof buf); switch_to_prot(entry); enable(); emulate_win_term(); dump_emm_imp(emm_imp_addr, buf); } return 0; } Perhaps there's even more to it, hidden interrupts and whatnot. Interesting stuff either way.
|
|||||||||||||||||||||
13 Jul 2020, 01:40 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.