PowerBASIC Forums
  PowerBASIC for Windows
  Use MASM code in PB

Post New Topic  Post A Reply
profile | register | preferences | faq | search

UBBFriend: Email This Page to Someone! next newest topic | next oldest topic
Author Topic:   Use MASM code in PB
Steve Hutchesson
Member
posted April 20, 2005 06:31 AM     Click Here to See the Profile for Steve Hutchesson     Edit/Delete Message   Reply w/Quote
I have on and off needed to use some code from MASM in PB and while
simple mnemonic code translates to PB inline easily enough, due to
the differences between a compiler and an assembler, some forms
don't translate properly. I have just tested out an idea that makes
it a lot easier to port some forms of MASM procedures to PB and it
is because PB properly supports the "db" format for BYTE data.

It take 2 programs, one in MASM to extract the MASM procedure and
save it as a seperate file. This is opened in a toy I wrote years
ago to convert file data to "db" format then place the "db" data
within a PB file and push parameters and call the code.

Below is the code for both. The test procedure is trivial with a MOV
and ADD but it proves the idea works.


; ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл
include \masm32\include\masm32rt.inc
; ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл

comment * -----------------------------------------------------
Build this template with
"CONSOLE ASSEMBLE AND LINK"
----------------------------------------------------- *

.code

start:

; ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл

call main

exit

; ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл

main proc

mov eax, OFFSET terminator
mov ecx, OFFSET starter
sub eax, ecx

test OutputFile("module.pb",ecx,eax), eax

ret

main endp

starter:

; ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл
; д=ў=д=ў=д=ў=д=ў=д=ў=д=ў=д=ў=д=ў=д=ў=д=ў=д=ў=д=ў=д=ў=д=ў=д=ў=д=ў=д=ў=д=ў=д

addit proc arg1 WORD,arg2 WORD

mov eax, arg1
add eax, arg2

ret

addit endp

; д=ў=д=ў=д=ў=д=ў=д=ў=д=ў=д=ў=д=ў=д=ў=д=ў=д=ў=д=ў=д=ў=д=ў=д=ў=д=ў=д=ў=д=ў=д
; ллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл

terminator:

end start

The PB test file.


' #########################################################################
'
' PB Main Template for PBCC
'
' #########################################################################

FUNCTION PBmain as LONG

LOCAL var as DWORD

! push 100
! push 300
! call addit
! mov var, eax

StdOut str$(var)

Exit FUNCTION

addit:
! db 85,139,236,139,69,8,3,69,12,201,194,8,0

End FUNCTION

' #########################################################################

Regards,

hutch at movsd dot com

------------------

IP: Logged

Steve Hutchesson
Member
posted April 20, 2005 07:11 AM     Click Here to See the Profile for Steve Hutchesson     Edit/Delete Message   Reply w/Quote
Here is another version created the same way from two algorithms in
MASM to create and read a character tree that has some of the
characteristics of a binary tree.


' #########################################################################
'
' PB Main Template for PBCC
'
' #########################################################################

#include "\pb\include\win32api.inc"

FUNCTION PBmain as LONG

LOCAL var as DWORD
LOCAL hMem as DWORD
LOCAL cloc as DWORD ' current location in tree
LOCAL pcloc as DWORD

hMem = GlobalAlloc(%GMEM_FIXED or %GMEM_ZEROINIT,1000000)

''' cmp rv(insert_data,pcmd,ptree,ADDR cloc,ebx), -1

pcloc = VarPtr(cloc)

w$ = "test"

! push 1 ; value to write in tree
! push pcloc ; address of current location in tree
! push hMem ; tree memory
! mov eax, w$ ; load string address into EAX
! push eax ; push address
! call insert_data ; call procedure

''' cmp rv(test_data,pcmd,ptree), -1

! push hMem
! mov eax, w$
! push eax
! call test_data

! mov var, eax

