I see that the CPU is capable of automatically selecting the size of full sized machine words, instructions and registers.
But I also see that NASM lacks the capability to allow selecting automatically-sized code and data.
The assembly language that NASM supports should be extended for handling it. I've tested it with a macros file and existing code won't be affected. It's fully transparent as it's supposed to simply add the capability to use automatically-sized code and data.
The immediate result would be that it would be possible to write one single assembly source code version that could be directly recompiled for 16, 32 and 64-bit modes, as well as for standard 16-bit Unreal Mode, as long as automatically-mode-selecting instructions can be ported to all modes, which uses to be the case for user-level programs.
So I have created a macro file called "x86 Portable":
00000000__x86_Portable.asmIt allows support for things like:
;v2017-08-08
;;;;INIT: Documentation
;;;;INIT: Documentation
;;;;INIT: Documentation
;;;;INIT: Documentation
;;;;INIT: Documentation
;;;;INIT: Documentation
;;;;INIT: Documentation
;;;;INIT: Documentation
;Automatic size selection for data/variables:
;-------------------------------------------------------------------------
;wideword -- Automatic size selection, 2, 4 or 8 bytes.
;ww -- Automatic size selection, define wideword, 2, 4 or 8 bytes.
;wideword_SZ -- Automatic size selection, 2, 4 or 8 bytes.
;Automatic size selection for any on-stack call return addresses:
;-------------------------------------------------------------------------
;_CALL_STACK_ADDR_SZ_ -- 2, 4 or 8 bytes.
;Automatic size selection for CPU registers:
;-------------------------------------------------------------------------
;wideax -- 2, 4 or 8 bytes.
;widebx -- 2, 4 or 8 bytes.
;widecx -- 2, 4 or 8 bytes.
;widedx -- 2, 4 or 8 bytes.
;widesi -- 2, 4 or 8 bytes.
;widedi -- 2, 4 or 8 bytes.
;widesp -- 2, 4 or 8 bytes.
;widebp -- 2, 4 or 8 bytes.
;Automatic size selection for "Address" and "Operand" prefixes:
;-------------------------------------------------------------------------
;awide -- a16, a32 or nothing.
;owide -- a16, a32 or nothing.
;Automatic size selection for CPU instructions:
;-------------------------------------------------------------------------
;cmpswide -- 2, 4 or 8 bytes.
;lodswide -- 2, 4 or 8 bytes.
;stoswide -- 2, 4 or 8 bytes.
;movswide -- 2, 4 or 8 bytes.
;inswide -- 2 or 4 bytes.
;outswide -- 2 or 4 bytes.
;retwide -- 2, 4 or 8 byte POPs for return addresses.
;iretwide -- 2, 4 or 8 byte POPs for return addresses.
;Automatic variable or register selection for 64-bit CPU r8-r9 registers:
;-------------------------------------------------------------------------
;_r8 -- 2, 4 or 8 bytes.
;_r9 -- 2, 4 or 8 bytes.
;_r10 -- 2, 4 or 8 bytes.
;_r11 -- 2, 4 or 8 bytes.
;_r12 -- 2, 4 or 8 bytes.
;_r13 -- 2, 4 or 8 bytes.
;_r14 -- 2, 4 or 8 bytes.
;_r15 -- 2, 4 or 8 bytes.
;;;;END: Documentation
;;;;END: Documentation
;;;;END: Documentation
;;;;END: Documentation
;;;;END: Documentation
;;;;END: Documentation
;;;;END: Documentation
;;;;END: Documentation
;The reason why we don't use numbers like 8086 for 16-bit code
;and 386 for 32-bit code is that this source file is size-oriented
;and we want to indicate the actual machine word size, not just
;the base CPU.
;
;Indicating the CPU as a number might work and be better when we are
;dealing with CPU-oriented code. The fact of naming the CPUs with numbers
;was a very optimizing thinking from people at Intel, so CPUs can be
;directly identified and named in the CPU instructions themselves
;and in software by defining pure numbers.
;
;Set the default mode of x86 Portable to work under
;16-bit Unreal Mode (with access to 4 GB of address space):
;;
%ifndef _x86_Portable__PLATFORMBITS_
%ixdefine _x86_Portable__PLATFORMBITS_ 1632
%endif
x86_Portable_START:
;Include a JMP instruction so that we can include this source file
;anywhere in a NASM/YASM assembly source code without causing failures
;due to the embedded data bytes here:
;;
align 16
jmp x86_Portable_END
align 16
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
%if _x86_Portable__PLATFORMBITS_==16 ;16-bit 8086 code
%ixdefine _CALL_STACK_ADDR_SZ_ 2
%ixdefine wideword word
%ixdefine ww dw
%ixdefine wideword_SZ 2
%ixdefine wideword_SZ_BitRotationMultiply 1
%ixdefine wideax ax
%ixdefine widecx cx
%ixdefine widedx dx
%ixdefine widebx bx
%ixdefine widesp sp
%ixdefine widebp bp
%ixdefine widesi si
%ixdefine widedi di
%ixdefine _r8 word[__r8]
%ixdefine _r9 word[__r9]
%ixdefine _r10 word[__r10]
%ixdefine _r11 word[__r11]
%ixdefine _r12 word[__r12]
%ixdefine _r13 word[__r13]
%ixdefine _r14 word[__r14]
%ixdefine _r15 word[__r15]
__r8 dw 0
__r9 dw 0
__r10 dw 0
__r11 dw 0
__r12 dw 0
__r13 dw 0
__r14 dw 0
__r15 dw 0
%ixdefine awide
%ixdefine owide
%ixdefine cmpswide cmpsw
%ixdefine lodswide lodsw
%ixdefine stoswide stosw
%ixdefine movswide movsw
%ixdefine inswide insw
%ixdefine outswide outsw
%ixdefine retwide ret
%ixdefine iretwide iret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
%elif _x86_Portable__PLATFORMBITS_==1632 ;16-bit Unreal Mode
%ixdefine _CALL_STACK_ADDR_SZ_ 2
%ixdefine wideword dword
%ixdefine ww dd
%ixdefine wideword_SZ 4
%ixdefine wideword_SZ_BitRotationMultiply 2
%ixdefine wideax eax
%ixdefine widecx ecx
%ixdefine widedx edx
%ixdefine widebx ebx
%ixdefine widesp esp
%ixdefine widebp ebp
%ixdefine widesi esi
%ixdefine widedi edi
%ixdefine _r8 dword[__r8]
%ixdefine _r9 dword[__r9]
%ixdefine _r10 dword[__r10]
%ixdefine _r11 dword[__r11]
%ixdefine _r12 dword[__r12]
%ixdefine _r13 dword[__r13]
%ixdefine _r14 dword[__r14]
%ixdefine _r15 dword[__r15]
__r8 dd 0
__r9 dd 0
__r10 dd 0
__r11 dd 0
__r12 dd 0
__r13 dd 0
__r14 dd 0
__r15 dd 0
%ixdefine awide a32
%ixdefine owide o32
%ixdefine cmpswide cmpsd
%ixdefine lodswide lodsd
%ixdefine stoswide stosd
%ixdefine movswide movsd
%ixdefine inswide insd
%ixdefine outswide outsd
%ixdefine retwide ret
%ixdefine iretwide iret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
%elif _x86_Portable__PLATFORMBITS_==32 ;32 bit x86 Protected Mode code
%ixdefine _CALL_STACK_ADDR_SZ_ 4
%ixdefine wideword dword
%ixdefine ww dd
%ixdefine wideword_SZ 4
%ixdefine wideword_SZ_BitRotationMultiply 2
%ixdefine wideax eax
%ixdefine widecx ecx
%ixdefine widedx edx
%ixdefine widebx ebx
%ixdefine widesp esp
%ixdefine widebp ebp
%ixdefine widesi esi
%ixdefine widedi edi
%ixdefine _r8 dword[__r8]
%ixdefine _r9 dword[__r9]
%ixdefine _r10 dword[__r10]
%ixdefine _r11 dword[__r11]
%ixdefine _r12 dword[__r12]
%ixdefine _r13 dword[__r13]
%ixdefine _r14 dword[__r14]
%ixdefine _r15 dword[__r15]
__r8 dd 0
__r9 dd 0
__r10 dd 0
__r11 dd 0
__r12 dd 0
__r13 dd 0
__r14 dd 0
__r15 dd 0
%ixdefine awide
%ixdefine owide
%ixdefine cmpswide cmpsd
%ixdefine lodswide lodsd
%ixdefine stoswide stosd
%ixdefine movswide movsd
%ixdefine inswide insd
%ixdefine outswide outsd
%ixdefine retwide ret
%ixdefine iretwide iret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
%elif _x86_Portable__PLATFORMBITS_==64 ;64-bit Long Mode code
%ixdefine _CALL_STACK_ADDR_SZ_ 8
%ixdefine wideword qword
%ixdefine ww dq
%ixdefine wideword_SZ 8
%ixdefine wideword_SZ_BitRotationMultiply 3
%ixdefine wideax rax
%ixdefine widecx rcx
%ixdefine widedx rdx
%ixdefine widebx rbx
%ixdefine widesp rsp
%ixdefine widebp rbp
%ixdefine widesi rsi
%ixdefine widedi rdi
%ixdefine _r8 r8
%ixdefine _r9 r9
%ixdefine _r10 r10
%ixdefine _r11 r11
%ixdefine _r12 r12
%ixdefine _r13 r13
%ixdefine _r14 r14
%ixdefine _r15 r15
%ixdefine awide
%ixdefine owide
%ixdefine cmpswide cmpsq
%ixdefine lodswide lodsq
%ixdefine stoswide stosq
%ixdefine movswide movsq
%ixdefine inswide insd
%ixdefine outswide outsd
%ixdefine retwide retq
%ixdefine iretwide iretq
%endif
align 16
x86_Portable_END:
;EOF
r8 to r15 are defined as WIDEWORDs if the current CPU mode doesn't have those Long Mode registers.
I will post examples of what can be done with it here later, I already have them as working code.
A macros file like this works great, but adding it to NASM itself would turn x86 Intel sytax assembly language into a low level language with nearly the same degree of code portability and reusability than C. I've proven it to myself. This is all NASM and Intel syntax x86 assembly language need to have added to improve them considerably.