Sorry if this has been discussed before on this board, I have vague recollection of it appearing somewhere but I can't find it.
Anyhow, this has been bugging me for the last few days. Consider the following code:
use32
mov al,[esp+esi] ;Okay
mov al,[esi+esp] ;Error: invalid address
I know that this is currently a deliberate decision to disallow ESP as the second register but it has been causing me many problems.
The reason is that when variables are declared inside virtual blocks or with EQU's the original register name can become unknown to the programmer. eg.
virtual at esp
.var db ?
end virtual
reg2 equ esi
... ;lots of intervening space or different included file
mov al,[.var+reg2] ;Okay
mov al,[reg2+.var] ;Error: invalid address
Sometimes when using macros/included files/EQU's together there can be mutually exclusive situations where manually switching the registers cannot solve the problem.
As a support reason for such a change to FASM to be made I notice that the base/index switching is already happening in 16bit code:
use16
mov al,[bx+si] ;Okay
mov al,[si+bx] ;Okay
For the meantime to help both me and my colleagues to solve this difficulty I have effected the following addition to X86_64.INC (06-May-2006):
call store_instruction_code ;current line 6113
;************** insert this ****************
cmp bl,44h ;ESP?
je try_swap_base_and_index
cmp bl,84h ;RSP?
jne index_not_stack_pointer
try_swap_base_and_index:
cmp cl,1 ;swapping is not allowed if scale<>1
jne index_not_stack_pointer
xchg bl,bh ;Make ESP/RSP the base
index_not_stack_pointer:
;*************** end of insert *************
cmp bl,44h ;previously line 6114, now 6125
This simple change has made my life so much easier, I would like to suggest that this idea become part of the future FASM line to enhance the usability. Lets make something that is already very good into something even better