StdOut str$(var) ' display value written to the tree with insert_data

GlobalFree hMem

Exit FUNCTION

insert_data:
! db 85,139,236,131,196,252,83,86,87,139,69,16,139,16,137,85
! db 252,51,192,139,125,8,139,77,12,235,5,139,255,131,199,1
! db 138,7,10,192,116,101,128,57,0,117,39,131,121,4,0,117
! db 11,136,1,232,169,0,0,0,235,227,235,125,131,121,8,0
! db 116,7,139,73,8,235,217,235,7,232,131,0,0,0,235,208
! db 235,103,128,57,0,116,98,56,1,117,22,131,121,4,0,116
! db 7,139,73,4,235,183,235,33,232,100,0,0,0,235,177,235
! db 24,56,1,116,20,131,121,8,0,116,7,139,73,8,235,160
! db 235,7,232,74,0,0,0,235,151,235,46,128,57,0,117,16
! db 131,121,4,0,117,10,136,1,139,85,20,137,81,4,235,81
! db 128,57,0,116,20,131,121,8,0,116,7,139,73,8,235,219
! db 235,7,232,26,0,0,0,235,210,139,73,4,59,77,20,117
! db 7,184,255,255,255,255,235,5,184,254,255,255,255,235,34,139
! db 255,131,69,252,12,139,85,12,3,85,252,137,81,8,139,202
! db 195,131,69,252,12,139,85,12,3,85,252,137,81,4,139,202
! db 195,139,77,16,139,85,252,137,17,95,94,91,201,194,16,0

test_data:
! db 85,139,236,51,192,139,85,8,139,77,12,235,3,131,194,1
! db 138,2,10,192,116,26,56,1,117,11,139,73,4,133,201,117
! db 236,235,38,235,34,139,73,8,133,201,117,234,235,27,235,23
! db 131,121,4,0,116,12,128,57,0,116,7,139,73,8,235,240
! db 235,5,139,65,4,235,7,235,5,184,255,255,255,255,201,194
! db 8,0



End FUNCTION

' #########################################################################

Regards,

hutch at movsd dot com

------------------

IP: Logged

Paul Breen
Member
posted April 13, 2006 04:19 PM     Click Here to See the Profile for Paul Breen     Edit/Delete Message   Reply w/Quote
I can't find any background info on the "db" format. I have searched
the data types in the manual. Is this documented for PowerBasic?
This table of some kind seems to be the key to a lot of fast
routines that Hutch posts here. I need a slower expanation of the
"table" part of the code to understand how it works.

------------------
Text consoles are good. If you want graphics, rent a movie.

IP: Logged

Eddy Van Esch
Member
posted April 13, 2006 04:50 PM     Click Here to See the Profile for Eddy Van Esch     Edit/Delete Message   Reply w/Quote
Paul,

The 'db' keyword is just a way to create a table in ASM.
It means that all the numbers following the db keyword are bytes.
There is also: DD, DW, DWD, DWORD
It is mentioned in the chapter 'ASM statements' in the PB help file.

It is basically a handy way to insert numbers (data) in your PB/ASM program.
However, this 'data' can also be assembler code.
To execute that code, you perform a 'call' to the start of code like this:


! call addit
...
addit:
! db 85,139,236,139,69,8,3,69,12,201,194,8,0

'! call addit' jumps to the start of the code, indicated with label 'addit'.
Then the code is executed. Important is that the code must end with an assembler 'RET' opcode. Otherwise, program control never returns.
In this example, the bytes 194,8 are the RET opcode.

Clear as mud?

Kind regards

------------------
Eddy
email: raimundo4u at yahoo dot com
www.devotechs.com -- HIME Huge Integer Math and Encryption library--

IP: Logged

SG Dunn
Member
posted April 13, 2006 04:51 PM     Click Here to See the Profile for SG Dunn     Edit/Delete Message   Reply w/Quote
[deleted as duplicate]

