flat assembler
Message board for the users of flat assembler.

Index > Main > fasm 1.67.21 bug not in 1.64?

Goto page 1, 2  Next
Author
Thread Post new topic Reply to topic
lazer1



Joined: 24 Jan 2006
Posts: 185
lazer1
if I create the following file say bug.asm

Code:

macro mycall reg,func
        {
        call func
        }

macro xyz num*
        {
        org 20000h
        mycall edi, f 
        }

use16
        xyz 0
main:   jmp main


f:      ret

    



this assembles fine with fasm 1.64 : Razz

Code:
flat assembler  version 1.64
2 passes, 6 bytes.
    


but many errors with 1.67.21 Mad

Code:
flat assembler  version 1.67.21  (15360 kilobytes memory)
test64\bug2.asm [14]:
        xyz 0
test64\bug2.asm [10] xyz [2]:
        mycall edi, f 
test64\bug2.asm [4] mycall [1]:
        call func
error: invalid value.

    


I have to use 1.67.21 as I need popfq which
isnt available in 1.64

catch 22 situation!

Rolling Eyes
Post 24 Mar 2007, 19:13
View user's profile Send private message Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1901
DOS386
Code:
        org 20000h
        mycall edi, f 
        }
        use16 
    


I don't think this can work. use16 limits code addressing and
org to 64 KB.

_________________
Bug Nr.: 12345

Title: Hello World program compiles to 100 KB !!!

Status: Closed: NOT a Bug
Post 25 Mar 2007, 11:23
View user's profile Send private message Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 7718
Location: Kraków, Poland
Tomasz Grysztar
Actually it's the opposite - it was the bug of earlier versions of fasm that was fixed recently. With "use16" your jump defaults to 16 bits, and "org 20000h" makes the addresses invalid for 16 bits. If you want to generate 32-bit jumps (with 66h prefix), you need to do it like:
Code:
jmp dword f    
Post 25 Mar 2007, 13:52
View user's profile Send private message Visit poster's website Reply with quote
lazer1



Joined: 24 Jan 2006
Posts: 185
lazer1
Tomasz Grysztar wrote:
Actually it's the opposite - it was the bug of earlier versions of fasm that was fixed recently. With "use16" your jump defaults to 16 bits, and "org 20000h" makes the addresses invalid for 16 bits. If you want to generate 32-bit jumps (with 66h prefix), you need to do it like:
Code:
jmp dword f    


this new feature is a total nuisance, Sad

the original code functioned just fine, Razz

I now have to change every single jmp instruction:

jmp, jg, jge, je, etc Evil or Very Mad

apart from pedantry what point is there to this? Surprised

also I cannot change it via redefining the jmps as that
will interfere with the 64 bit code,
Post 26 Mar 2007, 14:16
View user's profile Send private message Reply with quote
lazer1



Joined: 24 Jan 2006
Posts: 185
lazer1
NTOSKRNL_VXE wrote:
Code:
        org 20000h
        mycall edi, f 
        }
        use16 
    


I don't think this can work. use16 limits code addressing and
org to 64 KB.


"call f"

can have only 1 possible meaning, so fasm should really
disambiguate automatically as there is a clear
disambiguation,

I have literally hundreds of jmp and loop statements in
my 32 bit code,

I either have to do that via earlier versions of fasm or
go through endless code changing to dword,
Post 26 Mar 2007, 14:29
View user's profile Send private message Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4633
Location: Argentina
LocoDelAssembly
Quote:

also I cannot change it via redefining the jmps as that
will interfere with the 64 bit code

purge the macros when you reach 64-bit code. Sure that the code without address size override worked good? There was some situations where it worked bad but I can't find the damn thread.
Post 26 Mar 2007, 14:36
View user's profile Send private message Reply with quote
lazer1



Joined: 24 Jan 2006
Posts: 185
lazer1
lazer1 wrote:
NTOSKRNL_VXE wrote:
Code:
        org 20000h
        mycall edi, f 
        }
        use16 
    


I don't think this can work. use16 limits code addressing and
org to 64 KB.


"call f"

can have only 1 possible meaning, so fasm should really
disambiguate automatically as there is a clear
disambiguation,

I have literally hundreds of jmp and loop statements in
my 32 bit code,

I either have to do that via earlier versions of fasm or
go through endless code changing to dword,


if anything this will lead to MORE BUGS if I accidentally
put dword in long mode jmps. Not sure but I think
"jmp dword label"

would be an absolute jmp which wont be relocatable,
ALL my long mode code is relocatable,

