QB64.org Forum

Active Forums => QB64 Discussion => Topic started by: NOVARSEG on December 03, 2020, 11:53:46 pm

Title: Fun with CALL ABSOLUTE
Post by: NOVARSEG on December 03, 2020, 11:53:46 pm
Some fun with CALL ABSOLUTE
code not tested. Maybe someone might try to get it to work?

DIM apple AS LONG ' 4bytes
DIM string AS STRING * 20 'reserve space for ASM code

DEF SEG = VARSEG(apple)
FOR x% = 0 to 11
READ d%

DATA &h66,&hb8,&ha0,&h86,&h01,&h00,&h66,&ha3,&h00,&h00,&hcb"
POKE (VARPTR(apple) + 4 + x%),d%)
next x%
CALL ABSOLUTE(VARPTR(apple) + 4)

DEF SEG  'put DS where it was

PRINT apple  ' should = 100000
****

here is the assembler code  encoded in the DATA
'mov eax,100000
'mov [[0]],eax  'the single brackets would not show on the site so had to use 2 brackets.
'RETF
****
 
In mov [[0]],eax   the offset might not be zero.  In Quick Basic the offset is 6 If DS was pointing to start of BC_DATA segment. 

got the idea from https://scruss.com/qbasic_hlp/T008A.html

here is a site where you can disassemble code  http://shell-storm.org/online/Online-Assembler-and-Disassembler/?inst=mov+ax%2C0%0D%0Aretf&arch=x86-16&as_format=inline#assembly

Quite a few of the online assemblers put a 66h in front of  an opcode when it shouldn't - be careful!

**** So QB knows where the variable "apple" is in memory but the ASM code does not really know unless the offsets are predictable.
Title: Re: Fun with CALL ABSOLUTE
Post by: luke on December 04, 2020, 08:02:51 am
Watching you on this pointless crusade to use 16 bit memory commands is painful, like watching a person trying to shoot themselves in the foot but unsure how to load and fire a gun. Please stop.
Title: Re: Fun with CALL ABSOLUTE
Post by: SMcNeill on December 04, 2020, 08:27:04 am
Watching you on this pointless crusade to use 16 bit memory commands is painful, like watching a person trying to shoot themselves in the foot but unsure how to load and fire a gun. Please stop.

+1
Title: Re: Fun with CALL ABSOLUTE
Post by: bplus on December 04, 2020, 01:10:00 pm
Hey when your avatar name is NOVARSEG?

Is that a complaint?

Can't be: http://www.qb64.org/wiki/VARSEG

I suspect this forum a last Bastian of true QBasic die-hards.

There is this: http://masm32.com/board/index.php?topic=8287.0
Maybe NOT that particular board but the forum has a guy working on Basic for Masm.
I met jj2007 at BP.org

Here this Board, maybe?
http://masm32.com/board/index.php?board=57.0
Title: Re: Fun with CALL ABSOLUTE
Post by: Pete on December 04, 2020, 02:13:04 pm
We had a guy post at The QBasic forum some months ago who used this stuff extensively in game programs. The were really very ell built games, but because of his reliance on what I call address programming, there was no way to convert what he made to QB64 without a complete rewrite of several hundreds of lines of code.

LOL@luke's comment. Gave up on dry humor?

@footshooter: I'm glad you like the 16-bit stuff, and there was a time when the push to get QB64 100% QB compatible was of greater importance. There was a push that succeeded in limited support for some library functions but because there were so many as well as QB "features" like DEF FN, eventually the push fell by the wayside. Further development  was probably deemed just too much time and trouble for the limited use and at least DEF FN has a straight forward way for coders to put those statements into traditional functions. Rob did include CALL INTERRUPT mouse support in QB64, which can be used in place of the CALL ABSOLUTE mouse routines; but I get it, we all miss some of the older 16-bit stuff at times, especially if a large completed program can no longer be resurrected. QB64, of course, has its own mouse keywords, too.

Pete
Title: Re: Fun with CALL ABSOLUTE
Post by: SpriggsySpriggs on December 04, 2020, 02:17:06 pm
Watching you on this pointless crusade to use 16 bit memory commands is painful, like watching a person trying to shoot themselves in the foot but unsure how to load and fire a gun. Please stop.

++++++1
Title: Re: Fun with CALL ABSOLUTE
Post by: SpriggsySpriggs on December 04, 2020, 02:31:16 pm
Some fun with CALL ABSOLUTE
code not tested. Maybe someone might try to get it to work?

Why not test it first yourself? You know what the code is trying to accomplish and why it is written in such a fashion.
Title: Re: Fun with CALL ABSOLUTE
Post by: bplus on December 04, 2020, 03:03:15 pm
What is the attraction? Is it the 16 bit simplicity or getting down close to assembler calls, I thought it was the later.

If it's 16 bit simplicity that is like preferring screen 0 over _NEWIMAGE(yourWidth, yourHeight, 32 = millions of colors for all kinds of graphics) ;-))

