Preserving EBX register

Bare metal programming in PureBasic, for experienced users
Inf0Byt3
PureBasic Fanatic
PureBasic Fanatic
Posts: 2236
Joined: Fri Dec 09, 2005 12:15 pm
Location: Elbonia

Preserving EBX register

Post by Inf0Byt3 »

I've got this procedure where I need an extra register besides eax, ecx and edx. ebx seems to be good for the task, but I can't seem to be able to preserve it. For example consider the following code:

Code: Select all

Procedure myproc(bbb.l)

    CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
        !push rbx
    CompilerElse
        !push ebx
    CompilerEndIf

    ;bbb + 1
    !mov ebx, dword [p.v_bbb]
    !inc ebx
    !mov dword [p.v_bbb], ebx

    CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
        !pop rbx
    CompilerElse
        !pop ebx
    CompilerEndIf  

    ProcedureReturn bbb

EndProcedure

n = myproc(5) ;should return 6
Debug n
If the push and pop parts are commented, the result comes out ok. What is the safe way to use ebx?
None are more hopelessly enslaved than those who falsely believe they are free. (Goethe)
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3736
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Preserving EBX register

Post by wilbert »

When you alter the stack with pushing and popping registers, that messes up references to local variables like [p.v_bbb]
What I'm currently using is an integer variable to store the register. This works fine.
The same way you can preserve rsi/esi and rdi/edi if you need even more registers.
Using rbp/ebp as an extra register causes problems with the debugger.

Code: Select all

Procedure myproc(bbb.l)
  
  Protected.i reg_bx
  
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
    !mov [p.v_reg_bx], rbx
  CompilerElse
    !mov [p.v_reg_bx], ebx
  CompilerEndIf
  
  ;bbb + 1
  !mov ebx, dword [p.v_bbb]
  !inc ebx
  !mov dword [p.v_bbb], ebx
  
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
    !mov rbx, [p.v_reg_bx]
  CompilerElse
    !mov ebx, [p.v_reg_bx]
  CompilerEndIf 
  
  ProcedureReturn bbb
  
EndProcedure

n = myproc(5) ;should return 6
Debug n
macOS 10.15 Catalina, Windows 10
User avatar
Tenaja
Addict
Addict
Posts: 1816
Joined: Tue Nov 09, 2010 10:15 pm

Re: Preserving EBX register

Post by Tenaja »

Pb uses the stack for local variables. Since it doesn't use a frame pointer, any stack changes you make will kill the reference point.

This was a design decision the developer made early on, to allow more registers for optimizing, but at the cost of capabilities like this (and many other standard practices).
Inf0Byt3
PureBasic Fanatic
PureBasic Fanatic
Posts: 2236
Joined: Fri Dec 09, 2005 12:15 pm
Location: Elbonia

Re: Preserving EBX register

Post by Inf0Byt3 »

Thank you both for the explanation, it's perfectly clear now. I'll save the register in a variable as advised. Still got many things to learn :mrgreen:.
None are more hopelessly enslaved than those who falsely believe they are free. (Goethe)
Post Reply