flat assembler
Message board for the users of flat assembler.

Index > Main > Offset of a virtual member?

Author
Thread Post new topic Reply to topic
Proger



Joined: 25 Jul 2014
Posts: 2
Proger 25 Jul 2014, 19:05
I am trying to understand why the following doesn't compile:

Code:
virtual at ebp
  v db 0
end virtual

mov eax, v    


My understanding is that everything fasm creates as a "variable" is simply a label which value is an address. This is how regular data works, like this:
Code:
mov eax, dataname
dataname db 0    


This compiles to mov eax, 0x40.... So why it doesn't work the same way with virtual?

I could get this working:
Code:
lea eax, [v]
mov dword[eax], 123     


...but it's somewhat long-winded, I don't get why I have to LEA it first because fasm apparently knows the address (it correctly expands [v] into ebp).

Am I missing some syntax here?
Post 25 Jul 2014, 19:05
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20448
Location: In your JS exploiting you and your system
revolution 25 Jul 2014, 20:55
You have to use this:
Code:
virtual at ebp
  v db 0
end virtual

mov eax, dword[v] ;note the override and the square brackets
;or
movzx eax, [v] ;no override needed    
Post 25 Jul 2014, 20:55
View user's profile Send private message Visit poster's website Reply with quote
l_inc



Joined: 23 Oct 2009
Posts: 881
l_inc 26 Jul 2014, 01:03
Proger
This is an interesting one, I'd say. To make your question a bit more clear, here's an equivalent one:
Why does
Code:
label x at 0
mov eax,x    

compile and
Code:
label x at ebp
mov eax,x    

does not?

To simplify this even more, why the following does not compile?
Code:
mov eax,0+ebp    


I think, we'd need some higher forces intervention to clear this up.

_________________
Faith is a superposition of knowledge and fallacy
Post 26 Jul 2014, 01:03
View user's profile Send private message Reply with quote
neville



Joined: 13 Jul 2008
Posts: 507
Location: New Zealand
neville 26 Jul 2014, 03:49
I_inc, I'm sure there's no X86 instruction for adding an offset to a register in a register-to-register move. Ok, if the offset is 00, EBP+00 is still EBP, but what meaning would a non-zero offset have? Wink

A meaningful offset must be applied to an address operand, i.e. [ebp+00], not ebp+00

_________________
FAMOS - the first memory operating system
Post 26 Jul 2014, 03:49
View user's profile Send private message Visit poster's website Reply with quote
Proger



Joined: 25 Jul 2014
Posts: 2
Proger 26 Jul 2014, 04:59
revolution
My intention was to get the address of the member, not its value.

neville
This must be it - I didn't think about it. Indeed, if accessing value by address we can use arithmetics but we can't calculate address per se using math, that's exactly what LEA is for and that's why it works while MOV doesn't. Obviously, in-code data has fixed addresses which fasm can calculate. This answers l_inc's points too.

Actually, this will compile just fine because it uses a fixed base:
Code:
virtual at 123
v dd ?
end virtual

mov eax, v    


Thanks for clarification.
Post 26 Jul 2014, 04:59
View user's profile Send private message Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1670
Location: Toronto, Canada
AsmGuru62 26 Jul 2014, 13:44
LEA has the following uses:
1. Get the address of a local variables. Local variables based relative to ESP or EBP registers,
so, to load the address you do the following:
Code:
lea eax, [ebp + 8]
lea edi, [esp + 8]
    

If you use macro local from FASM package - it is done for you automatically.

2. LEA is good to calculate stuff, like to multiply a register by 3:
Code:
lea ecx [eax + eax*2]   ; ECX = 3*EAX
    

This is faster than MUL/IMUL opcode.

3. If you have the structure pointed to by a register, you can use the same
principle as in local variables to get an address of a field inside the structure:
Code:
struct CFolders
  wchFolder1 rw 256
  wchFolder2 rw 256
  wchFolder3 rw 256   ; Buffer #3
ends
...
;
; EBX -> CFolders instance
;
lea edi, [ebx + CFolders.wchFolder3]   ; EDI -> Buffer #3
    
Post 26 Jul 2014, 13:44
View user's profile Send private message Send e-mail Reply with quote
l_inc



Joined: 23 Oct 2009
Posts: 881
l_inc 26 Jul 2014, 13:53
neville
Proger wrote:
This answers l_inc's points too.

