Unable to get UserLibraries lib function adress

Just starting out? Need help? Post your questions and find answers here.
Denis
Enthusiast
Enthusiast
Posts: 704
Joined: Fri Apr 25, 2003 5:10 pm
Location: Doubs - France

Unable to get UserLibraries lib function adress

Post by Denis »

Salut Fred,

I get the same problem with PB 5.73 LTS (windows - x86), PB 6.00 alpha 3 (windows - x64) and PB 6.00 alpha 3 C backend (windows - x64) .

I'm on an asm lib (developed with PB 5.73 LTS (windows - x86)/PB 6.00 alpha 3 (windows - x64)).
I want to use prototype with PB but it's not possible to have this for example :

Fonction asm Is_MMX() , witch works correctly
This doesn't work (@ not supported)

Code: Select all

zzz = @Is_MMX()
To do the job i use asm but not really a good way...

Code: Select all

      EnableASM
      ! MOV rax, PB_Is_MMX
      ! MOV qword [p.v_zzz], rax
If you want the lib files i've done (Processor___x64, Processor___x64.lib, Processor___x86 and and Processor___x86.lib), i 'll send you them up (and also the list of functions, about 120).
A+
Denis
User avatar
Mijikai
Addict
Addict
Posts: 1360
Joined: Sun Sep 11, 2016 2:17 pm

Re: Unable to get UserLibraries lib function adress

Post by Mijikai »

Can you post working example code?
One test file and the code of a lib with only one test function.
Denis
Enthusiast
Enthusiast
Posts: 704
Joined: Fri Apr 25, 2003 5:10 pm
Location: Doubs - France

Re: Unable to get UserLibraries lib function adress

Post by Denis »

Hi Mijikai,

don't know if it will answer you

Based on An initFunction - -> Init_Processor - (When you create an userlib) :
As PB, i use include file with FASM
X64 version

Code: Select all

;
;       X64 UNICODE
;
;********************************************************
;       Init_Processor()
;
;   Description :
;   -------------
;   Memorise dans un qword l'ensemble des technologies disponibles
;********************************************************

format MS64 COFF
public PB_Init_Processor

;--------------------------------------------------------
;       include files
;--------------------------------------------------------
include '..\Processor_CPUID_Constants.inc'
;--------------------------------------------------------
;       macro
;--------------------------------------------------------
; macro d'alignement des variables globales
Macro ASMG_bssalign value { rb (value-1) - ($-_ASMG_BSSSection + value-1) mod value }
;--------------------------------------------------------
;       section code
;--------------------------------------------------------

;__________________________________________________________________________
; les registres volatiles PB sont :
; RAX, RCX, RDX, R8, R9, XMM0, XMM1, XMM2 et XMM3

; les registres volatiles MS sont :
;    RAX : Return value register
;    RCX, RDX, R8, R9 : First to fourth integer argument
;    R10, R11 : used in syscall/sysret instructions
;    XMM0 à XMM5 : First to sixth FP argument when __vectorcall is used
;    YMM0 à YMM5 : First to sixth FP argument when __vectorcall is used
;    YMM6:YMM15 : partie supérieure des registres
;    ZMM0-ZMM15 : partie supérieure des registres

;  On Intel 64 processors, CPUID clears the high 32 bits of the RAX/RBX/RCX/RDX registers in all modes
;  On AMD, in 64-bit mode, this instruction (CPUID) works the same as in legacy mode except that it zeroextends 32-bit register results to 64 bits.
;__________________________________________________________________________


section '.text' code readable executable
PB_Init_Processor:
; -----------------------  CPUID availability Detection 