long mode has been designed to be VERY relocatable,
Post 26 Mar 2007, 14:41
View user's profile Send private message Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4633
Location: Argentina
LocoDelAssembly
"jmp label" and "jmp dword label" are both relative so there is no problem. In fact FASM still encodes with rel8 if possible, it only adds the prefix to the instruction. I still can't find the thread but if I remember right the problem is that without the prefix the CPU does "IP = IP + rel" but since the address doesn't fit in 16 bits there is situations where it will not work and for that you need "EIP = EIP + rel" which is done by the address size override prefix.
Post 26 Mar 2007, 15:06
View user's profile Send private message Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 7718
Location: Kraków, Poland
Tomasz Grysztar
Yes, LocoDelAssembly, you remember right. The code from first post assembled with 1.64 would be buggy, as it would clear the upper 16 bits of EIP.
fasm doesn't create a 66h/67h prefixed instructions unless clearly told so - this was decided a long time ago, somewhere between the 0.9.x prereleases and the 1.0 (I recall it was perhaps due to some user feedback), the very early versions were for example doing "aggressive" size optimization in 32-bit mode by generating 16-bit conditional jumps (shorter by one byte). But it really was a bad idea and since then fasm always uses the size default for the given mode, unless the size is explicitly specified.
Post 26 Mar 2007, 16:17
View user's profile Send private message Visit poster's website Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4633
Location: Argentina
LocoDelAssembly
Quote:

as it would clear the upper 16 bits of EIP.

Oh, then I wrote wrong, it is "EIP = (IP + rel) AND $FFFF".

Thanks Smile
Post 26 Mar 2007, 16:36
View user's profile Send private message Reply with quote
lazer1



Joined: 24 Jan 2006
Posts: 185
lazer1
LocoDelAssembly wrote:
"jmp label" and "jmp dword label" are both relative so there is no problem. In fact FASM still encodes with rel8 if possible, it only adds the prefix to the instruction. I still can't find the thread but if I remember right the problem is that without the prefix the CPU does "IP = IP + rel" but since the address doesn't fit in 16 bits there is situations where it will not work and for that you need "EIP = EIP + rel" which is done by the address size override prefix.


I guess if you have code which is almost 64K in size and you jump to the
far end that will cause a problem as relative jumps are signed 15 bit so
to speak:

eg if you jump from 20000h to 29000h then it will possibly wrongly jump to

20000h + ffff....ff9000h = 19000h ???

ie the problem even happens in 16 bit code as relative jumps are 15 bit
in either direction,

I have changed the code now but it was painful,

most jumps were to local labels so I sped up the changes
via query search and replace "." by "dword ." Razz

(eg "jge .done" becomes "jge dword .done", but
".done:" MUSTNT be replaced by "dword .done:" Confused )

(most of my calls are done via macro so I only had to
change the 1 macro and a few cases where I called
directly)
Post 26 Mar 2007, 16:41
View user's profile Send private message Reply with quote
lazer1



Joined: 24 Jan 2006
Posts: 185
lazer1
LocoDelAssembly wrote:
Quote:

also I cannot change it via redefining the jmps as that
will interfere with the 64 bit code

purge the macros when you reach 64-bit code. Sure that the code without address size override worked good? There was some situations where it worked bad but I can't find the damn thread.


it did function fine, but I remember having one inexplicable bug,

I then completely redid that part of the code, so it is possible
that I redid the call with a nearer function,

so any problems I probably worked around by rewriting,

note that typically there wont be a problem with jmps as jmps
tend to be near,

my 16 bit code is via 64K aligned subsets, moving between
such is done via far calls,
Post 26 Mar 2007, 17:06
View user's profile Send private message Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4633
Location: Argentina
LocoDelAssembly
That jump would be impossible to encode with rel8/rel16, you have no choice other than rel32 but that is a different problem that the one Tomasz says. Suppose you want to jump from $10000 to $10100, then the calculus would be "$10000 + $100 = $10100", BUT since we are not using the adress size override this will happens: "($10000 + $100) AND $FFFF = $100". $100 obviously is not the expected target so here is of mandatory use the address size override.
Post 26 Mar 2007, 17:16
View user's profile Send private message Reply with quote
lazer1



Joined: 24 Jan 2006
Posts: 185
lazer1
LocoDelAssembly wrote:
Quote:

also I cannot change it via redefining the jmps as that
will interfere with the 64 bit code

purge the macros when you reach 64-bit code. Sure that the code without address size override worked good? There was some situations where it worked bad but I can't find the damn thread.


the modified code no longer functions!

possibly "call dword f" uses the stack differently from
how the earlier fasm did "call f"

