Page 1 of 1
Convert Inline ASM to C Backend compatible code?
Posted: Fri Feb 11, 2022 12:31 am
by zikitrake
Hi, I would like to continue using this fantastic code from @Wilbert :
https://www.purebasic.fr/english/viewtopic.php?t=66497
It has a part of inline ASM:
Code: Select all
Procedure _PNGSizeCheck_(*MemoryAddress, MaxSize.l)
EnableASM
mov rdx, [p.p_MemoryAddress]
!mov eax, [p.v_MaxSize]
push rbx
!lea ebx, [eax - 8]
!xor eax, eax
cmp dword [rdx], 0x474e5089
!jne .l1
cmp dword [rdx + 4], 0x0a1a0a0d
!jne .l1
!mov eax, 8
!.l0:
mov ecx, [rdx + rax]
!bswap ecx
lea rax, [rax + rcx + 12]
!cmp eax, ebx
!ja .l1
cmp dword [rdx + rax + 4], 0x444e4549
!jne .l0
!add eax, 12
!.l1:
pop rbx
DisableASM
ProcedureReturn
EndProcedure
Is possible convert it to C backend compatible code without losing speed?
Thank you in advance!
Re: Convert Inline ASM to C Backend compatible code?
Posted: Fri Feb 11, 2022 1:54 pm
by juergenkulow
Please note:
Code: Select all
;- Macros (Windows)
CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
Macro rax : eax : EndMacro
Macro rbx : ebx : EndMacro
Macro rcx : ecx : EndMacro
Macro rdx : edx : EndMacro
CompilerEndIf
and in IncludeFile "MemoryStreamModule.pbi"
Code: Select all
Procedure.i MStream_AddRef(*this.MStream_Object)
; InterlockedIncrement of *this\refcount
CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
!mov edx, [p.p_this]
!lock inc dword [edx + 4]
CompilerElse
!mov rdx, [p.p_this]
!lock inc dword [rdx + 8]
CompilerEndIf
ProcedureReturn *this\refcount
EndProcedure
Procedure.i MStream_Release(*this.MStream_Object)
; InterlockedDecrement of *this\refcount
CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
!mov edx, [p.p_this]
!lock dec dword [edx + 4]
CompilerElse
!mov rdx, [p.p_this]
!lock dec dword [rdx + 8]
CompilerEndIf
; Free memory if refcount = 0
If *this\refcount = 0
FreeMemory(*this)
ProcedureReturn 0
EndIf
ProcedureReturn *this\refcount
EndProcedure
Re: Convert Inline ASM to C Backend compatible code?
Posted: Sat Feb 12, 2022 3:06 pm
by zikitrake