; Détermine si l'instruction CPUID est disponible pour le processeur
; ceci avant toute opération avec CPUID
; Determines if the CPUID instruction is available to the processor 
; before any operation with CPUID
; code based from AMD (40332.pdf), AMD64 Architecture Programmer's Manual, Volumes 1-5 page 165/166
  PUSHFQ                   ; store RFLAGS on stack
  POP    rax               ; store EFLAGS in EAX
  MOV    ecx, eax          ; save in ECX for later testing
  XOR    eax, 0x0200000    ; toggle bit 21
  PUSH   rax               ; push to stack
  POPFQ                    ; save changed EAX to RFLAGS
  PUSHFQ                   ; push RFLAGS to TOS
  POP    rax               ; store EFLAGS in EAX
  CMP    eax, ecx          ; see if bit 21 has changed
  JZ     no_CPUID         ; if no change, no CPUID
  
  ; sauvegarde du résultat (True) dans la variable globale processor_Technologie_Avalaible
  OR     byte [processor_Technologie_Avalaible], processor__CPUID_Avalaible


Get_CPUID_infos:

;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
;■                         CPUID level 0                         ■
;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
; INTEL
;--------
; The ID flag (bit 21) in the EFLAGS register indicates support for the CPUID instruction. If a software procedure can
; set and clear this flag, the processor executing the procedure supports the CPUID instruction. This instruction operates
; the same in non-64-bit modes and 64-bit mode.
;--------
; AMD
; Some processor implementations may Not support the CPUID instruction. Support For the CPUID
; instruction is determined by testing the RFLAGS.ID bit. If software can write this bit, then the CPUID
; instruction is supported by the processor implementation. Otherwise, execution of CPUID results in an
; invalid-opcode exception.
;--------

; retrouve le nombre d'entrées maximales pour les informations de base du CPUID
; ici CPUID est disponible
  MOV    eax, 0                     ; standard Function
; sauvegarde du registre volatile
  PUSH   rbx
  CPUID            
  
; highest value the CPUID recognizes for returning basic processor information.
; The value is returned in the EAX register and is processor specific.
; valeur la plus élevée que le CPUID reconnaît pour renvoyer les informations de base du processeur.
; La valeur est renvoyée dans le registre EAX et est spécifique au processeur.
  MOV    qword [processor__CPUID_Level_0000_0000____Maximum_Input_Value_for_Basic_Function_CPUID_Information], rax
; A vendor identification string is also returned in EBX, EDX, and ECX.
; Une chaîne d'identification du fournisseur est également renvoyée dans EBX, EDX et ECX.

; écriture des 3 registres en mémoire à processor__Vendor_String
   MOV    dword [processor__Vendor_String], ebx
   MOV    dword [processor__Vendor_String+4], edx
   MOV    dword [processor__Vendor_String+8], ecx

; restauration du registre volatile
  POP    rbx
;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
;■                         CPUID level 1                         ■
;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
; Maximum Input Value, check result, CPUID Maximum Value Limit must be >= 1 to get CPUID level 1
  CMP    qword [processor__CPUID_Level_0000_0000____Maximum_Input_Value_for_Basic_Function_CPUID_Information], 1    
  JNAE   CPUID_level_bad_result

; Get    CPUID level 1h  infos
  MOV    eax, 1             ; CPUID level 1 
; sauvegarde du registre volatile rbx
  PUSH   rbx
  CPUID
; processor CPUID Level 1 result EAX  
  MOV    dword [processor__CPUID_Level_0000_0001____ECX_optional_value_none___EAX_return_value], eax
; processor CPUID Level 1 result EBX  
  MOV    dword [processor__CPUID_Level_0000_0001____ECX_optional_value_none___EBX_return_value], ebx
; processor CPUID Level 1 result ECX  
  MOV    dword [processor__CPUID_Level_0000_0001____ECX_optional_value_none___ECX_return_value], ecx
; processor CPUID Level 1 result EDX  
  MOV    dword [processor__CPUID_Level_0000_0001____ECX_optional_value_none___EDX_return_value], edx
; restauration réelle du registre volatile rbx
  POP    rbx
;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
;■                        CPUID level 7h                         ■
;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
; Maximum Input Value, check result, eax must be > = to 1 to get CPUID level 1
  CMP    qword [processor__CPUID_Level_0000_0000____Maximum_Input_Value_for_Basic_Function_CPUID_Information], 7    
  JNAE   CPUID_level_bad_result
; Get    CPUID level 7h  infos
  MOV    eax, 7 
  MOV    ecx, 0   ; sub-leaf
