Page 1 of 1

Preserving EBX register

Posted: Sun Apr 26, 2015 5:15 pm
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?

Re: Preserving EBX register

Posted: Sun Apr 26, 2015 5:31 pm
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

Re: Preserving EBX register

Posted: Sun Apr 26, 2015 5:35 pm
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).

Re: Preserving EBX register

Posted: Sun Apr 26, 2015 6:33 pm
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:.