I am looking at the function arg and return macros to see
if I can resolve the problem,

luckily I have a backup of the earlier code, so I could quit
the "dword f" idea and just use the earlier fasm for the
16 bit code,
Post 26 Mar 2007, 18:06
View user's profile Send private message Reply with quote
lazer1



Joined: 24 Jan 2006
Posts: 185
lazer1
what is the correct way to return from a function called via "call dword f" ?
Post 26 Mar 2007, 18:28
View user's profile Send private message Reply with quote
lazer1



Joined: 24 Jan 2006
Posts: 185
lazer1
LocoDelAssembly wrote:
That jump would be impossible to encode with rel8/rel16, you have no choice other than rel32 but that is a different problem that the one Tomasz says. Suppose you want to jump from $10000 to $10100, then the calculus would be "$10000 + $100 = $10100", BUT since we are not using the adress size override this will happens: "($10000 + $100) AND $FFFF = $100". $100 obviously is not the expected target so here is of mandatory use the address size override.


well maybe you are right,

my modified code however went from bad to worse, so I have
reverted to the original code and will use an earlier fasm for
the 16 bit code.

perhaps I put one dword too many,

"jmp dword somelabel" seemed to be malfunctioning for
nearby labels,

WHY do I need "dword" to do eg:

.label: jmp dword .label

?

surely as a relative jmp that is a few bytes but
the current fasm doesnt allow:
org 20000h
...
.label: jmp .label



I'll try doing the dwords again sometime,

I wish there was a run time option at least where the dword's are
done automatically just for the case of labels,


I am trying it out again, this time error message by error message
and trying the binary via the earlier fasm after each file, and making
backups if the file functions,


Last edited by lazer1 on 26 Mar 2007, 21:28; edited 1 time in total
Post 26 Mar 2007, 20:12
View user's profile Send private message Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4633
Location: Argentina
LocoDelAssembly
Oh yes, never realised that, you have to use
Code:
db $66
ret    
With that you will be able to return using a 4-byte return address.

I will do some experiments later because since you say that the supposed to be bug code generated by fasm 1.64 works, then maybe there is no 16 upper bits clearing?
Post 26 Mar 2007, 21:00
View user's profile Send private message Reply with quote
lazer1



Joined: 24 Jan 2006
Posts: 185
lazer1
after many hours of modifying and then compiling with the earlier
fasm I have found the cause of the malfunction when I modified
"call f" to "call dword f",

call dword f

with

f:
...
ret

has the stack wrong on return. Most of my code resets the stack
with ebp so the error doesnt matter. But in one file I have a few
functions which dont reset the stack which leads to total misfunction.

neither "ret" nor "retf" reset the stack correctly. "retf" totally malfunctions.

"ret" is ok provided I restore the stack afterwards from a backup in
ebp,

any ideas what the problem is?

is there a way to return from "call dword f" where I dont need to do
"mov esp, ebp" afterwards to restore the stack?
Post 27 Mar 2007, 02:26
View user's profile Send private message Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 7718
Location: Kraków, Poland
Tomasz Grysztar
LocoDelAssembly: just RETD mnemonic is enough (see manual's section 2.1.6). As for the experiments, I made them too (also in long mode), when I realized there was a mentioned bug - and I recall it is documented by both Intel and AMD manuals.
Post 27 Mar 2007, 06:26
View user's profile Send private message Visit poster's website Reply with quote
lazer1



Joined: 24 Jan 2006
Posts: 185
lazer1
Tomasz Grysztar wrote:
LocoDelAssembly: just RETD mnemonic is enough (see manual's section 2.1.6). As for the experiments, I made them too (also in long mode), when I realized there was a mentioned bug - and I recall it is documented by both Intel and AMD manuals.


ok, retd is functioning correctly,

I still havent completed converting the code,
currently I compile the dword code with the earlier fasm,

when all files are converted I will compile via the new fasm

one problem I found is that there is no form of "loop label"
which both the earlier fasm and the current fasm accept,

the earlier fasm doesnt accept "loop dword label" but
accepts eg "jmp dword label" and "call dword label",

I got around that by replacing "loop label" by

sub cx, 1
jnz dword label

(I dont use "dec" as this code isnt speed critical, I
generally avoid the unusual opcodes of 16 bit. In fact
I will probably avoid loop in future as it is too complicated
to remember: does it loop if cx goes to 0 or from 0?
yes I know the answer is to 0, but I have to look that up
which wastes time. )
Post 27 Mar 2007, 13:08
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page 1, 2  Next

< 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-2020, Tomasz Grysztar.

Powered by rwasa.