But screen 0 still has purpose.
Title: Re: Fun with CALL ABSOLUTE
Post by: Pete on December 04, 2020, 03:04:39 pm
If it's 16 bit simplicity that is like preferring screen 0 over _NEWIMAGE(yourWidth, yourHeight, 32 = millions of colors for all kinds of graphics) ;-))

Now you're getting it!

Pete :D

SCREEN 0, the only screen any real programmer would ever need.
Title: Re: Fun with CALL ABSOLUTE
Post by: NOVARSEG on December 04, 2020, 04:40:10 pm
OK thanks everyone.

That was the first time I used CALL ABSOLUTE.  These types of commands were popular in the day.

QB64 supports CALL ABSOLUTE. so that is the main reason I posted.

I think this CALL ABSOLUTE could be used for fast string operations

say two strings are dimensioned like:

DIM string1 AS STRING * 16384
DIM string2 AS STRING * 16384

The code I posted is basically a way to access these strings through ASM code.

Example, lets say you want to encrypt string2 by XORing the bytes in string1 with string2

The ASM code can do that as long as it knows the location of the DIMed strings.


Title: Re: Fun with CALL ABSOLUTE
Post by: bplus on December 04, 2020, 05:22:55 pm
Well now I wonder if _MEM stuff doesn't give same access to the bits and bytes to analyse and process strings fast!
Title: Re: Fun with CALL ABSOLUTE
Post by: NOVARSEG on December 04, 2020, 08:03:18 pm
what is the best way to XOR the bytes in string2 with bytes in string1?

I was thinking of using MID$ (in quick basic) but from past experience that is too slow

how do you use the memory functions in QB64 to do that.

DIM string1 AS STRING * 16384
DIM string2 AS STRING * 16384

Procedure is to get the first byte from string1 and store it  in  A%. Then get the first byte from string2 and XOR it with A%. Then replace the first byte of string2 with A%

Repeat for every byte.
Title: Re: Fun with CALL ABSOLUTE
Post by: SMcNeill on December 04, 2020, 08:15:26 pm
DIM string1 AS STRING * 16384
DIM string2 AS STRING * 16384

DIM m1 AS _MEM, m2 AS _MEM
DIM b1 AS _BYTE, b2 AS _BYTE
m1 = _MEM(string1): m2 = _MEM(string2)

FOR i = 0 TO 16383
    _MEMGET m1, m1.OFFSET + i, b1
    _MEMGET m2, m2.OFFSET + i, b2
    b3 = b1 XOR b2
    ‘Do whatever you want with b3 
NEXT

(Though in this case, I’d read as _UNSIGNED _INTEGER64’s, to reduce processes by 1/8th.)



I direct all questions to my mem video series.  I suggest starting there.  https://www.qb64.org/forum/index.php?topic=1731.0
Title: Re: Fun with CALL ABSOLUTE
Post by: NOVARSEG on December 04, 2020, 08:32:48 pm
SMcNeill

Thanks.  Looking at _MID in the wiki.

Watching your videos. That is interesting on how binary file access is similar to _MEM

XOR 8 bytes at a time would be fast.

Title: Re: Fun with CALL ABSOLUTE
Post by: bplus on December 04, 2020, 08:55:48 pm
ASC(String$, i) will get you numbers instead of letters fast! as opposed to MID$(String$, start (strings are base 1), lengthOfSlice) which will give a slice of the string.
Title: Re: Fun with CALL ABSOLUTE
Post by: Richard on December 04, 2020, 10:54:37 pm
Quote from Steve

Quote
DIM string1 AS STRING * 16384
DIM string2 AS STRING * 16384

DIM m1 AS _MEM, m2 AS _MEM
DIM b1 AS _BYTE, b2 AS _BYTE
m1 = _MEM(string1): m2 = _MEM(string2)

FOR i = 0 TO 16383
    _MEMGET m1, 1.OFFSET + i, b1
    _MEMGET m2, m2.OFFSET + i, b2
    b3 = b1 XOR b2
    ‘Do whatever you want with b3
NEXT

(Though in this case, I’d read as _UNSIGNED _INTEGER64’s, to reduce processes by 1/8th.)

@Steve

I am unclear of your comment in the (...) - do you mean having

 i as _UNSIGNED_INTEGER64

or for the whole line(s)

_MEMGET m1, 1.OFFSET + i, b1



Also, when you say reduce processes by 1/8 - many people use conflicting interpretations - so do you mean the final timings are

original - 1/8  = ~88% of original time

OR

original *1/8  = ~12% of original time


In any case, how would you write the most time-efficient code for the example task as above?
Title: Re: Fun with CALL ABSOLUTE
Post by: SMcNeill on December 05, 2020, 01:06:22 am
DIM string1 AS STRING * 16384
DIM string2 AS STRING * 16384