Thank you!I'll keep using the classic PB compiler then, which in the PB 6 version does the job as well as ever.
Re: Convert Inline ASM to C Backend compatible code?
Posted: Sat Feb 12, 2022 7:12 pm
by idle
Would be better to port it back to basic. I don't think we can have jmps with inline asm or maybe we can when it's at&t format. I tried yesterday but failed.
Re: Convert Inline ASM to C Backend compatible code?
Posted: Sat Feb 12, 2022 8:08 pm
by mk-soft
It also makes no sense to use ASM in the C-backend. This way, the code does not run on arm processors.
Re: Convert Inline ASM to C Backend compatible code?
Posted: Sat Feb 12, 2022 10:28 pm
by skywalk
I have a similar problem:
Code: Select all
Procedure RestoreX(DataLabel.i)
CompilerSelect #PB_Compiler_Processor
CompilerCase #PB_Processor_x64
!MOV rax, [p.v_DataLabel] ; instead of -> !MOV rax, [rsp+64]
!MOV [PB_DataPointer], rax
CompilerCase #PB_Processor_x86
!MOV eax, [p.v_DataLabel] ; instead of -> !MOV eax, [esp+8]
!MOV [PB_DataPointer], eax
CompilerDefault
MessageRequester("RestoreX", "Unknown Processor.", #MB_ICONERROR)
CompilerEndSelect
EndProcedure
; Example use within a procedure.
Procedure Do1()
RestoreX(?ds_MyDatasectionStuff)
Read.i i
EndProcedure
Re: Convert Inline ASM to C Backend compatible code?
Posted: Sun Feb 13, 2022 1:03 am
by idle
Re: Convert Inline ASM to C Backend compatible code?
Posted: Sun Feb 13, 2022 4:39 am
by skywalk
Thanks idle!
This got me close, but 1st data element is corrupted?
I posted the code
here.
Re: Convert Inline ASM to C Backend compatible code?
Posted: Sun Feb 13, 2022 6:39 am
by breeze4me
It seems to work, but it is not thoroughly tested.
Code: Select all
Procedure _PNGSizeCheck_(*MemoryAddress, MaxSize)
Protected result
!__asm__ __volatile__ (".intel_syntax noprefix;"
CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
!"mov edx, %1;"
!"mov eax, %2;"
!"lea ebx, [eax - 8];"
!"xor eax, eax;"
;!"xor ecx, ecx;"
!"cmp dword ptr [edx], 0x474e5089;"
!"jne locallabel_1;"
!"cmp dword ptr [edx + 4], 0x0a1a0a0d;"
!"jne locallabel_1;"
!"mov eax, 8;"
!"locallabel_0:;"
!"mov ecx, dword ptr [edx + eax];"
!"bswap ecx;"
!"lea eax, [eax + ecx + 12];"
!"cmp eax, ebx;"
!"ja locallabel_1;"
!"cmp dword ptr [edx + eax + 4], 0x444e4549;"
!"jne locallabel_0;"
!"add eax, 12;"
!"locallabel_1:;"
!"mov %[res], eax;"
!".att_syntax"
!: [res] "=r" (v_result)
!: "r" (p_memoryaddress), "r" (v_maxsize)
!: "edx", "eax", "ecx", "ebx"
!);
CompilerElse
!"mov rdx, %1;"
!"mov rax, %2;"
!"lea rbx, [rax - 8];"
!"xor rax, rax;"
!"xor rcx, rcx;"
!"cmp dword ptr [rdx], 0x474e5089;"
!"jne locallabel_1;"
!"cmp dword ptr [rdx + 4], 0x0a1a0a0d;"
!"jne locallabel_1;"
!"mov rax, 8;"
!"locallabel_0:;"
!"mov ecx, dword ptr [rdx + rax];"
!"bswap ecx;"
!"lea rax, [rax + rcx + 12];"
!"cmp eax, ebx;"
!"ja locallabel_1;"
!"cmp dword ptr [rdx + rax + 4], 0x444e4549;"
!"jne locallabel_0;"
!"add rax, 12;"
!"locallabel_1:;"
!"mov %[res], rax;"
!".att_syntax"
!: [res] "=r" (v_result)
!: "r" (p_memoryaddress), "r" (v_maxsize)
!: "rdx", "rax", "rcx", "rbx"
!);
CompilerEndIf
ProcedureReturn result
EndProcedure
Remove the macro.
;- Macros (Windows)
CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
Macro rax : eax : EndMacro
Macro rbx : ebx : EndMacro
Macro rcx : ecx : EndMacro
Macro rdx : edx : EndMacro
CompilerEndIf
Code: Select all
Procedure.i MStream_AddRef(*this.MStream_Object)
; InterlockedIncrement of *this\refcount
;*this\refcount + 1
!__asm__ __volatile__ (".intel_syntax noprefix;"
CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
!"mov edx, %0;"
!"lock inc dword ptr [edx + 4];"
!".att_syntax"
!:
!: "r" (p_this)
!: "edx"
!);
CompilerElse
!"mov rdx, %0;"
!"lock inc dword ptr [rdx + 8];"
!".att_syntax"
!:
!: "r" (p_this)
!: "rdx"
!);
CompilerEndIf
ProcedureReturn *this\refcount
EndProcedure
Procedure.i MStream_Release(*this.MStream_Object)
; InterlockedDecrement of *this\refcount
;*this\refcount - 1
!__asm__ __volatile__ (".intel_syntax noprefix;"
CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
!"mov edx, %0;"
!"lock dec dword ptr [edx + 4];"
!".att_syntax"
!:
!: "r" (p_this)
!: "edx"
!);
CompilerElse
!"mov rdx, %0;"
!"lock dec dword ptr [rdx + 8];"
!".att_syntax"
!:
!: "r" (p_this)
!: "rdx"
!);
CompilerEndIf
; Free memory if refcount = 0
If *this\refcount = 0
FreeMemory(*this)
ProcedureReturn 0
EndIf
ProcedureReturn *this\refcount
EndProcedure
Re: Convert Inline ASM to C Backend compatible code?
Posted: Sun Feb 13, 2022 12:59 pm
by zikitrake
breeze4me wrote: Sun Feb 13, 2022 6:39 am
It seems to work, but it is not thoroughly tested....
I absolutely adore you

It seems to work like a charm
Sincerely, huge thanks to you and other users who make this forum so great.
Re: Convert Inline ASM to C Backend compatible code?
Posted: Sun Feb 13, 2022 4:11 pm
by wilbert
Thanks for converting.
I was wondering, does anyone know if the atomic function
Code: Select all
Procedure AtomicInc(*p.Integer)
!return __atomic_add_fetch((int *)p_p, 1, __ATOMIC_RELAXED);
EndProcedure
AtomicInc(@v)
Debug v
is crossplatform and working on the arm version of macOS ?
Re: Convert Inline ASM to C Backend compatible code?
Posted: Sun Feb 13, 2022 9:14 pm
by idle
thanks breeze4me, I had an error in my code and thought there was something wrong using labels.