Strange issue with loading Pointers of Structures

Bare metal programming in PureBasic, for experienced users
SMaag
Enthusiast
Enthusiast
Posts: 347
Joined: Sat Jan 14, 2023 6:55 pm
Location: Bavaria/Germany

Strange issue with loading Pointers of Structures

Post by SMaag »

I want to load the Pointer of a Structure variable to a Register! The Structure Var can be a var.vector4 or *var.vector4

If I do this inside a Procedure it works with MOV for the *var and LEA for the var
But when I do the same from outside a Procedure I need MOV for both *var and var

here is the example

Code: Select all

EnableASM 
EnableExplicit

; for calls from inside a procedure it's differnt: Structure Pointers with MOV and VAR with LEA
; for me this seems correct. But for calls from outside a Procedure we need MOV for both. See below!
Macro _VectorPointerToREG(_REG_, _vector_)
  Debug SizeOf(_vector_)
  CompilerIf SizeOf(_vector_)=SizeOf(Integer)
    MOV _REG_, _vector_
  CompilerElse
    LEA _REG_, _vector_
  CompilerEndIf
EndMacro

; why outside of a Procedrue it is always MOV? for Structure pointers and for var
Macro _VectorPointerToREG_outsidePorc(_REG_, _vector_)
  MOV _REG_, _vector_
EndMacro

Macro DbgREG(_REG=RAX)
  Define _dbgval_
  MOV _dbgval_, _REG
  Debug _dbgval_
EndMacro

Procedure vecTest(*vec.Vector4)
  Protected mv.Vector4
  Debug "inside Procedure"
  Debug "mv"
  _VectorPointerToREG(RAX, mv)
  DbgREG()
  Debug @ mv
  Debug ""
  Debug"*vec"
  _VectorPointerToREG(RAX, *vec)
  DbgREG()
  Debug *vec
EndProcedure

Define v.Vector4
Define *pv.Vector4 = @v

Debug @v
Debug *pv
Debug @*pv
Debug""
vecTest(v)

Debug ""
Debug "outside Procedure"
Debug ""
Debug "v"
; _VectorPointerToREG_outsidePorc(RAX, v)  ; Try this! It will cause an error
_VectorPointerToREG_outsidePorc(RAX, v)
DbgREG()
Debug @v

Debug ""
Debug "*pv"
_VectorPointerToREG_outsidePorc(RAX, *pv)
DbgREG()
Debug *pv


SMaag
Enthusiast
Enthusiast
Posts: 347
Joined: Sat Jan 14, 2023 6:55 pm
Location: Bavaria/Germany

Re: Strange issue with loading Pointers of Structures

Post by SMaag »

Now I have a workarround. But I still not understand what is the reason for the Problem!

Code: Select all

EnableASM 
EnableExplicit

; for calls from inside a procedure it's differnt: Structure Pointers with MOV and VAR with LEA
; for me this seems correct. But for calls from outside a Procedure we need MOV for both. See below!
Macro _VectorPointerToREG(_REG_, _vector_)
  CompilerIf #PB_Compiler_Procedure <> #Null$
    CompilerIf SizeOf(_vector_)=SizeOf(Integer)
      MOV _REG_, _vector_
    CompilerElse
      LEA _REG_, _vector_
    CompilerEndIf
  CompilerElse
    MOV _REG_, _vector_
  CompilerEndIf
EndMacro

; why outside of a Procedrue it is always MOV? for Structure pointers and for var
Macro _VectorPointerToREG_outsidePorc(_REG_, _vector_)
  MOV _REG_, _vector_
EndMacro

Macro DbgREG(_REG=RAX)
  Define _dbgval_
  MOV _dbgval_, _REG
  Debug _dbgval_
EndMacro

Procedure vecTest(*vec.Vector4)
  Protected mv.Vector4, *pmv.Vector4=@mv
  Debug "inside Procedure"
  Debug "mv - Protected var"
  _VectorPointerToREG(RAX, mv)
  DbgREG()
  Debug @ mv
  Debug ""
  Debug"*vec - Procedure Parameter"
  _VectorPointerToREG(RAX, *vec)
  DbgREG()
  Debug *vec
  
  Debug ""
  Debug "*pmv - Protected Pointer"
  _VectorPointerToREG(RAX, *pmv)
  DbgREG()
  Debug *pmv
EndProcedure

Define v.Vector4
Define *pv.Vector4 = @v

Debug @v
Debug *pv
Debug @*pv
Debug""
vecTest(v)

Debug ""
Debug "outside Procedure"
Debug ""
Debug "v"
_VectorPointerToREG_outsidePorc(RAX, v)  ; Try this! It will cause an error
;_VectorPointerToREG_outsidePorc(RAX, v)
DbgREG()
Debug @v

Debug ""
Debug "*pv"
_VectorPointerToREG(RAX, *pv)
DbgREG()
Debug *pv
User avatar
spikey
Enthusiast
Enthusiast
Posts: 783
Joined: Wed Sep 22, 2010 1:17 pm
Location: United Kingdom

Re: Strange issue with loading Pointers of Structures

Post by spikey »

I'm know I'm not following you entirely here (I've an infection and brain functions are impaired!) but I can see some problems.
1) The macro DbgREG is bugged. Where does _dbgval_ come from?
2) LEA and MOV perform two completely separate functions. LEA moves addresses into registers. MOV moves values stored in memory into/out of registers. I'm struggling to think of any situations when you would legitimately want to mix the two up. Use them together - yes often, interchange them - no.
3) There's no monolithic "variable storage space". Stuff ends up in various places depending on what type it is and in which scope it is defined.
Simple type (<= .I in size) local variables and parameters will end up on the stack. Global, main, static and shared variables will end up in the writeable data section. Complex types (simple strings and structures, arrays, lists, maps of any kind, memory blocks) will end up on the heap.

In the program's code everything will be referenced as an offset from the appropriate base pointer to their location if that's easy to manage, or an entirely separate pointer, if its not (e.g. lists, maps, blocks).
Post Reply