Author Topic: Converting from PB code to Oxygen for getting HDD serial, MB Serial , Bios  (Read 2244 times)

0 Members and 1 Guest are viewing this topic.

Karen Zibowski

  • Guest
Hi
I have a PowerBasic program which I need to convert from PowerBasic to OxygenBasic.  It can
extract out a computer's serial numbers or IDs such as HDD serial, MB Serial , Bios details.

I have attached the program here, and see if any experts here that can convert it to an OxygenBasic program
It would be a useful utility to aid copy protection of your software.

Thank you
Regards
Karen

Mike Lobanovsky

  • Guest
Hi Karen,

Having had a glance through your CombID.inc, I've good news for you: you can have your little proggy converted into at least 3 different modern 32-bit indie BASICs easily. And for all three of them this challenge would be just ... trivial.

The languages are: FBSL (your humble servant), thinBasic (Eros Olmi), and OxygenBasic (Charles Pegge).

I am sure there are yet more BASIC dialects that can handle the challenge successfully with or without Jose's includes. :)

64-bit wise, I think O2 can cope with it OOTB, can't it, Charles? James, can BC9 follow suit in 64 bits as well?



(P.S. Not sure if Brian Alvarez is ready to accept the challenge with his PluriBasic 6.0...)
« Last Edit: March 06, 2018, 11:50:55 AM by Mike Lobanovsky »

jcfuller

  • Guest

I'll pass. My x86 asm is horrid and x64 is non existant.

James
 

Charles Pegge

  • Guest
Here is the cpuid component o2 modification:

1 plings removed from asm instructions

2 ebx register must be preserved, then restored after cpuid execution

3 hiwrd/lowrd redundant

NB CPU serial numbers are not properly implemented after PentiumIII, due to privacy concerns.

Code: [Select]
def hiwrd hiword
def lowrd loword

'===============================================================
'  GetCpuSerial - Returns serial no on Intel CPU
'  http://www.garybeene.com/powerbasic/thread_014065.htm
'  However it is not in the same format as those obtained by C#
FUNCTION GetCpuSerial()  AS STRING
LOCAL t AS DWORD, m AS DWORD, b AS DWORD

local sys mrbx=rbx 'save rbx for global refs

mov eax,1
cpuid
mov t,eax
mov eax,3
cpuid
mov m,edx
mov b,ecx

mov rbx,mrbx 'restore rbx for lobal refs

function=hex$(t,8) & hex$(m,8) & hex$(b,8)

'FUNCTION = HEX$(HIWRD(t),4) &  HEX$(LOWRD(t),4) &  HEX$(HIWRD(m),4) &  _
'HEX$(LOWRD(m),4) &  HEX$(HIWRD(b),4) &  HEX$(LOWRD(b),4)

END FUNCTION

print GetCpuSerial

Mike Lobanovsky

  • Guest
Bravo, Charles! :D

Spotted that very early but waited for you to step in. My FBSL equivalent follows below. Great minds think alike! 8)  :D

Charles Pegge

  • Guest

Not taking care of ebx, at least in o2, is likely to be the most frequent cause of ASM code failure.

One feature I introduced into the o2 Assembler is the ability to automatically downgrade 64bit registers into 32bit registers on a 32bit platform.  Thus rax downgrades to eax. This allows coders to create dual-compatibility assembler very easily.

Attached below is a program to record various CPU characteristics.


Mike Lobanovsky

  • Guest
... ability to automatically downgrade 64bit registers into 32bit registers on a 32bit platform.  Thus rax downgrades to eax.

COOL!!! 8)

