QB64.org Forum
Active Forums => QB64 Discussion => Topic started 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.
-
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.
-
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
-
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
-
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
-
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
-
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.
-
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.
-
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.
-
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.
-
Well now I wonder if _MEM stuff doesn't give same access to the bits and bytes to analyse and process strings fast!
-
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.
-
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
-
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.
-
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.
-
Quote from Steve
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?
-
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.
-
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
-
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.
-
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
-
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?
-
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
-
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++