DIM m1 AS _MEM, m2 AS _MEM
DIM b1 AS _UNSIGNED _INTEGER64, b2 AS _UNSIGNED _INTEGER64, b3 AS _UNSIGNED _INTEGER64
m1 = _MEM(string1): m2 = _MEM(string2)

FOR i = 0 TO 16383 STEP 8
    _MEMGET m1, m1.OFFSET + i, b1
    _MEMGET m2, m2.OFFSET + i, b2
    b3 = b1 XOR b2
    ‘Do whatever you want with b3
NEXT

b1, b2, b3 are all UINT64s above, so I’m reading and processing 8 bytes at a time, rather than 1, allowing me to STEP 8 in my FOR loop.  You’ll have 1/8th the reads and comparisons, being a lot faster in the end.
Title: Re: Fun with CALL ABSOLUTE
Post by: NOVARSEG on December 05, 2020, 01:36:42 am
Would this work?


FOR i = 0 TO 16383 STEP 8
 
   _MEMGET m1, 1.OFFSET + i, b1
   _MEMGET m2, m2.OFFSET + i, b2
   _MEMPUT m2, m2.OFFSET + i, b2 XOR b1
   
NEXT
Title: Re: Fun with CALL ABSOLUTE
Post by: SMcNeill on December 05, 2020, 02:04:39 am
Would this work?


FOR i = 0 TO 16383 STEP 8
 
   _MEMGET m1, 1.OFFSET + i, b1
   _MEMGET m2, m2.OFFSET + i, b2
   _MEMPUT m2, m2.OFFSET + i, b2 XOR b1
   
NEXT

No idea without testing.  b1 XOR b2 gives what variable type as a return answer, by default?  Are you trying to put a SINGLE value where your UINT64 was?  You can try it and see, but it’s not the way I’d personally do things.  You might try specifying AS _UNSIGNED _INTEGER64 on the end of that last line, but honestly, I’m not certain how  permissive QB64 would be with that style syntax.

All I can do is say test it and experiment.
Title: Re: Fun with CALL ABSOLUTE
Post by: NOVARSEG on December 05, 2020, 02:28:01 am
Forgot that b3 was DIMed

**Encrypt
FOR i = 0 TO 16383 STEP 8
 
   _MEMGET m1, m1.OFFSET + i, b1
   _MEMGET m2, m2.OFFSET + i, b2
    b3 = b1 XOR b2
  _MEMPUT m2, m2.OFFSET + i, b3
   
NEXT

**Decrypt
FOR i = 0 TO 16383 STEP 8
 
   _MEMGET m1, m1.OFFSET + i, b1
   _MEMGET m2, m2.OFFSET + i, b2
    b3 = b1 XOR b2
  _MEMPUT m2, m2.OFFSET + i, b3
   
NEXT

****
OK there might be a faster way. In assembler you can do
****in general
mov si, offset string1
mov di, offset string2
mov eax, [si + bx]
XOR [di + bx], eax
**etc
4 bytes at a time from string1 XORed with same 4 bytes in string2
there are op code for 8 bytes too:  https://www.felixcloutier.com/x86/xor
To make that look QB-ish

   _MEMGET m1, m1.OFFSET + i, b1
   _XORPUT m2, m2.OFFSET + i, b1  ' 8bytes at a time
Title: Re: Fun with CALL ABSOLUTE
Post by: SMcNeill on December 05, 2020, 07:33:37 am
As much as you like assembler, I’m surprised you don’t just code in it exclusively.  Run both and give us some speed comparison tests.  How much faster and efficient is your assembly routine?  Is it worth the bother?
Title: Re: Fun with CALL ABSOLUTE
Post by: Pete on December 05, 2020, 02:05:06 pm
What Steve, not having... "Fun with CALL ABSOLUTE" yet? This guy reminds me of Chandler, from the QBasic Forum. His mind was stuck in 0's and 1's Land. Me, I have a book on Assembly Language. It was fun for a few routines, back in the QB days, and helped explain how the QB mouse functions worked, but nowadays, it just props up a crooked bar stool in the garage. It is very efficient at dong that.

Pete
Title: Re: Fun with CALL ABSOLUTE
Post by: NOVARSEG on December 05, 2020, 06:29:00 pm

Quote
As much as you like assembler, I’m surprised you don’t just code in it exclusively.  Run both and give us some speed comparison tests.  How much faster and efficient is your assembly routine?  Is it worth the bother?

Just showing another way to do that particular string operation.  However the _MID stuff is already fast and you would need a good reason to tweak what QB64 already has.   I'm very impressed with QB64 - it is miles ahead of any BASIC out there.

Anyway XOR in string operations is  especially useful for file encryption.   I'm sure C++ has an instruction that would essentially compile to the ASM code:
****in general
mov si, offset string1
mov di, offset string2
mov eax, [si + bx]
XOR [di + bx], eax
**etc

So I don't think it would be too hard to create
 _XORPUT m2, m2.OFFSET + i, b1 
I'm no expert in C++