; sauvegarde du registre volatile rbx
  PUSH   rbx
  CPUID
; processor__CPUID_Level_7_EAX.i 
; eax Bits 31 - 00: Reports the maximum input value for supported leaf 7 sub-leaves
  MOV    dword [processor__CPUID_Level_0000_0007____ECX_optional_value_0000_0000___EAX_return_value], eax 
; processor__CPUID_Level_7_EBX.i 
  MOV    dword [processor__CPUID_Level_0000_0007____ECX_optional_value_0000_0000___EBX_return_value], ebx
; processor__CPUID_Level_7_ECX.i 
  MOV    dword [processor__CPUID_Level_0000_0007____ECX_optional_value_0000_0000___ECX_return_value], ecx
; processor__CPUID_Level_7_EDX.i 
  MOV    dword [processor__CPUID_Level_0000_0007____ECX_optional_value_0000_0000___EDX_return_value], edx
; restauration réelle du registre volatile rbx
  POP    rbx


include '\Level_0x80000000\Level_0x80000000__x64.asm'
include '\Level_0x80000000\Level_0x80000001__x64.asm'
include '\Level_0x80000000\Level_0x80000002__x64.asm'
include '\Level_0x80000000\Level_0x80000003__x64.asm'
include '\Level_0x80000000\Level_0x80000004__x64.asm'
include '\Level_0x80000000\Level_0x80000006__x64.asm'
include '\Level_0x80000000\Level_0x80000007__x64.asm'
include '\Level_0x80000000\Level_0x80000008__x64.asm'
include '\Level_0x80000000\Level_0x80000009__x64.asm'
include '\Level_0x80000000\Level_0x8000000A__x64.asm'
include '\Level_0x80000000\Level_0x8000000B__x64.asm'
include '\Level_0x80000000\Level_0x8000000C__x64.asm'
include '\Level_0x80000000\Level_0x8000000D__x64.asm'
include '\Level_0x80000000\Level_0x8000000E__x64.asm'
include '\Level_0x80000000\Level_0x8000000F__x64.asm'
include '\Level_0x80000000\Level_0x80000010__x64.asm'
include '\Level_0x80000000\Level_0x80000011__x64.asm'
include '\Level_0x80000000\Level_0x80000012__x64.asm'
include '\Level_0x80000000\Level_0x80000013__x64.asm'
include '\Level_0x80000000\Level_0x80000014__x64.asm'
include '\Level_0x80000000\Level_0x80000015__x64.asm'
include '\Level_0x80000000\Level_0x80000016__x64.asm'
include '\Level_0x80000000\Level_0x80000017__x64.asm'
include '\Level_0x80000000\Level_0x80000018__x64.asm'
include '\Level_0x80000000\Level_0x80000019__x64.asm'
include '\Level_0x80000000\Level_0x8000001A__x64.asm'
include '\Level_0x80000000\Level_0x8000001B__x64.asm'
include '\Level_0x80000000\Level_0x8000001C__x64.asm'
include '\Level_0x80000000\Level_0x8000001D__x64.asm'
include '\Level_0x80000000\Level_0x8000001E__x64.asm'
include '\Level_0x80000000\Level_0x8000001F__x64.asm'
include '\Level_0x80000000\Level_0x80000020__x64.asm'



  
  
  
  
Processor_Brand_String_Not_Supported:  

; -----------------------  ends with error
no_CPUID:
CPUID_level_bad_result:



EndFunction:
  RET

;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
;■                           variables globales de la fonction                           ■
;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
section '.data' data readable writeable
_ASMG_BSSSection:

; processor_Technologie_Avalaible.q
ASMG_bssalign 8
Public processor_Technologie_Avalaible
processor_Technologie_Avalaible:
  dq  0
;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
;■                  CPUID level 0 storing values                 ■
;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
; cette variable recevra les valeurs respectives du registre EAX
; CPUID Maximum Value Limit
Public processor__CPUID_Level_0000_0000____Maximum_Input_Value_for_Basic_Function_CPUID_Information
processor__CPUID_Level_0000_0000____Maximum_Input_Value_for_Basic_Function_CPUID_Information:
  dq  0