[This message has been edited by SG Dunn (edited April 13, 2006).]

IP: Logged

Eddy Van Esch
Member
posted April 13, 2006 04:57 PM     Click Here to See the Profile for Eddy Van Esch     Edit/Delete Message   Reply w/Quote
Maybe I forgot to mention this important thing.
The assembler code as in :

addit:
! db 85,139,236,139,69,8,3,69,12,201,194,8,0

are not generated 'by hand'. They are the output of an assembler like MASM.

What Steve showed here is a way to assemble code using an assembler like MASM for example, and directly use that code in PB by inserting the opcodes as !db statements ..

Kind regards


------------------
Eddy
email: raimundo4u at yahoo dot com
www.devotechs.com -- HIME Huge Integer Math and Encryption library--

[This message has been edited by Eddy Van Esch (edited April 13, 2006).]

IP: Logged

Paul Breen
Member
posted April 15, 2006 02:51 AM     Click Here to See the Profile for Paul Breen     Edit/Delete Message   Reply w/Quote
Thanks,
every little bit helps. It is the structure of the table that
perplexes me. In the addit:
! db 85,139,236,139,69,8,3,69,12,201,194,8,0
there are only 13 bytes. This will leave some bits "undefined"?.
Is 1 and 2 below the same?
1) asm db 1,2,3
the same as:
2) asm db 1
asm db 2
asm db 3

------------------
Text consoles are good. If you want graphics, rent a movie.

IP: Logged

Steve Hutchesson
Member
posted April 15, 2006 04:46 AM     Click Here to See the Profile for Steve Hutchesson     Edit/Delete Message   Reply w/Quote
Paul,

I probably should have made more sense of this posting in the first
place, Eddy is right that its a method to use code created in another
place with another compiler or an assembler and while it works fine
it does have some serious limitations.

What I was trying to get around is PB does not support external object
modules but because it supports the assembler DB format, you can directly
insert code as DB sequences. The fun part is grabbing the code from
another exe file.

I did it in MASM by putting a label before and after a complete procedure
then writing the code to read the section of binary output between the
labels and save it to a file. I then fed it through a binary to DB
format converter so I have a PB compatible format and pasted it
directly into a PB source code.

The rest is just using PUSH / CALL assembler notation to call the
assembler procedure. Now the major limitation is you can only do this with
a procedure that does no external procedure calls at all, basically
a LEAF procedure as there is no way to get the correct address of
an external function.

It works fine but it has serious limitations in what can be done with it.

Regards,

hutch at movsd dot com

------------------

IP: Logged

Eddy Van Esch
Member
posted April 15, 2006 04:55 AM     Click Here to See the Profile for Eddy Van Esch     Edit/Delete Message   Reply w/Quote
quote:
In the addit:
! db 85,139,236,139,69,8,3,69,12,201,194,8,0
there are only 13 bytes. This will leave some bits "undefined"?.

---I'm not sure I follow you here, Paul. What exactly do you mean by 'bits undefined' ?
This particular db statement simply inserts these 13 bytes in your code. The first one being located at address 'addit'.
By jumping to address addit ('! call addit') this code is executed.

quote:
Is 1 and 2 below the same?
1) asm db 1,2,3
2) asm db 1
asm db 2
asm db 3

---- Yes, they both insert 3 bytes (bytes 1, 2 and 3) in your code.

Kind regards

------------------
Eddy
email: raimundo4u at yahoo dot com
www.devotechs.com -- HIME Huge Integer Math and Encryption library--

[This message has been edited by Eddy Van Esch (edited April 15, 2006).]

IP: Logged

David Gwillim
Member
posted April 15, 2006 09:16 AM     Click Here to See the Profile for David Gwillim     Edit/Delete Message   Reply w/Quote
Now wouldn't it be nice if PB's built-in assembler could handle the MASM
style db for string creation:

db "This is a string that I will terminate with a zero byte",0