(Hutch's eyes are going to bleed though)

Karen Zibowski

  • Guest
Many Thanks Charles and Mike

I tried to compile using your methods for FUNCTION CPUMfc as shown below

Code: [Select]
$ filename "GetCpuMfc_64.exe"
use rtl64

'===============================================================
' CPUMfc - Returns manufacturer name string of CPU
FUNCTION CPUMfc () AS STRING

dim AS STRING* 12  IID

push ebx
 xor eax,eax
 cpuid
 'push edi
' lea edi, lID

 mov[lID],ebx
 mov[lID+4],edx
 mov[lID+8],ecx
 mov eax, IID
 pop ebx

FUNCTION = lID
END FUNCTION       


'----------------------------------
print CPUMfc


but got a compilation error at this line, how to resolve this error?
Code: [Select]
FUNCTION = lID

Thanks in advance

Regards
Karen

Mike Lobanovsky

  • Guest
Karen,

Let's start with the fact that there is no such a thing as LID at all declared as LOCAL in your function. Where do you think PB and/or O2 are supposed to dump their register contents to? :)

Second, don't you find your IID string buffer a bit too tight for 3 * 4 = 12 bytes of register values plus the string's NULL (0) terminator? Asm doesn't know WCHAR's or BSTR's, but rather uses zero terminated CHAR strings.

Charles Pegge

  • Guest
This is a little more tricky then meets the eye. My solution is to short-circuit normal string operations within the function, and dunk straight into a bstring equivalent. (The caller's GC will destroy it after it has been printed, as usual)

Also, use 64bit register rdi to do the addressing.

It will downgrade gracefully for 32bit compilation too. :)

Code: [Select]
$ filename "GetCpuMfc_64.exe"
use rtl64

'===============================================================
' CPUMfc - Returns manufacturer name string of CPU
FUNCTION CPUMfc () AS STRING

'dim AS STRING* 12  IID

 sys IID=getmemory 12
 push rbx
 xor rax,rax
 cpuid
 mov rdi,IID
 mov [rdi+00],ebx
 mov [rdi+04],edx
 mov [rdi+08],ecx
 pop rbx
 mov rax,IID
 return
 'FUNCTION = IID
END FUNCTION       


'----------------------------------
print CPUMfc

Mike Lobanovsky

  • Guest
:o

Do you mean to say the thing keeps track of CPUMfc's BSTR return length all the way since sys IID = getmemory 12 ?!

Incredible!

Charles, you could've written three practical compilers and yet one more 16-bit assembler in place of this super spyware network alone! MI6 + CIA + KGB + MOSSAD and Stasi into the bargain!

:o

(Are rsi/rdi volatile in the O2 assembler?)

Charles Pegge

  • Guest
Mike,

I'm exploiting the fact that all O2's memory allocations ultimately come from SysAllocStringByteLen, whether they are cast as bstrings or sys integer variables. When an o2 function returns a string, it is actually a bstring. The same is true when passing a string byval: it is passed as a bstring.

When a bstring is returned from a function, within an expression, it is logged for deletion after the end of the statement.
In that respect, It is very much like an agent of the secret services, which is why old spies prefer to avoid retirement.

PS
rsi and rdi are volatile in internal functions. Exported functions and callbacks preserve these registers for the caller.

Mike Lobanovsky

  • Guest
Re: PS

Thanks for the clarification! That's actually very cool to have two extra volatile registers within the entire O2 namespace limits. So, is it only rbx that we have to protect/preserve when inlining?

Re: BSTR

I understand pretty clearly what the code does and how it all might be implemented within the engine.

All the more astonished am I by Oxygen's AI that's able to track the output BSTR's essential attribute, its length, miles away back in the code down to a casual assignment of 12 newly allocated bytes to a void pointer IID!!!  :o

Fantastic!

« Last Edit: March 07, 2018, 03:02:45 PM by Mike Lobanovsky »

Charles Pegge

  • Guest
Yes, rbx, rbp, rsp must be treated with care, especially altering all 3 at the same time! rbx holds the location of .bssdata and is used to reference all globals, constants, DLLs and RTLs. rbp is for all locals, params, and return vars.

bstrs are also used for all dynamic arrays and objects. The underlying uniformity, with the length field,  is very useful.

Mike Lobanovsky

  • Guest
Charles,

Have you ever tried to benchmark what it costs to allocate memory via SysAllocStringByteLen vs. straight malloc? BTW where does FreeBASIC pasture, memory wise?