; Début de la chaîne d'identification du fournisseur renvoyée dans EBX, EDX et ECX, stocké en en Unicode.
; 24 caractères (ascci ->> unicode + un zéro de fin de chaine unicode)
Public processor__Vendor_String
processor__Vendor_String:
  db 12 dup 0
;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
;■                  CPUID level 1 storing values                 ■
;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
; ces variables recevront les valeurs respectives des registres EAX, EBX, ECX et EDX
; après l'apel de CPUID avec EAX = 1

Public processor__CPUID_Level_0000_0001____ECX_optional_value_none___EAX_return_value
processor__CPUID_Level_0000_0001____ECX_optional_value_none___EAX_return_value:
  dq  0
  
Public processor__CPUID_Level_0000_0001____ECX_optional_value_none___EBX_return_value
processor__CPUID_Level_0000_0001____ECX_optional_value_none___EBX_return_value:
  dq  0

Public processor__CPUID_Level_0000_0001____ECX_optional_value_none___ECX_return_value
processor__CPUID_Level_0000_0001____ECX_optional_value_none___ECX_return_value:
  dq  0

Public processor__CPUID_Level_0000_0001____ECX_optional_value_none___EDX_return_value
processor__CPUID_Level_0000_0001____ECX_optional_value_none___EDX_return_value:
  dq  0
;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
;■                 CPUID level 7h storing values                 ■
;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
; ces variables recevront les valeurs respectives des registres EAX, EBX, ECX et EDX
; après l'apel de CPUID avec EAX = 7h

Public processor__CPUID_Level_0000_0007____ECX_optional_value_0000_0000___EAX_return_value
processor__CPUID_Level_0000_0007____ECX_optional_value_0000_0000___EAX_return_value:
  dq  0

Public processor__CPUID_Level_0000_0007____ECX_optional_value_0000_0000___EBX_return_value
processor__CPUID_Level_0000_0007____ECX_optional_value_0000_0000___EBX_return_value:
  dq  0

Public processor__CPUID_Level_0000_0007____ECX_optional_value_0000_0000___ECX_return_value
processor__CPUID_Level_0000_0007____ECX_optional_value_0000_0000___ECX_return_value:
  dq  0

Public processor__CPUID_Level_0000_0007____ECX_optional_value_0000_0000___EDX_return_value
processor__CPUID_Level_0000_0007____ECX_optional_value_0000_0000___EDX_return_value:
  dq  0


include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000000__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000001__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000002__x64.asm'
;include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000003__x64.asm'
;include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000004__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000006__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000007__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000008__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000009__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x8000000A__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x8000000B__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x8000000C__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x8000000D__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x8000000E__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x8000000F__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000010__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000011__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000012__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000013__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000014__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000015__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000016__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000017__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000018__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000019__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x8000001A__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x8000001B__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x8000001C__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x8000001D__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x8000001E__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x8000001F__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000020__x64.asm'
and for example the Brand string asm file

Code: Select all

;
;       X64 UNICODE
;
;********************************************************
;        Processor__Brand_String.i 
;           (
;             bufferBrand.i
;           )
;
;   Description :
;   -------------
;   Recopie la chaine définissant la marque du processeur du processeur dans le buffer passé en paramètre
;********************************************************

format MS64 COFF
public PB_Processor__Brand_String

;--------------------------------------------------------
;       include files
;--------------------------------------------------------
include '..\Processor_CPUID_Constants.inc'
include '..\..\Constantes_PureBasic_x64.inc'
;--------------------------------------------------------
;       paramètre de la fonction
;--------------------------------------------------------
; bufferBrand.i
bufferBrand  equ rsp+8
;--------------------------------------------------------
;       variables globales librairie : données CPUID
;--------------------------------------------------------
extrn processor__CPUID_Level_8000_0000____Maximum_Input_Value_for_Extended_Function_CPUID_Information
extrn processor__Brand_String
;--------------------------------------------------------
;       section code
;--------------------------------------------------------

