Oxygen Basic
Programming => Problems & Solutions => Topic started by: Karen Zibowski on March 06, 2018, 10:23:12 AM
-
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
-
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...)
-
I'll pass. My x86 asm is horrid and x64 is non existant.
James
-
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.
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
-
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
-
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.
-
... 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)
-
Many Thanks Charles and Mike
I tried to compile using your methods for FUNCTION CPUMfc as shown below
$ 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?
FUNCTION = lID
Thanks in advance
Regards
Karen
-
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.
-
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. :)
$ 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
-
: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?)
-
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.
-
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!
-
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.
-
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?
-
Many Thanks Charles
Good work