It does not actually.
Quote:
Ok, if the offset is 00, EBP+00 is still EBP, but what meaning would a non-zero offset have?

I never said anything about non-zero "offsets". Those are meaningless. But fasm does some internal calculations and optimizations. This way you can for example write something like
Code:
mov eax,-ebp*3-ebx+2*(ebp+ebx+$10)+ebp-ebx    

and this will perfectly compile as long as the expression simplifies to a scalar. As for me, it should not be a problem to correctly compile the expression if it simplifies to any basis vector of the expression vector space.

_________________
Faith is a superposition of knowledge and fallacy
Post 26 Jul 2014, 13:53
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8359
Location: Kraków, Poland
Tomasz Grysztar 27 Jul 2014, 10:11
This is a limitation of fasm's implementation. When processing any instruction, that requires a register operand, fasm expects a specific kind of syntactical token, i.e. the direct specification of register. It does not affect an expression there, even if after evaluating the expression the result would be a single register and nothing more. You can experiment with EQTYPE operator to investigate what kind of text fasm interpretes as a valid register token:
Code:
if ebp eqtype eax       ; true, both sides contain a single register token

    mov eax,ebp

end if

if +ebp eqtype eax      ; false, the left side is an expression

    mov eax,+ebp        ; because of limitation of current fasm implementation,
                        ;  an expression cannot be evaluated to register here
end if

label v at ebp

if v eqtype ebp         ; false, the left side is a label and is interpreted as an expression

    mov eax,v           ; the same limitation causes an error in this case, too

end if

if v eqtype +ebp        ; true, this demonstrates that a single label is treated the same way
                        ;  as an expression

    label v2 at +ebp    ; some examples of places where fasm's implementation
    mov eax,[v2]        ;  allows to use expressions containing registers

end if    


This limitation had never been considered a serious problem, because such usage would rarely be practical - in any case where you used such expression, it could be assembled correctly only in the case when everything cancelled out in such a way, that only a single register with no additional offsets was left.

Of course it would be nice, if fasm was able to evaluate correctly this kind of syntax, but this would require a lot of work for mainly an aesthetic effect.

In that rare situation when you don't want to use LEA and you are sure that the expression is going to evaluate cleanly, you can use some trickery to get the desired result:
Code:
if v relativeto ebp & v-ebp=0
  mov eax,ebp
else if v relativeto esp & v-esp=0
  mov eax,esp
; etc.
else
  mov eax,v
end if    
This could be packaged into some easy-to-use macro.
Post 27 Jul 2014, 10:11
View user's profile Send private message Visit poster's website Reply with quote
l_inc



Joined: 23 Oct 2009
Posts: 881
l_inc 27 Jul 2014, 15:58
Tomasz Grysztar
Quote:
Of course it would be nice, if fasm was able to evaluate correctly this kind of syntax

I like, that we agree on that.
Quote:
but this would require a lot of work for mainly an aesthetic effect

I actually completely agree, that it's rarely practical and is mainly about aesthetics. I'm kind of proud of using fasm as assembler compiler, and find it nice to be able to present to someone else such examples and say: "See, how cool and consistent it is!"

But pragmatically it's definitely not worth putting large additional effort, especially if the effort is about introducing special cases rather then making the underlying architecture more consistent.

_________________
Faith is a superposition of knowledge and fallacy
Post 27 Jul 2014, 15:58
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20448
Location: In your JS exploiting you and your system
revolution 27 Jul 2014, 21:44
fasmarm has been able to do this since version 1.08:
Code:
virtual at sp
 x1 dw ?
 x2 dw ?
end virtual
mov r0,x2 ;assembles to add r0,sp,4    
The main reason I support this is because ARM does not have an LEA equivalent opcode so it would have been difficult to get the addresses of the x1 or x2 without such a method.

Edit: sp can be replaced with any other valid register also.
Post 27 Jul 2014, 21:44
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8359
Location: Kraków, Poland
Tomasz Grysztar 28 Jul 2014, 11:55
Yes, this is in fact not a limitation of the fasm's core architecture, but of the x86 instruction handlers implementation. All changes that would be required to make this trick work with x86 instructions would be restricted to X86.INC/AVX.INC only. But it would require alterations of a heavily re-used code schemma and it would probably introduce additional complexity into many of the instruction handlers. Still, next time when I do some work in these areas (like when I implement AVX512), I may think about it a bit more.
Post 28 Jul 2014, 11:55
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-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.