;__________________________________________________________________________
; les registres volatiles PB sont :
; RAX, RCX, RDX, R8, R9, XMM0, XMM1, XMM2 et XMM3

; les registres volatiles MS sont :
;    RAX : Return value register
;    RCX, RDX, R8, R9 : First to fourth integer argument
;    R10, R11 : used in syscall/sysret instructions
;    XMM0 à XMM5 : First to sixth FP argument when __vectorcall is used
;    YMM0 à YMM5 : First to sixth FP argument when __vectorcall is used
;    YMM6:YMM15 : partie supérieure des registres
;    ZMM0-ZMM15 : partie supérieure des registres
;__________________________________________________________________________


section '.text' code readable executable
PB_Processor__Brand_String:
; sauvegarde du paramètre sur la pile
 ; MOV    qword [bufferBrand], rcx

; Check pointer bufferBrand (0 = error)
  TEST   rcx, rcx
  JZ     Error__bufferBrand_Null

; check result level 0x80000000/0x80000004
  MOV    r8d, dword [processor__CPUID_Level_8000_0000____Maximum_Input_Value_for_Extended_Function_CPUID_Information]
  TEST   r8d, 0x80000000
  JZ     Error__bufferBrand_Null
  CMP    r8d, 0x80000004
  JNAE   Error__bufferBrand_Null

; rdx point original first Ascii string level 0x80000002 (processor__Brand_String)
  MOV    rdx , processor__Brand_String
; r8 point destination buffer (bufferBrand)
  MOV    r8, rcx
; loop counter, 48 Ascii char to recopy
  MOV    rcx, 48
; Ascii char to Unicode char, so upper part of ax to 0
  MOV    ax, 0
; loop start  
.write_Brand_String:
; al = Ascii char
  MOV    al, [rdx]
; write Unicode char to destination buffer 
  MOV    [r8], ax
; increment pointers  
  INC    rdx
  ADD    r8, 2
; first decrement ecx and after test it to 0, jmp if no 0 to .write_Brand_String
  LOOP   .write_Brand_String
; write 0 of end string (adresse buffer base + 96)
  MOV    word [r8], 0
	
Ok:
; it's Ok, return #True
  MOV    rax, True


EndFunction:
  RET
;------------------ Errors ------------------
Error__bufferBrand_Null:
; error, return #False
  XOR    rax, rax
  JMP    EndFunction
and a tipical PB call of this function, the buffer receives unicode format of the string
on my computer : Intel(R) Core(TM) i5-7400 CPU @ 3.00GHz
(CPUID level 80000002h, CPUID level 80000003h & CPUID level 80000004h)
code for 80000002h, it's close for 80000003h & level 80000004h

Code: Select all

;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
;■                     CPUID level 80000002h                     ■
;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
; Get    CPUID level 80000002h  infos
  MOV    eax, 80000002h
; sauvegarde du registre volatile rbx
  PUSH   rbx
  CPUID
; ; processor CPUID Level 80000002h result EAX
  MOV    dword [processor__Brand_String], eax
; ; processor CPUID Level 80000002h result EBX
  MOV    dword [processor__Brand_String+4], ebx
; ; processor CPUID Level 80000002h result ECX
  MOV    dword [processor__Brand_String+8], ecx
; ; processor CPUID Level 80000002h result EDX
  MOV    dword [processor__Brand_String+12], edx
; restauration  du registre volatile rbx
  POP    rbx