Dave

------------------
David Gwillim
Noesis Corporation, NY

noesisdgatoptonlinedotnet

GAIA - the Mother of us all
Isaac Asimov's Gaia

IP: Logged

Steve Hutchesson
Member
posted April 15, 2006 06:51 PM     Click Here to See the Profile for Steve Hutchesson     Edit/Delete Message   Reply w/Quote
David,

2 things, with masm, you need to name the data item so you can reference it.


txtitem db "Hi, I am an ascii text example",0

The other is the CHR$() notation in PB will do this for you.


txtitem chr$("Hi, I am an ascii text example",0)

This is a good capacity in PB that seems to be underused or not
well understood but it makes zero seperated, double zero terminated
text lists easy to write which is the format for Open File dialog
text.

Regards,

hutch at movsd dot com

------------------

IP: Logged

David Gwillim
Member
posted April 15, 2006 08:15 PM     Click Here to See the Profile for David Gwillim     Edit/Delete Message   Reply w/Quote
Hi Hutch,

Sorry for confusing the issue by leaving off the identifier/label
in the MASM db statement. I was just roughly showing the syntax of db.

This compiles in PB:
Asm db "T","h","i","s"," ","i","s"," ","a"," ","s","t","r","i","n","g"

This doesn't:
Asm db "This is a string"

Thanks for the inpriration of using chr$() for putting what is effectively a long text constant
into PB code.

In your use of chr$(), I think you meant:

$textitem = chr$("Hi, I am an ascii text example",0)

or

Sub MySub()
...

textitem$ = chr$("Hi, I am an ascii text example",0)
...
End Sub

The only problem with chr$() used like this is that the limit that can
be assigned to a string constant is 255 bytes, even if you bypass the
line length issue with the line continuation character "_".

textitem$ = $help01 + $help02 + $help03 ... $helpNN

will fail once the concatenation exceeds 255 bytes.

Using asm db there is only the limit of the size of a function/sub whatever
that is. In C I was used to being able to make a zero terminated string constant
as long as I wanted - e.g. for help text.

Up until now the only way that I knew of in PB to do large "constant" strings is to build them
with DATA statements and a loop, or assign individual string constants (<255 bytes)
with sequential assignments:

HelpText$ = $help01
HelpText$ = HelpText$ & $help02
HelpText$ = HelpText$ & $help03
HelpText$ = HelpText$ & $help04
HelpText$ = HelpText$ & $help05
HelpText$ = HelpText$ & $help06
HelpText$ = HelpText$ & $help07
HelpText$ = HelpText$ & $help08
HelpText$ = HelpText$ & $help09
HelpText$ = HelpText$ & $help10
... etc ...

There's no limit to what a string VARIABLE can contain except that set by the OLE engine.

But I just tried chr$() in this role and it works just great! You can do the equivalent of creating a large
text constant and yet have it be very readable in the code.


Function PBMain()
textitem$ = Chr$( _
"This is a quite long string of text that I am going to use to test the maximum size returned by chr()",13,10, _
"This is a quite long string of text that I am going to use to test the maximum size returned by chr()",13,10, _
"This is a quite long string of text that I am going to use to test the maximum size returned by chr()",13,10, _
"This is a quite long string of text that I am going to use to test the maximum size returned by chr()",13,10, _
"This is a quite long string of text that I am going to use to test the maximum size returned by chr()",13,10, _
"This is a quite long string of text that I am going to use to test the maximum size returned by chr()",13,10, _
"This is a quite long string of text that I am going to use to test the maximum size returned by chr()",13,10)

MsgBox Format$(Len(textitem$))
End Function

The above compiles just fine and gives string length report of 721 characters.

Thanks for the inspiration Hutch.

Dave

------------------
David Gwillim
Noesis Corporation, NY

noesisdgatoptonlinedotnet

GAIA - the Mother of us all
Isaac Asimov's Gaia