Code: Select all

      *bufferBrand = AllocateMemory(98)
      If *bufferBrand = #Null
            MessageRequester(Error, BadAllocateMemory, #PB_MessageRequester_Error)
            End
      EndIf
      
      If Processor__Brand_String(*bufferBrand) = #False
            MessageRequester(Error, BadAllocateMemory, #PB_MessageRequester_Error)
            FreeMemory(*bufferBrand)
            End
      EndIf
      
      Debug  PeekS(*bufferBrand)
A+
Denis
Denis
Enthusiast
Enthusiast
Posts: 704
Joined: Fri Apr 25, 2003 5:10 pm
Location: Doubs - France

Re: Unable to get UserLibraries lib function adress

Post by Denis »

and for example the generic function to detect
AVX, FMA, VAES, VPCLMULQDQ, but ...
i use XGETBV without detecting if it is supported, so a lot of work is comming for me
The example is based on an Intel code inside the monumental documentation ...

Code: Select all

;
;       X64 UNICODE
;
;********************************************************
;       Processor__Generic_Is_Function.i 
;           (
;             function_Flag.i
;           )
;
;   Description :
;   -------------
;   Fonction générique de détection de fonctions telles que :
;   AVX, FMA, VAES, VPCLMULQDQ
;********************************************************

format MS64 COFF
public PB_Processor__Generic_Is_Function

;--------------------------------------------------------
;       include files
;--------------------------------------------------------
include '..\Processor_CPUID_Constants.inc'
;--------------------------------------------------------
;       paramètre de la fonction
;--------------------------------------------------------
; function_Flag (Integer)
function_Flag  equ rsp+8
;--------------------------------------------------------
;       section code
;--------------------------------------------------------

;__________________________________________________________________________
; les registres volatiles PB sont :
; RAX, RCX, RDX, R8, R9, XMM0, XMM1, XMM2 et XMM3

; les registres volatiles MS sont :
;    RAX : Return value register
;    RCX, RDX, R8, R9 : First to fourth integer argument
;    R10, R11 : used in syscall/sysret instructions
;    XMM0 à XMM5 : First to sixth FP argument when __vectorcall is used
;    YMM0 à YMM5 : First to sixth FP argument when __vectorcall is used
;    YMM6:YMM15 : partie supérieure des registres
;    ZMM0-ZMM15 : partie supérieure des registres
;__________________________________________________________________________


section '.text' code readable executable
PB_Processor__Generic_Is_Function:
; sauvegarde du paramètre sur la pile
; MOV    qword [function_Flag], rcx
  MOV    r8, rcx

; result returned in eax

  MOV    eax, 1
  CPUID            
  AND    ecx, r8           ; example for AVX : Flag = 0x018000000
  CMP    ecx, r8           ; check desired feature flags
  JNE    not_supported
; processor supports features
  MOV    ecx, 0            ; specify 0 for XFEATURE_ENABLED_MASK register
  XGETBV                   ; result in EDX:EAX
  AND    eax, 0x06
  CMP    eax, 0x06         ; check OS has enabled both XMM   AND    YMM State support
  JNE    not_supported
; return #true If function (determined by function_Flag) is supported else #False  
  MOV    eax, 1            ; mark as supported

.EndFunction:
  RET

;------------------ Errors ------------------
not_supported:
; return #true If function (determined by function_Flag) is supported else #False  
  MOV    eax, 0            ; mark as not supported
  JMP    .EndFunction
A+
Denis
User avatar
Mijikai
Addict
Addict
Posts: 1360
Joined: Sun Sep 11, 2016 2:17 pm

Re: Unable to get UserLibraries lib function adress

Post by Mijikai »

What exactly are you doing with prototypes?
Im still not sure what exactly the problem is :?

If your question is how to get access to your UserLib written in FASM from PB i do it like this :)
I recoded the function to get the ProcessorBrand (only vendor) in FASM:

Code: Select all

;compile as dummy.obj

format MS64 COFF
include 'win64a.inc';im so lazy XD

public GetProcessorBrand

section '.text' code readable executable

proc GetProcessorBrand
     locals
        buffer  dq 0x0
     endl
     test rcx,rcx
     jz GetProcessorBrand_Error
     mov [buffer],rcx
     mov eax,0x80000000
     cpuid
     cmp eax,0x80000004
     jl GetProcessorBrand_Error
     xor rax,rax
     cpuid
     mov rax,[buffer]
     mov dword[rax],ebx
     mov dword[rax + 0x4],edx
     mov dword[rax + 0x8],ecx
     mov rax,0x1
     ret
     GetProcessorBrand_Error:
     xor rax,rax
     ret
endp 

In PureBasic i use the Import function (doesnt matter if its compiled to a *.lib or not):

Code: Select all

EnableExplicit

Import "dummy.obj"
  GetProcessorBrand.i(*Buffer)
EndImport

Procedure.i Main()
  Protected *mem
  *mem = AllocateMemory(16)
  If *mem
    If GetProcessorBrand(*mem);<- only vendor really :>
      Debug PeekS(*mem,12,#PB_Ascii)  
    EndIf
    FreeMemory(*mem)
  EndIf
  ProcedureReturn #Null  
EndProcedure

Main()

End
Denis
Enthusiast
Enthusiast
Posts: 704
Joined: Fri Apr 25, 2003 5:10 pm
Location: Doubs - France

Re: Unable to get UserLibraries lib function adress

Post by Denis »

Mijikai
What exactly are you doing with prototypes?
I trying to add examples and for some function, i will emulate a false return (failure) value and load the correct function with prototype, i.e. another asm function written if the Is_xx() function failed.

There are interesting examples on the forum for such functions.

Prototypes exist in FASM, but I haven't done any testing yet.

About import, i only use it for .lib function not created with PB.
The way you show me is very interesting, thank you very much. :D
A+
Denis
User avatar
Mijikai
Addict
Addict
Posts: 1360
Joined: Sun Sep 11, 2016 2:17 pm

Re: Unable to get UserLibraries lib function adress

Post by Mijikai »

U could use a jmp gate.

FASM:

Code: Select all

format MS64 COFF
include 'win64a.inc'

public GetProcessorBrand

section '.text' code readable executable

GetProcessorBrand1:
     mov rax,0x0
     jmp GetProcessorBrand_Check

GetProcessorBrand2:
     mov rax,0x1
     jmp GetProcessorBrand_Check

proc GetProcessorBrand
     jmp qword[fnc]
     GetProcessorBrand_Check:
     cmp rax,0x1;<- check for failure
     je GetProcessorBrand_Return
     mov rax,[fnc];<- if the first call to the function failed we change its route
     xchg [fnc + 0x8],rax
     mov [fnc],rax
     xor rax,rax
     GetProcessorBrand_Return:
     ret
endp

section '.data' data readable writeable
        fnc:
        dq GetProcessorBrand1
        dq GetProcessorBrand2
PB:

Code: Select all

EnableExplicit

Import "dummy.obj"
  GetProcessorBrand.i()
EndImport

Procedure.i Main()
  Debug GetProcessorBrand();<- call fails / internal function route changes
  Debug GetProcessorBrand();<- now it works :>
  ProcedureReturn #Null  
EndProcedure

Main()

End
Denis
Enthusiast
Enthusiast
Posts: 704
Joined: Fri Apr 25, 2003 5:10 pm
Location: Doubs - France

Re: Unable to get UserLibraries lib function adress

Post by Denis »

yeah,
another interesting way! :wink:
A+
Denis
freak
PureBasic Team
PureBasic Team
Posts: 5929
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Re: Unable to get UserLibraries lib function adress

Post by freak »

So where is the bug?
quidquid Latine dictum sit altum videtur
Denis
Enthusiast
Enthusiast
Posts: 704
Joined: Fri Apr 25, 2003 5:10 pm
Location: Doubs - France

Re: Unable to get UserLibraries lib function adress

Post by Denis »

So where is the bug?
(See the first post)
for example for the fonction of my userlib Is_MMX()

Code: Select all

*pt = @Is_MMX()
is not supported
A+
Denis
freak
PureBasic Team
PureBasic Team
Posts: 5929
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Re: Unable to get UserLibraries lib function adress

Post by freak »

That was never supported. So it is not a bug, especially not one for the C backend.
quidquid Latine dictum sit altum videtur
infratec
Always Here
Always Here
Posts: 6817
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Unable to get UserLibraries lib function adress

Post by infratec »

@freak
So it is not possible to create a thread with a lib function?
Because there I need

Code: Select all

CreateThread(@xyz(), 0)
If @xyz() is not supported with lib functions I can not use them as a thread.
Is this correct?
Post Reply