[This message has been edited by David Gwillim (edited April 16, 2006).]

IP: Logged

Paul Breen
Member
posted April 16, 2006 02:39 AM     Click Here to See the Profile for Paul Breen     Edit/Delete Message   Reply w/Quote
I did a little experimenting with pbcc,winhex and pe explorer.
asm db 65
asm db 66
asm db 67
asm db 67,66,65
waitkey$

This compiles and it answers my own question. You can read
ABCCBA in consequtive addresses in the hex editor.
With pe explorer you can look at the running executable.
I have 30 days to play with the demo from heaven tools, it's fun.

Hutch, what if you put a "marker" or header sequence in memory.
Could you search for that? You might set the masm equivalent of
waitkey$ then use a debugger to copy and paste from memory?

Eddy, about the "undefined bits, before I actually used the hex
editor I thought if we are using 32 bit memory and set an odd
number of bytes, some of the bits would be undefined. I see now
that the "table" consists of consequtive address of a specific number.

------------------
I would take the ring with the intention of doing good, but through me it would wield a power too great and terrible to imagine.

IP: Logged

Steve Hutchesson
Member
posted April 16, 2006 08:53 AM     Click Here to See the Profile for Steve Hutchesson     Edit/Delete Message   Reply w/Quote
Paul,

An assembler is a different animal to a compiler and you can routinely
set labels to module level scope so all you need to do is place one
before a procedure and one after it and perform a trick in the .DATA
section as masm will resolve labels to offsets at assembly time.

Something like this.


label1:

Yourproc proc args etc ....

; your code

Yourproc endp

label2:

In the .DATA section you write a DWORD variable like this.


proclen DD label2 - label1

The variable "proclen" is the number of bytes contained between the two labels.

At runtime, you load the 1st label then write the number of bytes
in the variable directly to disk and you have the exact binary
content of the procedure.

The rest is a conversion to PB notation and call the code using
normal PUSH / CALL syntax and it works fine.

Regards,

hutch at movsd dot com

------------------

IP: Logged

Eddy Van Esch
Member
posted April 16, 2006 03:02 PM     Click Here to See the Profile for Eddy Van Esch     Edit/Delete Message   Reply w/Quote
quote:
Originally posted by Steve Hutchesson:
... then write the number of bytes
in the variable directly to disk and you have the exact binary
content of the procedure.

You can also do this in PB like shown below. Although it would not make much sense to extract code from a PB program and to insert it as databytes into another PB program .. But just to show the trick.

Of course, you have to be careful what you put inside the routine.


#COMPILE EXE
#DIM ALL

FUNCTION PBMAIN AS LONG
LOCAL i AS LONG
LOCAL a AS STRING

'Read bytes of "routine" Lab_Start and store in string
FOR i = CODEPTR(Lab_Start) TO CODEPTR(Lab_End)-1
a = a + HEX$(PEEK(i),2) + " "
NEXT i
MSGBOX a
EXIT FUNCTION


'This "routine" does nothing, just for demo
Lab_Start:
! db 1,2,3,255,0
i = 255
! ADD eax, &h01
! ADD eax, DWORD PTR &h1234
! db 2,4
i = 1
! db &hFF,&hFE
! ret
Lab_End:
END FUNCTION

Kind regards


------------------
Eddy
email: raimundo4u at yahoo dot com
www.devotechs.com -- HIME Huge Integer Math and Encryption library--

[This message has been edited by Eddy Van Esch (edited April 16, 2006).]

IP: Logged

All times are EasternTime (US)

next newest topic | next oldest topic

Administrative Options: Close Topic | Archive/Move | Delete Topic
Post New Topic  Post A Reply
Hop to:

Contact Us | PowerBASIC BASIC Compilers

Copyright й 1999-2007 PowerBASIC, Inc. All Rights Reserved.


Ultimate Bulletin Board 5.45c