The MASM Forum Archive 2004 to 2012

General Forums => The Workshop => Topic started by: jj2007 on October 06, 2009, 08:24:57 PM

Title: MasmBasic
Post by: jj2007 on October 06, 2009, 08:24:57 PM
23 May 2012: MasmBasic resides now in the new Masm32 Forum (http://masmforum.com/~masm32/board/index.php?topic=94.0). See also the online list of functions (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm).

This thread may remain online for some time, but check the new site for the latest edition :wink

(18 May: Try/Catch/Finally uses linker's mapfile to let editor jump to the line that triggered the exception)

MasmBasic is a library that allows to use BASIC syntax in assembler, i.e. it is not a "separate" language but rather a library of macros and routines, fully compatible with MASM (http://www.microsoft.com/downloads/en/details.aspx?familyid=7a1c9da0-0510-44a2-b042-7ef370530c64&displaylang=en) (from version 6.15 upwards, see e.g. version 8.0 (http://www.masm32.com/board/index.php?topic=13529.msg105895#msg105895)), JWasm (http://www.japheth.de/JWasm.html#jwdownload) and the latest Masm32 SDK (version 11) (http://masm32.com/). I wrote it for my own use and pleasure, but since many forum members contributed to it, through good advice and even better algos, I think it is just fair to release it here. The usual disclaimers apply, of course - do not use for military purposes, in hospitals and anywhere else where buggy applications could cause damage. You have been warned :8)

So what exactly is MasmBasic?

Quoteinclude \masm32\MasmBasic\MasmBasic.inc

.code
start:
   GetFiles *.asc
   mov ebx, eax
   Print Str$("%i files found:", ebx), CrLf$, "No.", Tb$, "Name"
   For_ n=0 To ebx-1
      Print Str$("\n#%i\t", n+1), Files$(n)
   Next
   Exit

end start

This snippet (by the way: a full-fledged Windows application :bg) gives the following output:
Quote
50 files found:
No.     Name
#1      BCD.asc
#2      CallDLL.asc
...
#49     TinyRTF.asc
#50     VirtualAllo.asc

As the example shows,
    1. MasmBasic is not BASIC: mov ebx, eax is not part of any BASIC dialect.
    2. MasmBasic is assembly, i.e. it will flawlessly assemble with Microsoft Macro Assembler (MASM, version 6.15 upwards) or, alternatively, with Jwasm (http://www.japheth.de/JWasm.html)

Here is a more complex application. This snippet opens Windows.inc, converts all hexadecimal equates into decimal ones, and writes it back to disk:

Quoteinclude \masm32\MasmBasic\MasmBasic.inc

.code
start:   call Convert
   Exit

Convert proc
LOCAL pos, posAfter, MyTimer, MyCounter
  and MyCounter, 0
  mov MyTimer, Timer
Recall "\Masm32\include\Windows.inc", L$()   ; load an array of strings from file
  mov ebx, eax
  For_ n=0 To ebx-1
   mov pos, Instr_(1, L$(n), "equ", 5)      ; start in pos 1, 1=case-insensitive + 4=full word
   .if pos
      mov esi,
Val(Mid$(L$(n), pos+3, 99))   ; get the numeric value of the string behind equ
      .if signed edx<0                     ; edx returns the number of usable chars; a
         neg edx                        ; negative number indicates a hex$ or bin$ was found
         add edx, pos
         add edx, 3
         mov posAfter, edx
         inc MyCounter
         
Let L$(n)=Left$(L$(n), pos-1)+"EQU "+Str$(esi)+Mid$(L$(n), posAfter)
      .endif
   .endif
  Next
Store "MyWindows.inc", L$()      ; write all strings back to file
  sub MyTimer, Timer
 
Print Str$("\nConverting %i hex equates in Windows.inc to decimals", MyCounter), Str$(" took %i ms\n", 0-MyTimer)
  ret
Convert endp

end start


Output:
QuoteConverting 7676 hex equates in Windows.inc to decimals took 31 ms

MasmBasic comes with RichMasm (http://www.masm32.com/board/index.php?topic=9044): Download the archive at the bottom of this post, and extract it to the root of your Masm32 folder with the "use folder names" option. The editor is configured to give context-sensitive help with the F1 key, and to expand many instructions. For example,
opo [space] will expand to Open "O", #1,
mb becomes MsgBox 0, "¨", "Hi", MB_OK
for_ becomes For_ n=0 To ebx-1 ... Next
ism becomes invoke SendMessage,
etc.; more in \masm32\MasmBasic\MbGuide.rtf (in RichMasm:  File/MasmBasic Guide)

Last but not least an ultra-short Win32 application :wink

include \masm32\MasmBasic\MasmBasic.inc
Init
Credits
Exit
end start


Let me know who is missing :bg

Alphabetical list of available commands (March 2012 - many string functions now have a wide aka Unicode variant):
QuoteApp16, wArrayFill, ArrayMinMax, ArraySearch, ArraySort, Asc, Bin$, Chr$, CL$, wCL$, CatchRTE, ClearLocalVariables, wClip$(), HtmlClip$, Clr, Clr$, ConsoleColor, Copy, CopyData$, Count/wCount, CurDir$, CreateInvoke, CrtDate$, CrtTime$, Cvi, Cvl, Date$, deb, Declare, DefNum, Delete, Dim My$(a, b), Dim MyStruc(99) As RECT, Dim MyDword(x) As DWORD etc, Dll, Erase, Err$, ErrLines, SetErrLine, ExeFolder$, Exist, Exit, ExpandEnv$, Fcmp, FileRead$, FilesDiffer, For_ .. Next, Fsign, GetField, GetFiles, GfSize, GfDate$, GfTime$, GfAgexxx, GetRegVal, gsl, gsl_INIT, gsl_EXIT, Hex$, ImgPaint, Inkey, Input, Insert, Instr_, Kill, LastFileDosName, LastFileName, LastFileSize, Launch, Left$, Len, Let, Locate, Lower$, Ltrim$, Max, Mid$, Min, Mirror$, MouseK, MouseX, MouseY, MovVal, NanoTimer, New$, Open I/O/A/U, PopCount, Print, Print #n, PrintCpu, PrintLine, QSort, QSortDesc, Rand, Recall, Rename, Replace$, Res$(), Right$, Rinstr, Rtrim$, Seek, SendData, wSetClip$, SetField, SetRegVal, Space$, Sqrt, Store, wStr$, String$, StringsDiffer, Swap, ToolTips, Trim$, UnZipFiles, Upper$, Val, Win$()/SetWin$, WinByTitle, wChr$, wData, wInstr, wLeft$/wMid$/wRight$, wLen, wLet, wLower$/wUpper$, wMsgBox, wPrint #n, wRes$, SendControlKey, SetHtmlClip$, wSetWin$, Try/Catch, ZipFiles

Archive moved to the new Masm32 Forum (http://masmforum.com/~masm32/board/index.php?topic=94.0)
Title: Re: MasmBasic
Post by: dedndave on October 06, 2009, 09:02:10 PM
very nice Jochen - i wondered what you were working on - lol   :U
let me play with it a while
Title: Re: MasmBasic
Post by: hutch-- on October 06, 2009, 11:00:02 PM
JJ,

Looks good.  :thumbu

It makes sense to remove a lot of the non-critical hack work so thatwork can be pointed at the type of code that takes time to develop properly.
Title: Re: MasmBasic
Post by: jj2007 on October 06, 2009, 11:23:36 PM
Quote from: hutch-- on October 06, 2009, 11:00:02 PM
JJ,

Looks good.  :thumbu

Thanks :bg

Quote
It makes sense to remove a lot of the non-critical hack work so that work can be pointed at the type of code that takes time to develop properly.

You hit the nail on the head - that's what I intended with this library. Much of this can also be done with Masm32, of course. I chose the Basic syntax because almost everybody with a basic (pun intended) knowledge can intuitively grasp what the above code does. And I tried to keep it newbie-friendly, with boundary checks and runtime error messages etc. This is version 0.9, so to speak. I had a lot of spare time in my holidays, so I could finally complete what was built up over time in The Laboratory. It seems almost bug-free now, but here and there I'll have to polish things. For example, the 200 ms for converting Windows.inc are 95% due to a slow Store L$() routine that writes string by string to a file...
Title: Re: MasmBasic
Post by: newAsm on October 07, 2009, 02:40:34 AM
Hi jj2007,

Is masmbasic.inc available as there is no attachment of it in the forum?

Thanks..newAsm
Title: Re: MasmBasic
Post by: sinsi on October 07, 2009, 02:59:16 AM
"You are not allowed to access this section"
:(
Title: Re: MasmBasic
Post by: dedndave on October 07, 2009, 03:16:13 AM
newasm - he updated the d/l
at one point, it did not have the masmbasic folder
it is straightened out, now
here is the d/l link...
http://www.masm32.com/board/index.php?action=dlattach;topic=9044.0;id=6739
Title: Re: MasmBasic
Post by: BlackVortex on October 07, 2009, 03:19:11 AM
Quote from: dedndave on October 07, 2009, 03:16:13 AM
newasm - he updated the d/l
at one point, it did not have the masmbasic folder
it is straightened out, now
here is the d/l link...
http://www.masm32.com/board/index.php?action=dlattach;topic=9044.0;id=6739
Orly ?

"You are not allowed to access this section "

:P
Title: Re: MasmBasic
Post by: dedndave on October 07, 2009, 03:20:47 AM
i accessed it with no problems
maybe you have violated the terms of the agreement   :lol
or perhaps you have downloaded your daily limit of thunder and glory for today - lol
Title: Re: MasmBasic
Post by: BlackVortex on October 07, 2009, 04:42:16 AM
It doesn't work for Sinsi either, so ...
Title: Re: MasmBasic
Post by: sinsi on October 07, 2009, 05:03:55 AM
OK, I had to go to topic 9044 (richmasm), first post and download the attachment from there. link wtf I guess...
http://www.masm32.com/board/index.php?topic=9044.45

edit: I'll admit it - the code with 'Credits' in it made me want to look  :red
But jj, your friend drunk_sinsi is annoyed :8)
Title: Re: MasmBasic
Post by: BlackVortex on October 07, 2009, 05:09:03 AM
So, correct link is
http://www.masm32.com/board/index.php?action=dlattach;topic=9044.0;id=6740
Title: Re: MasmBasic
Post by: MichaelW on October 07, 2009, 05:24:41 AM
A direct download link provides no context.
Title: Re: MasmBasic
Post by: BlackVortex on October 07, 2009, 06:01:39 AM
Quote from: MichaelW on October 07, 2009, 05:24:41 AM
A direct download link provides no context.
And what does a broken direct link provide ?    :P

Anyway, the archive contains documentation, too.
Title: Re: MasmBasic
Post by: jj2007 on October 07, 2009, 08:16:46 AM
Quote from: dedndave on October 07, 2009, 03:16:13 AM
newasm - he updated the d/l
at one point, it did not have the masmbasic folder
it is straightened out, now
here is the d/l link...
http://www.masm32.com/board/index.php?action=dlattach;topic=9044.0;id=6739

Hi Dave et al,

> at one point, it did not have the masmbasic folder
That seems to be a cache problem - you probaby got an old version of the archive. Yesterday night's version has MasmBasic.inc of 7 October, 56851 bytes. Hitting Control F5 usually forces a reload, but I am not sure if that applies to attachments, too. It seems a frequent problem with the Forum software.

> You are not allowed to access this section
I got the same message now that I am logged in on a different PC. It seems the Forum software allows that kind of direct access only with special tricks; so I took the link away (as Michael noted, it might also be confusing), but for legal reasons users will still have to download it together with RichMasm (http://www.masm32.com/board/index.php?topic=9044).

@sinsi: drunk_sinsi was not included in the credits because for obvious reasons he was not able to make any valuable contributions to this library:green
Title: Re: MasmBasic
Post by: dedndave on October 07, 2009, 08:42:35 AM
it may be browser-specific - i am using firefox
Title: Re: MasmBasic
Post by: hutch-- on October 07, 2009, 09:08:02 AM
JJ,

Just post it at the start of this topic and delete the other one, saves the messing around. I get the same error message and I and the amin here so the file seems not to be at that URL any longer.
Title: Re: MasmBasic
Post by: jj2007 on October 07, 2009, 10:19:27 AM
Quote from: hutch-- on October 07, 2009, 09:08:02 AM
JJ,

Just post it at the start of this topic and delete the other one, saves the messing around. I get the same error message and I and the amin here so the file seems not to be at that URL any longer.

OK, done. Anybody having problems with the fact that SSE2 and ml 6.15+ are needed?
Title: Re: MasmBasic
Post by: hutch-- on October 07, 2009, 11:20:24 AM
JJ,

I installed a new version of masm32 on another partition then tried both running the zip file from the root then running it from the masm32 directory but it did not work as installed. I played musical chairs with the directories until richmasm started and it seemed to run fine but there were still paths for various bits that5 were in the wrong place and would not run.

Certainly different but looks very interesting, about the only thing missing is a good short black. Is there a roadmap as to what should be installed where ?
Title: Re: MasmBasic
Post by: jj2007 on October 07, 2009, 11:41:43 AM
Quote from: hutch-- on October 07, 2009, 11:20:24 AM
JJ,

I installed a new version of masm32 on another partition then tried both running the zip file from the root then running it from the masm32 directory but it did not work as installed. I played musical chairs with the directories until richmasm started and it seemed to run fine but there were still paths for various bits that5 were in the wrong place and would not run.

Certainly different but looks very interesting, about the only thing missing is a good short black. Is there a roadmap as to what should be installed where ?
Hutch,

Which archiver are you using?
Does your archiver restore the tree?
Do you see
\masm32\MasmBasic and
\masm32\RichMasm
??
Title: Re: MasmBasic
Post by: hutch-- on October 07, 2009, 12:33:12 PM
JJ,

I popped it with the current version of Winrar. It has a tree, masm32 and two directories off it, masmbasic & richmasm. Richmasm has two more directories, icons and res.

Unzip it from the root and I get the two directories in the masm32 main directory, MASMBASIC and Richmasm. Richmasm has icons and RES.

If I start Richmasm.exe from its original location it pops a dialog box with the message,

Could not open
L:\masm32\Richmasm\masm32\masmbasic\mbguide.rtf

I moved richmasm.exe to the masm32 main firectory. Created another masm32 directory off the original, moved MASMBASIC as a subdirectory to it, moved RES as a subdirectory of the original masm32 directory and the editor Richmasm.exe starts and find the rtf and ini files it needed.
Title: Re: MasmBasic
Post by: jj2007 on October 07, 2009, 04:45:07 PM
Quote from: hutch-- on October 07, 2009, 12:33:12 PM
Could not open
L:\masm32\Richmasm\masm32\masmbasic\mbguide.rtf

Hutch,

Thanks for the detailed diagnosis. That was an easy one, it's fixed already, new version attached to top of this thread. If richmasm.exe has another time stamp than 7 October, 18:38, press F5 or whatever to get around the cache problem.
Title: Re: MasmBasic
Post by: jj2007 on October 07, 2009, 07:49:00 PM
Quote from: jj2007 on October 06, 2009, 11:23:36 PM
the 200 ms for converting Windows.inc are 95% due to a slow Store L$() routine that writes string by string to a file...

Fixed:
Converting 7676 hex equates in Windows.inc to decimals took 31 ms
(opening the file, reading the strings, converting them, writing back to disk)
Title: Re: MasmBasic
Post by: qWord on October 07, 2009, 11:40:06 PM
very nice jj
that's why i love masm - it gives you the ability to create your own highlevel syntax  :dance:

qWord
Title: Re: MasmBasic
Post by: hutch-- on October 08, 2009, 01:53:00 AM
JJ,

Went in fine, editor started first click, I tested it on a couple of the masm example code apps and got the ASC files to work of the right end menu.

Now I only have one complaint, WHERE THE PHUK is the coffee menu ?


Short Black
Long Black
Cappuccino
Moccacino


There is something seriously wrong when an Italian code editor cannot make coffee.  :P
Title: Re: MasmBasic
Post by: dedndave on October 08, 2009, 03:11:13 AM
should be makin beer - Jochen is German - lol
Title: Re: MasmBasic
Post by: jj2007 on October 08, 2009, 06:40:58 AM
Quote from: hutch-- on October 08, 2009, 01:53:00 AM
Now I only have one complaint, WHERE THE PHUK is the coffee menu ?


Short Black
Long Black
Cappuccino
Moccacino


There is something seriously wrong when an Italian code editor cannot make coffee.  :P

Hutch,

I promise you will get your coffee menu if you can manually write code that does the conversion example in less than 31 ms :toothy
Of course, if Dave is quciker, the menu entry will be called "Beer for dedndave"...!

  mov MyTimer, Timer
Recall "\Masm32\include\Windows.inc", L$() ; convert Windows.inc
mov ebx, eax
For_ n=0 To ebx-1
mov pos, Instr_(1, L$(n), "equ", 5) ; start in pos 1, 1=case-insensitive + 4=full word
.if pos
mov esi, Val(Mid$(L$(n), pos+3, 99))
.if signed edx<0
neg edx
add edx, pos
add edx, 3
mov posAfter, edx
inc MyCounter
Let L$(n)=Left$(L$(n), pos-1)+"EQU "+Str$(esi)+Mid$(L$(n), posAfter)
.endif
.endif
Next
Store "MyWindows.inc", L$() ; write all strings to file
sub MyTimer, Timer
Print Str$("\nConverting %i hex equates in Windows.inc to decimals", MyCounter), Str$(" took %i ms\n", 0-MyTimer)
Title: Re: MasmBasic
Post by: Ficko on October 08, 2009, 07:50:03 AM
Hi JJ!

That's a great job! :U

I was thinking about something simile but never come to realization with it.

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

I have some "observation" you may not aware of running "RichMasm" under Vista.

(A screenshot is attached)

1. The "menu headings - navigation bar -" - like "File, Format etc. - are not displayed.
2. The out put window starts at the right side of the split covering up the buttons sitting there.

Regards,
Ficko
Title: Re: MasmBasic
Post by: jj2007 on October 08, 2009, 12:25:02 PM
Quote from: Ficko on October 08, 2009, 07:50:03 AM
Hi JJ!

That's a great job! :U
Thanks, Ficko  :red

> 1. The "menu headings - navigation bar -" - like "File, Format etc. - are not displayed.

I do not have Vista, but Lingo found a workaround (http://www.masm32.com/board/index.php?topic=9044.msg81519#msg81519): "if we mark "Disable desktop composition" option from Properties\Compatibility of the richmasm.exe all appears OK"

> 2. The out put window starts at the right side of the split covering up the buttons sitting there.

I should fix that indeed. You can drag the search window by clicking into "matches" and holding down the mousekey. The new position will be stored once you save the file.

What about the MasmBasic library (File/New Masm source/MasmBasic)? Did anybody manage to produce a crash, or is it safe for newbies...?
Title: Re: MasmBasic
Post by: jj2007 on October 09, 2009, 07:03:37 PM
Minor update (on top of this thread):
1. The For_ ... Next loop now allows to use eax as counter start or end.

QuotePrint "A square made with three nested For...Next loops:"
            mov eax, 4
            mov ecx, eax
            For_ n1=0 To eax-1
               Print
               For_ n2=0 To ecx-1
                  Print "#"
                  For_ n3=ecx+2 To ecx-1
                     Print "*"
                  Next
               Next n2
            Next

2. In RichMasm, applications that contain a (non-commented) int 3 are assembled, linked and launched in OllyDbg when pressing F6. RichMasm determines automatically if the app is Subsystem Console or Windows, and minimises the console window when Olly is ready. In version 2, RM minimised it only when subsystem console was explicitly set with OPT_Susy Console. Version 3 will minimise the window also if Susy is autodetected.
Title: Re: MasmBasic
Post by: jj2007 on October 15, 2009, 06:50:32 PM
Updated with new functions:

   Insert My$(n)
   Delete My$(n)
   mov A$, New$(100, HEAP_ZERO_MEMORY)   ; 100 zero-initialised bytes
   mov esi, New$(1000)         ; may contain garbage (ok for reading in a known # of bytes)

   MsgBox 0, Win$(hWnd), "The title of the main window:", MB_OK
   .if WinByTitle("- Mozilla", 4)   ; search bits: 4=full word, case sensitive
      Print Win$(eax), 13, 10
   .else
      Print "no Firefox window open", 13, 10
   .endif
   Let Files$(n)=String$(32767, 0)         ; assigns a zero-initialised buffer to Files$(n)
   mov eax, String$(32768-1, "A")         ; assigns a buffer initialised with A to eax
   Print String$(15, "+x")         ; prints +x+x+x+x+x+x+x+x+x+x+x+x+x+x+x
   mov esi, FileRead$("MyFile.dat")   ; creates a string on the heap and reads in the specified file
   Launch "Notepad.exe"
   Launch "Notepad.exe MyNewFile.txt"
   Launch "Notepad.exe MyNewFile.txt", SW_MINIMIZE
   Launch "Notepad.exe MyNewFile.txt", SW_MAXIMIZE, 2000   ; cmd, show, timeout in ms

   deb 1, "The first loop", ecx, esi$, edi$, MyReal10, ST(1)
   deb 2, "Second loop:", al, ecx, esi$, $My$
   The debug macro preserves registers but not flags
   can show FPU registers once but trashes them afterwards
   the string content of registers can be shown by using esi$
   global and local variables can be shown as strings by using e.g. $buffer
   cancelling deb 1, ... does not cancel deb 2, ..., so you can test several loops in one go
   deb 1, ... deb 4, ... are being displayed, while deb 5, writes to a file:
   deb 5, "ToFile", eax, esi$, edi$ saves contents (without showing them) to DebLog.txt

Download version 4 on top of thread.
Title: Re: MasmBasic
Post by: hutch-- on October 16, 2009, 08:58:29 AM
JJ,

While I remember inbetween database servers not working etc ... with a tool that has as much development as RichMasm, it would be to its advantage to be able to specify how and where it gets set up in terms of paths of any support files it needs to run. Probably just a dialog box with path slots and common dialog boxes would do the job but it would make it a lot easier for potential users to get it going and configure it the way they like.
Title: Re: MasmBasic
Post by: qWord on October 16, 2009, 02:44:36 PM
jj,
While taking a quick view on your macros, I've found the macro 'cStyle$'. There are some bugs in it: e.g. for an escape sequence followed by an single character ("\nX") or for two or more esc.seq. in a row ("\n\t\n"). I've modified your macro a bit, so that it works as expected (hopefully) -> file attached.

regards, qWord
Title: Re: MasmBasic
Post by: jj2007 on October 19, 2009, 08:44:40 AM
Quote from: hutch-- on October 16, 2009, 08:58:29 AM
JJ,

While I remember inbetween database servers not working etc ...
Indeed this post and the following by qWord were not signalled as unread by the forum software - probably related to their hardware problems

Quote
with a tool that has as much development as RichMasm, it would be to its advantage to be able to specify how and where it gets set up in terms of paths of any support files it needs to run. Probably just a dialog box with path slots and common dialog boxes would do the job but it would make it a lot easier for potential users to get it going and configure it the way they like.

Hutch,
Valid point, no doubt. RichMasm/MasmBasic follow your own logic that hard-coded paths are easier to maintain; so, if a user extracts the archive to the root folder of the Masm32 drive with "use folder names" (WinZip) or similar set, the tree will be created with the two folders \masm32\masmbasic and \masm32\RichMasm. That setup works fine, to the point that most if not all examples in \masm32\examples assemble by just hitting hard the F6 button. If they don't, such as \masm32\examples\advanced\wrep\wrep.asm, then it might not be RichMasm's fault.

Now of course there are situations where an experienced user might want to tweak the settings. You can do so by studying File/Configure project, and if that is not enough, by editing \masm32\RichMasm\Res\bldallRM.bav and \masm32\RichMasm\Res\bldallRM.bax - but be warned that currently they are not protected from being overwritten by a new installation.
RichMasm's "makeit.bat" is generated on the fly as \masm32\RichMasm\Res\bldallRM.bat and is composed of bldallRM.bav (default variables), user-defined OPT_xxx variables, and bldallRM.bax.
I am using RichMasm for creating normal executables, dll's and libraries, and up till now I have never had to revert to a manual makeit.bat; therefore I wonder which option you miss? Maybe I can add it to *.bax; otherwise, one could also insert a switch
IF EXIST makeit.bat (
makeit.bat
exit
ENDIF

... into the bldallRM.bav.
bldallRM.bax is a pretty clever template, but clearly there are limits. What I definitely not like is sources that assume that paths are set by the user in the environment variables; a source posted here that starts with include windows.inc has good chances to be ignored. The Masm32 setup is hardcoded and therefore newbie-friendly; and so is RichMasm. But concrete proposals for improvement are always welcome...

Cheers,
JJ
Title: Re: MasmBasic
Post by: jj2007 on October 19, 2009, 08:51:04 AM
Quote from: qWord on October 16, 2009, 02:44:36 PM
jj,
While taking a quick view on your macros, I've found the macro 'cStyle$'. There are some bugs in it: e.g. for an escape sequence followed by an single character ("\nX") or for two or more esc.seq. in a row ("\n\t\n"). I've modified your macro a bit, so that it works as expected (hopefully) -> file attached.

regards, qWord


Hi qWord,
Thanks a lot, looks very convincing. I had written this one some time ago and then forgot about it, indeed it's not even used by MasmBasic, but cStyle$() could be handy in some situations. The next update will contain your version, with credits.

By the way: I repeatedly had problems with @CatStr, see e.g. in the Dim macro:
;; @CatStr(<nustr db ">, MacName$, <", 0>) ; produces garbage
tmp$ CATSTR <nustr db ">, MacName$, <", 0> ; works fine
tmp$

Is that a known ml.exe bug, or is it by design??
Title: Re: MasmBasic
Post by: qWord on October 19, 2009, 05:57:18 PM
Quote from: jj2007 on October 19, 2009, 08:51:04 AM
By the way: I repeatedly had problems with @CatStr, see e.g. in the Dim macro:
;; @CatStr(<nustr db ">, MacName$, <", 0>) ; produces garbage
tmp$ CATSTR <nustr db ">, MacName$, <", 0> ; works fine
tmp$

Is that a known ml.exe bug, or is it by design??
The problem is, that there are two valid interpretations for this (IMO):
nustr   db ">, MacName$, <", 0
and
nustr   db "...",0
So, to be on the save site, you should use exclamation marks when quotes occures inside angle brackets:
@CatStr(<nustr db !">,%MacName$, <!", 0>)
;(the % was also missing here (which is needed to expand textmacros or equations inside a macro-function call)
; -> this produce somethink like '??0011' instead of the macro-local's content)

the same applies for angle bracket inside quoted text:
IFIDNI some,<">"> ; => error A2046:missing single or double quotation mark in string
ENDIF

IFIDNI some,<"!>"> ; works
ENDIF

Title: Re: MasmBasic
Post by: hutch-- on October 19, 2009, 10:54:46 PM
JJ,

The reasoning was this simple, while I would not try and alter the creative genius of RichMasm the basics of QE is that it is configurable in a number of ways so it can be set up to do more or less whatever you want in terms of where its installed, where you want any accessories, paths set in the menu.ini etc ....

I use another copy of it for the basic development I still do from time to time and it lives in another place with different accessories, menu options and binaries.

The only reason for making the suggestion was that you have done so much work on Richmasm that it would help people who want to play with it if they could manually configure it and add bits to it as they need them.
Title: Re: MasmBasic
Post by: jj2007 on October 20, 2009, 11:42:51 AM
Quote from: hutch-- on October 19, 2009, 10:54:46 PM
The reasoning was this simple, while I would not try and alter the creative genius of RichMasm the basics of QE is that it is configurable in a number of ways so it can be set up to do more or less whatever you want in terms of where its installed, where you want any accessories, paths set in the menu.ini etc ....

Hutch,
Point taken. The new version (attached on top of thread) allows users to keep their own version of various settings in a dedicated User folder. For example, you can create your own version of keyboard shortcuts.

Another addition: The help file following immediately after [&Help] in menus.ini will be opened when pressing F1.

QuoteAlthough RichMasm and MasmBasic are configured in a flexible way,
taking account of exe, dll and lib sources,
you can copy these files to satisfy highly specific requirements:

\masm32\RichMasm\Res\menus.ini
\masm32\RichMasm\Res\Keywords.ini
\masm32\RichMasm\Res\BldAllRM.bav
\masm32\RichMasm\Res\BldAllRM.bax

Copy them into \masm32\RichMasm\User, and edit them according to your needs.

Note that \masm32\RichMasm\User\bldallRM.bat will be generated by RichMasm from
- BldAllRM.bav,
- the OPT_xxx user options set in your source,
- BldAllRM.bax.
Both bav and bax must be present (obviously, it makes no sense to edit bldallRM.bat).

Fumbling with bav and bax is recommended only to users who have a thorough
understanding of batch files.
Title: Re: MasmBasic
Post by: jj2007 on October 21, 2009, 08:08:16 PM
Quote from: qWord on October 16, 2009, 02:44:36 PM
jj,
While taking a quick view on your macros, I've found the macro 'cStyle$'. There are some bugs in it: e.g. for an escape sequence followed by an single character ("\nX") or for two or more esc.seq. in a row ("\n\t\n"). I've modified your macro a bit, so that it works as expected (hopefully) -> file attached.

regards, qWord


Hi qWord,
I can't get it to work:

   Print cStyle$("\nHow\nare\nyou?")  ; OK
   MsgBox 0, cStyle$("How\nare\nyou?"), "Hi", MB_OK ; shows only "How"

Somehow a zero byte gets inserted - by the way in both your and my version. Will look into it asap.

On top of thread I posted a new version whose deb macro preserves the FPU and the flags.
Title: Re: MasmBasic
Post by: qWord on October 21, 2009, 08:41:14 PM
have you used jwasm? masm throws an error for:
MsgBox 0, cStyle$("How\nare\nyou?"), "Hi", MB_OK ; shows only "How"

You can solve the problem by adding angle brackets around the parameter 'text' (MsgBox):

invoke MessageBox, dlg, reparg_offset(<&text>), reparg_offset(<&title>), style


Title: Re: MasmBasic
Post by: qWord on October 21, 2009, 11:57:00 PM
I've seen, that your unicode macros wData and wChr$ creates ascii strings that are converted at runtime - this is unnecessary: I've rewritten them (modification of cStyle$), so that this runtime-step is dropped. This two macros can easily changed to support ascii (if your interested in). If you don't like the escape sequences I've choose, then you only have to change/remove them in the ifidn/elseifidn/endif-Block.


     ; create unicode string,  allowed Esc.Seq.: \n    = new line
    ;                                           \0    = 0
    ;                                           \t    = tab
    ;                                           \a\b  = ()
    ;                                           \l\r  = <>
    ;                                           \x    = !
    ;                                           \\    = \
    ;                                           \q    = "
    ;                                           \s    = '
    ; blank arguments are ignored, this applies also to "" and ''
    wData Some,"\a1\b\t x = 12q\n\a2\b\t y = 2x\n\a3\b\t x = y\n\t\a1\b,\a2\b =\r \a3\b\n\a4\b\t12q = 24q",10,13, 10,13,"\l'some senseless words\x'\r"
    %echo @CatStr(<sizeof Some = >,%(SIZEOF Some))
    invoke MessageBoxW,0,OFFSET Some,wChr$("\qQuotes\q",'\\"are simple"'),MB_OK
Title: Re: MasmBasic
Post by: jj2007 on October 22, 2009, 09:24:06 AM
Quote from: qWord on October 21, 2009, 11:57:00 PM
I've seen, that your unicode macros wData and wChr$ creates ascii strings that are converted at runtime - this is unnecessary

Actually, this is by design: My wChr$ occupies half as much space in the .data section; not a big deal but we are stingy, aren't we? ;-)

Your version works fine but chokes a) with JWasm and b) with ml and with quoted strings of size 4, e.g. wChr$("1234"). Testbed below.

include \masm32\MasmBasic\MasmBasic.inc

Use_qWord = 1
if Use_qWord
include wData.txt
endif

.code
start:
; these two choke with the qWord version:
; mov eax, wChr$("1234")
; invoke MessageBoxW, 0, wChr$("1234"), wChr$("I am a Unicode box:"), MB_OK
invoke MessageBoxW, 0, wChr$("Hello Masm32 forum"), wChr$("I am a Unicode box:"), MB_OK
Exit

end start

OPT_Icon MasmBasic
OPT_Assembler ml
Title: Re: MasmBasic
Post by: hutch-- on October 22, 2009, 10:00:41 AM
JJ,

I know that the development of the code to make the coffee is probably some way off but in the mean time I have another suggestion that may fill the gap until you develop that code. how abourt a used defined menu that orders your choice of coffee from a cafe of your choice ?


Short Black, www.maroiscafe.it/orders.htm
Long Black, www.Rositas.com/getitnow.htm
Espresso,www.gastrinomicdelights.com/tryyourluck.htm
TurkishBlack,www.yavash_yavash.tr


PS: I want a copy of the coffee making code when you finish developing it.
Title: Re: MasmBasic
Post by: qWord on October 22, 2009, 10:37:18 AM
Quote from: jj2007 on October 22, 2009, 09:24:06 AM
not a big deal but we are stingy, aren't we? ;-)
in case of clocks ? - yes  :bg

Quote from: jj2007 on October 22, 2009, 09:24:06 AM
Your version works fine but chokes a) with JWasm
There are still bugs in jwasm's macros system. In this case the problem comes from the 'ifidn x,<!">', which seems not to remove the exclamation mark. I've solve this problem by removing it - masm accept this also.

Quote from: jj2007 on October 22, 2009, 09:24:06 AM
with ml and with quoted strings of size 4, e.g. wChr$("1234"). Testbed below.
OPATTR allow them as immediates, so that they are treated as numbers - problem fixed  :bg



Title: Re: MasmBasic
Post by: jj2007 on October 22, 2009, 05:04:20 PM
Quote from: hutch-- on October 22, 2009, 10:00:41 AM
Espresso,www.gastrinomicdelights.com/tryyourluck.htm

Hutch,
Are you sure it's gastrinomicdelights?? That sounds a bit like the gastritis you will get from really strong code coffee...
Quote
PS: I want a copy of the coffee making code when you finish developing it.
Promised. It may take a while, though :bg
Title: Re: MasmBasic
Post by: jj2007 on October 22, 2009, 05:32:09 PM
Quote from: qWord on October 22, 2009, 10:37:18 AM
Quote from: jj2007 on October 22, 2009, 09:24:06 AM
not a big deal but we are stingy, aren't we? ;-)
in case of clocks ? - yes  :bg

Hmmm... show me a speed-critical example using invoke MessageBoxW, 0, wChr$("Hello Masm32"), wChr$("Unicode is simple:"), MB_OK  :green

Your latest code works flawless, except for the bloat factor, of course :bg. Shall I incude it into the library as qChr$ and qData? What do the other hundreds of thousands of MasmBasic users out there think about it??
Title: Re: MasmBasic
Post by: jj2007 on October 23, 2009, 11:57:58 PM
Update on top of thread. New functions:
- Fsign:
Quote.if Fsign(MyRealVar)
      MsgBox 0, "MyRealVar is negative", "Fsign:", MB_OK
   .else
      MsgBox 0, "MyRealVar is not negative", "Fsign:", MB_OK
   .endif
   returns Sign?, and works with all sizes (Real4, Real8, Real10)

- Hex$:
QuotePrint Hex$(eax)
   Print Hex$(cx)
   Print Hex$(dl)
   Print Hex$(MyDword)
   Print Hex$(MyWord)
   Print Hex$(MyByte)
   Print Hex$(123)
   Let A$="Hex="+Hex$(1a2b3c4dh)+"h"

- Bin$:
QuotePrint Bin$(123)
   Let esi=Bin$(-1)+"y"
   MsgBox 0, Bin$(ebx, f), "The Bin$", MB_OK
   returns DWORD in edx - use only once in Let
   option f adds a formatted bit counter
Here is the output of the f option with Print Bin$(123, f):
00000000000000000000000001111011
10987654321098765432109876543210
Title: Re: MasmBasic
Post by: jj2007 on October 30, 2009, 11:36:51 PM
Inspired by DednDave's post (http://www.masm32.com/board/index.php?topic=12621.msg97236#msg97236), I have added a 16-bit example. This is a partial update only - extract the archive to the root folder of your Masm32 drive with "use folder names" on, then open \masm32\RichMasm\RES\hello16.asc

EDIT: Now included in the updated main package.
Title: Re: MasmBasic
Post by: jj2007 on November 02, 2009, 11:54:05 PM
Since I rarely print my code on paper, I had not foreseen a printing function. As this thread (http://www.masm32.com/board/index.php?topic=12612.msg97125#msg97125) shows, there is a certain demand for this feature, so I implemented it. Since I could test it only on a fake printer (PdfCreator), I would be grateful for feedback - see MasmBasic7.zip on top of this thread.

Attached an example printout: TinyRTF is the "little brother" of RichMasm, the source is included in the package.
Title: Re: MasmBasic
Post by: rags on November 03, 2009, 01:07:08 AM
JJ,
  I am using XP SP3 and the printer is a Konica Minolta MagicColor 2300 DL laser printer. The whole document is not being printed on my machine.
On what should be a multiple page printout I am losing a line at the bottom of the printed page, or sometimes the bottom line is not completely
printed. IE- only half the line height gets printed.

Also are there more than just the fixed or proportional font options?
I personally like a smaller print size on paper and it cuts down on the paper used.
Title: Re: MasmBasic
Post by: jj2007 on November 03, 2009, 01:35:41 PM
Quote from: rags on November 03, 2009, 01:07:08 AM
I am using XP SP3 and the printer is a Konica Minolta MagicColor 2300 DL laser printer. The whole document is not being printed on my machine.
On what should be a multiple page printout I am losing a line at the bottom of the printed page, or sometimes the bottom line is not completely printed. IE- only half the line height gets printed.

rags,
version 7c attached on top of this thread fixes the printer issue by using a default value of 6mm for the bottom.

> Also are there more than just the fixed or proportional font options?
> I personally like a smaller print size on paper and it cuts down on the paper used.

\masm32\RichMasm\Res\RichMasm.ini:
[App_Info]
prtL=700
prtR=900
prtT=100
prtB=600
SizeNormal=12
SizeLarge=14 --->Control L
SizeXXL=20 --->Control Shift L
SizeSmall=8 --->Menu Format, Small font
FaceSrc=System --->default when opening source code
FaceProp=Tahoma --->Menu proportional, or Control L
FaceLarge=Arial --->Control Shift L

Copy the file to \masm32\RichMasm\User\RichMasm.ini and modify according to your needs (but don't touch the Inf200 string).

Unfortunately the functions for scaling of printer output and/or zooming a RichEdit control are a bad joke, so this is all I can offer.
EDIT: Version 7d has scaling, at least for the Adobe PDF converter. Add the following setting to \masm32\RichMasm\user\RichMasm.ini:
prtScale=50
Warning: This will most likely print only half of the pages if the printer does not support scaling (e.g. a HP Color Laserjet does not...). I have tested it only for the Adobe "Printer"; print to pdf, open the pdf in the Adobe reader and print it from there. Example output attached.
EDIT(2): Scaling works fine for PrimoPDF and PdfCreator, but not for M$ Document Imaging. I am curious whether there are real printers around that perform scaling...
Title: Re: MasmBasic
Post by: jj2007 on November 27, 2009, 04:15:15 PM
New version on top of thread, with minor bugfixes and two major new features:

1. Export of code in MasmForum "quote" format:
Quoteinclude \masm32\MasmBasic\MasmBasic.inc
.code
start:   call Convert
   Exit
Convert proc
LOCAL pos, posAfter, MyTimer, MyCounter
  and MyCounter, 0
  mov MyTimer, Timer
Recall "\Masm32\include\Windows.inc", L$()   ; load an array of strings from file
  For_ n=0 To eax-1                           ; Recall returns # of strings in eax, so we use 0 ... eax-1
   mov pos, Instr_(1, L$(n), "equ", 5)      ; start in pos 1, 1=case-insensitive + 4=full word
   .if pos
      mov esi,
Val(Mid$(L$(n), pos+3, 99))   ; get the numeric value of the string behind equ
      .if signed edx<0                     ; edx returns the number of usable chars; a
         neg edx                        ; negative number indicates a hex$ or bin$ was found
         add edx, pos
         add edx, 3
         mov posAfter, edx
         inc MyCounter
         
Let L$(n)=Left$(L$(n), pos-1)+"EQU "+Str$(esi)+Mid$(L$(n), posAfter)
      .endif
   .endif
  Next
Store "MyWindows.inc", L$()               ; write all strings back to file
  sub MyTimer, Timer
 
Print Str$("\nConverting %i hex equates in Windows.inc to decimals", MyCounter), Str$(" took %i ms\n", 0-MyTimer)
  ret
Convert endp

end start

2. Inclusion of the resource file in the main code:

QuoteSetControlsPosition endp
   
end start

Rsrc start
#include "\masm32\include\resource.h"

#define  ID_SPIN1 101      //msctls_updown32, vertical
#define  ID_SPIN2 102      //msctls_updown32, horizontal
...
    CONTROL         "Spin1",ID_SPIN1,"msctls_updown32",UDS_SETBUDDYINT |
                    UDS_AUTOBUDDY | UDS_ARROWKEYS,83,77,11,38
    CONTROL         "Spin2",ID_SPIN2,"msctls_updown32",UDS_SETBUDDYINT |
...
END
Rsrc end

RichMasm options
OPT_Susy   Windows
OPT_Icon   Hammer
OPT_Linker   polink
Title: Re: MasmBasic
Post by: 2-Bit Chip on November 28, 2009, 03:45:16 AM
Amazing project you have there jj2007. :8)

I would like to contribute this:  :lol

PrintLn MACRO args
    .if args == 0
        Print 13,10   
    .else 
        Print args,13,10
ENDM


It can be used to print normally with a new line, or just a newline itself.

PrintLn Str$("Have a good day!") or PrintLn
Title: Re: MasmBasic
Post by: jj2007 on November 28, 2009, 08:21:38 AM
Quote from: 2-Bit Chip on November 28, 2009, 03:45:16 AM
Amazing project you have there jj2007. :8)
:bg See the comments of Hutch and Sinsi in the Romper Room

Quote
I would like to contribute this:  :lol

Good idea, I will include it in the package. Here it is in an example:

Quoteinclude \masm32\MasmBasic\MasmBasic.inc

PrintLine MACRO args      ; credits to 2-Bit Chip (http://www.masm32.com/board/index.php?topic=12460.msg98745#msg98745)
  ifb <args>
   Print
  else
   Print args, CrLf$
  endif
ENDM

.code
start:   GetFiles *.asc   ; get all assembler sources in the current folder
   mov ebx, eax      ; #files found
   PrintLine
   PrintLine
   PrintLine "Hello"
   PrintLine "Hello"
   PrintLine
   PrintLine Str$("%i files found\n", ebx)
   For_ n=0 To ebx-1
      PrintLine Files$(n)
   Next
   getkey      ; standard macro from the Masm32 library
   
Exit      ; Uppercase please, the strings need cleanup
[/color]
end start

Output:



Hello
Hello

71 files found

Bin2Byte.asc
Bin2ByteB.asc
Bin2ByteInMB.asc
Bin2ByteX.asc
BinSwap.asc
Title: Re: MasmBasic
Post by: dedndave on November 28, 2009, 04:10:22 PM
don't mind Hutch and sinsi, Jochen
they are just jealous because they didn't think of it, first - lol
Title: Re: MasmBasic
Post by: jj2007 on November 28, 2009, 05:02:45 PM
Quote from: dedndave on November 28, 2009, 04:10:22 PM
don't mind Hutch and sinsi, Jochen
they are just jealous because they didn't think of it, first - lol

Dave, they are RealMen(TM) and prefer endless greeeey listings. I fully understand that. At my advanced age, I need color to remember where the difficult bits of my code where :toothy

@2-Bit Chip: PrintLine is in, see version 8c on top of thread.

Another minor bugfix: The deb macro choked for deb 5, "First loop", eax, ebx, ST(0), My$

deb 1, "Test", eax, esi$ displays the contents of eax as an integer, the contents of esi as a string. You may use deb 2, "Second loop", eax etc. and cancel the displayed MsgBox individually for deb 1...4. However, deb 5 appends the contents to DebLog.txt in the current folder - an extremely handy feature that didn't work in version 8b.
Title: Re: MasmBasic
Post by: jj2007 on November 29, 2009, 01:54:39 AM
This orphanage thread on reading strings (http://www.masm32.com/board/index.php?topic=12769.msg98820#msg98820) led to another update: Version 8e (on top of this thread) includes an example on how listboxes with many items can be displayed faster: While the standard way needs 1,200 milliseconds, it can be done in only 30 - a factor 40 improvement.
For making this work, Recall had to be modified so that it returns the # of bytes read from file.

From the template available at File/New Masm source/Listbox and Recall:

Quote   sm EQU <invoke SendMessage, >              ; an equate to save some typing
   sm hListbox, WM_SETREDRAW, 0, 0           ; A: stop the screen updating (the order is very important!)

   sm hListbox, LB_RESETCONTENT, 0, 0   ;      B: clear the listbox
   Recall "\Masm32\include\Windows.inc", L$()        ; read the strings from file to the L$() array ; eax=line count, edx=bytes read
   mov linecount, eax
   sm hListbox, LB_INITSTORAGE, eax, edx        ; C: tell the OS what you need
   For_ n=0 To linecount-1

         sm hListbox, LB_ADDSTRING, 0, L$(n)
   Next
   sm hListbox, WM_SETREDRAW, 1, 0           ; D: turn on screen updating
Title: Re: MasmBasic
Post by: ecube on December 01, 2009, 04:55:24 AM
no included source, i'll pass
Title: Re: MasmBasic
Post by: jj2007 on December 01, 2009, 07:51:44 AM
Quote from: E^cube on December 01, 2009, 04:55:24 AM
no included source, i'll pass
You wouldn't understand it anyway. If somebody is seriously interested, pm me ("seriously" means I expect proof that the sender has already coded something in MB).
Title: Re: MasmBasic
Post by: ecube on December 01, 2009, 08:47:00 AM
Quote from: jj2007 on December 01, 2009, 07:51:44 AM
Quote from: E^cube on December 01, 2009, 04:55:24 AM
no included source, i'll pass
You wouldn't understand it anyway. If somebody is seriously interested, pm me ("seriously" means I expect proof that the sender has already coded something in MB).

uh i've programmed in vb for awhile, and I understand ASM minus sse2 etc which I HIGHLY doubt your code contains that. Anyway you keep being arrogant and thinking you're some kinda ASM wizard, cause you already seen what happens when you release your "amazing" code, people like lingo come by and write something far faster/smaller.
Title: Re: MasmBasic
Post by: UtillMasm on December 01, 2009, 08:56:08 AM
 ::)
code nothing in MB, i'll pass.

:toothy
PS.Support release MB source.
Title: Re: MasmBasic
Post by: jj2007 on December 01, 2009, 09:44:16 AM
Quote from: E^cube on December 01, 2009, 08:47:00 AM
uh i've programmed in vb for awhile
Show us some of your code, please. If it's not Masm, VB is fine, too.

Quote
I understand ASM minus sse2 etc which I HIGHLY doubt your code contains that.
If you knew how to use Olly, you could find out.
Title: Re: MasmBasic
Post by: ecube on December 01, 2009, 10:14:55 AM
Quote from: jj2007 on December 01, 2009, 09:44:16 AM
Quote from: E^cube on December 01, 2009, 08:47:00 AM
uh i've programmed in vb for awhile
Show us some of your code, please. If it's not Masm, VB is fine, too.

Quote
I understand ASM minus sse2 etc which I HIGHLY doubt your code contains that.
If you knew how to use Olly, you could find out.

tired of playing these games with you,i'm not acting like i'm some superior coder like you are, none the less learn how to search
http://www.masm32.com/board/index.php?topic=11103.0
Title: Re: MasmBasic
Post by: jj2007 on December 01, 2009, 10:20:08 AM
Quote from: E^cube on December 01, 2009, 10:14:55 AM
tired of playing these games with you,i'm not acting like i'm some superior coder like you are, none the less learn how to search
http://www.masm32.com/board/index.php?topic=11103.0

Attribute VB_Name = "modPreLoader__"
...'
' - by Libor Blaheta


Thanks, Libor.
Title: Re: MasmBasic
Post by: ecube on December 01, 2009, 10:30:47 AM
Quote from: jj2007 on December 01, 2009, 10:20:08 AM
Quote from: E^cube on December 01, 2009, 10:14:55 AM
tired of playing these games with you,i'm not acting like i'm some superior coder like you are, none the less learn how to search
http://www.masm32.com/board/index.php?topic=11103.0

Attribute VB_Name = "modPreLoader__"
...'
' - by Libor Blaheta


Thanks, Libor.

Read my topic description, actually don't,you're obviously a slow read, and I don't even know why i'm wasting time on you anymore, go work on your IDE and keep thinking it's anywhere near Radasm. Dillusion must be grande
Title: Re: MasmBasic
Post by: hutch-- on December 01, 2009, 12:19:36 PM
Hey guys,

Keep it friendly, you are both rare species, assembler programmers.  :bg
Title: Re: MasmBasic
Post by: dedndave on December 01, 2009, 01:32:45 PM
E^cube
JJ has spent a lot of hours on this project
the fact that he doesn't want to give it away to everyone doesn't surprise me
there are many projects in here that do not include source - we don't chastise them for that
the fact that he is willing to share the source with us for the cost of a PM seems rather gracious to me
and, if i know Jochen, there is a lot of SSE2 code in there - and a lot of fast and small routines, as well, both SSE and non-SSE
when he said we might not understand it, he wasn't kidding - lol
his code is well known to be full of confusing macros and if/while structures   :bg
Title: Re: MasmBasic
Post by: ecube on December 01, 2009, 01:41:01 PM
Quote from: dedndave on December 01, 2009, 01:32:45 PM
E^cube
JJ has spent a lot of hours on this project
the fact that he doesn't want to give it away to everyone doesn't surprise me
there are many projects in here that do not include source - we don't chastise them for that
the fact that he is willing to share the source with us for the cost of a PM seems rather gracious to me
and, if i know Jochen, there is a lot of SSE2 code in there - and a lot of fast and small routines, as well, both SSE and non-SSE

it's not about the fact he doesn't want to release the source, it's his delusions of grandeur and arrogance that bothers me. But whatever, out of hutches request I won't post in this thread anymore.
Title: Re: MasmBasic
Post by: jj2007 on December 01, 2009, 02:00:33 PM
Quote from: dedndave on December 01, 2009, 01:32:45 PM
when he said we might not understand it, he wasn't kidding - lol
his code is well known to be full of confusing macros and if/while structures   :bg

Dave, there are many coders here who will understand it, you included, of course :thumbu
It's more a matter of principle: If somebody demonstrates a serious interest, and has contributed a substantial amount of genuine code to this forum, then yes he can have the code. Otherwise not - it's not meant for the trolls.

Next post is back to topic.
Title: String sort in MasmBasic
Post by: jj2007 on December 01, 2009, 02:11:16 PM
One of the commands on my "missing" list is a string sort. The proper way of doing this in the Unicode age is probably via CompareStringEx or similar, but why not cheat a little bit and let Windows do the job?

The good news is its very easy, see below, and fast enough for ordinary human beings. Windows.inc gets sorted in one third of a second - reading, sorting and writing the file (I know that's incredibly slow, but compare it to the 3-4 seconds that Outlook needs to display the insert hyperlink box for the first time...).

The bad news is you must download the archive again from the top thread, because Let L$(n)=esi stumbled over a tiny but very significant bug. Apologies :red

Quoteinclude \masm32\MasmBasic\MasmBasic.inc   ; no further includes needed

FileSort   PROTO: DWORD, :DWORD

.code
start:
;   sort Windows.inc and write the result to SortedWindows.inc:
   fn FileSort, "\Masm32\include\Windows.inc", "\Masm32\RichMasm\SortedWindows.inc"
   Exit

FileSort proc uses esi SrcFile, DestFile
LOCAL hInstance, hListbox
LOCAL ctLines, ctValid, ShowTime$
LOCAL buffer[4096]:BYTE
IdListbox = -123
   push Timer                  ; save the ticks
   invoke GetModuleHandle, NULL
   mov hInstance, eax
   invoke CreateWindowEx, WS_EX_CLIENTEDGE, chr$("listbox"), NULL,
      WS_CHILD or LBS_SORT,
      0, 0, 0, 0,
      rv(GetDesktopWindow), IdListbox, hInstance, NULL
   mov hListbox, eax            ; we have created a hidden listbox as a child of the desktop

   Recall SrcFile, L$()            ; read the strings from file to the L$() array: eax=line count, edx=bytes read
   mov ctLines, eax
   invoke SendMessage, hListbox, LB_INITSTORAGE, eax, edx  ; tell the OS how much space you need
   and ctValid, 0
   For_ n=0 To ctLines-1
         Let esi=Trim$(L$(n))      ; we are not interested in leading spaces and nullstrings
         .if Len(esi)
            invoke SendMessage, hListbox, LB_ADDSTRING, 0, esi
            inc ctValid
         .endif
   Next
   lea esi, buffer
   For_ n=0 To ctValid-1
         invoke SendMessage, hListbox, LB_GETTEXT, n, esi
         Let L$(n)=esi
   Next
   Store DestFile, L$(), ctValid

   mov esi, Timer                        ; get the end ticks ...
   pop eax
   sub esi, eax                        ; ... and subtract the start ticks
   Let ShowTime$=Str$("%i \tms", esi)+Str$(" for sorting\n%i\tentries in ", ctLines)+SrcFile
   invoke DestroyWindow, hListbox
   MsgBox 0, ShowTime$, "MasmBasic is cute:", MB_OK
   ret
FileSort endp

end start
Title: Re: MasmBasic
Post by: UtillMasm on December 01, 2009, 02:53:43 PM
 :U
above code is so good, but i can understand it.
PS. you are a MACRO guy.
Title: Re: MasmBasic
Post by: jj2007 on December 04, 2009, 01:40:53 AM
Update #9, downloadable at top of thread. Improves on the Val() function: The conversion of all hex values in Window.inc to decimals works now almost 100%, with the exception of line 17628:
IMAGE_ARCHIVE_START equ "!<arch>",10

When using mov ebx, Val("123h"), the value is returned in eax, while edx returns info about success or failure of the evaluation:
edx==0   ; failure, not a valid format
edx==-127   ; failure, strange format, you better check
edx>0   ; success, edx chars have been used
edx<0   ; success with a hex$ or bin$; use the following to get the correct # of chars used:
Quoteneg edx
         .if dh                        ; if dh is set, it was a binary string
            mov eax, L$(n)
            deb 1, "Found a binary value in Windows.inc", eax$
            movzx edx, dl
         .endif
Here is a list of recognised (and not recognised) formats. Those marked in red will not work.
Quoteinclude \masm32\MasmBasic\MasmBasic.inc

.code   ; Teststrings
asc1   db "100", 9, "3", 0
asc2   db "100b", 9, "-260 (4)", 0
asc3   db "100h", 9, "-4", 0
asc4   db "(100)", 9, "5", 0
asc5   db "(100b)", 9, "-261 (5)", 0
asc6   db "(100h)", 9, "-5", 0
asc7   db "($100)", 9, "-5", 0
asc8   db "(0x100)", 9, "-6", 0
asc9   db "(100)", 9, "5", 0
asc10   db "(1e3)", 9, "5", 0
asc11   db "1e3", 9, "3", 0
asc12   db "(e100)", 9, "0, invalid format", 0
asc13   db "e100", 9, "0, invalid format", 0
asc14   db "(z100)", 9, "0, invalid format", 0
asc15   db "z100", 9, "0, invalid format", 0
asc16   db "-100", 9, "4", 0
asc17   db "-100b", 9, "-261 (5)", 0
asc18   db "(-100b)", 9, "-263 (7)", 0
asc19   db "-100h", 9, "-5", 0
asc20   db "(-100h)", 9, "-7", 0
asc21   db "+100", 9, "4", 0
asc22   db "+100b", 9, "-261 (5)", 0
asc23   db "+100h", 9, "-5", 0
asc24   db "(2e3)", 9, "5", 0
asc25   db "(2345e2)", 9, "8", 0   ; DotPos
asc26   db "(2.34e3)", 9, "8", 0
asc27   db "(2e3)", 9, "5",
13, 10, 0
asc28   db "(+100)", 9, "6 x", 0
asc29   db "(+100b)", 9, "-263 (7) x", 0
asc30   db "(+100h)", 9, "-7 x", 0
asc31   db "{ 3E7h, 0h }", 0
asc32   db "(", 34, "SeMachineAccountPrivilege", 34, ")", 0
asc33   db 34, "SeMachineAccountPrivilege", 34, 0
asc34   db 34, "!<arch>",34, ", 10 xx this one fails with Windows.inc!", 0

start:
   Print "Result", Tb$, "#chars", Tb$, "Source", Tb$, "exp#chars", CrLf$
   ct=0
   REPEAT 34
      ct=ct+1
      tmp$ CATSTR <Print Str$("%i\t", Val(offset asc>, %ct, <)), Str$("%i\t", edx), offset asc>, %ct, <, CrLf$>
      tmp$
   ENDM
   Exit
end start

Title: Re: MasmBasic
Post by: oex on December 04, 2009, 01:53:07 AM
I think I found a syntax error.... Shouldnt

Quoteinclude \masm32\MasmBasic\MasmBasic.inc

be

Quoteinclude \masm32\MasmBasic\MasmBasic.inc

?
Title: Re: MasmBasic
Post by: jj2007 on December 04, 2009, 02:32:48 AM
Quote from: oex on December 04, 2009, 01:53:07 AM
Quoteinclude \masm32\MasmBasic\MasmBasic.inc
Would look better indeed, but for assembling the RichMasm editor exports a plain text temporary file, tmp_file.asm, so colours will be ignored anyway. I will change the template as shown below.
Quoteinclude \masm32\MasmBasic\MasmBasic.inc
Title: Re: MasmBasic
Post by: oex on December 04, 2009, 02:44:26 AM
:lol sorry 2am and still writing code, the distraction was most welcome
Title: Re: MasmBasic
Post by: jj2007 on December 05, 2009, 10:34:27 AM
Quote from: oex on December 04, 2009, 02:44:26 AM
:lol sorry 2am and still writing code, the distraction was most welcome

Hey, write some MasmBasic code, I want to see if it can be crashed :bg
Title: Re: MasmBasic
Post by: oex on December 05, 2009, 02:56:29 PM
It has color :bg too high level for me, I wouldnt know where to start :lol
Title: Re: MasmBasic
Post by: eatstoomuchjam on December 05, 2009, 08:50:23 PM

I was recently inspired to try MASM32 again after a fairly long hiatus and this MASMBASIC looks like fun so I thought I'd give it a try, but I'm running into a couple of problems and I'm hoping the gurus can help out.

The first one is that there isn't much documentation on Input() other than to use it after Open(), but


.data
    InBuffer$ dd

.code
    Open "O",#1,"C:\temp\file.txt"
    Print #1, "This is a test",13,10
    Close #1

    Open "I", #2, "C:\temp\file.txt"
    Input #2, InBuffer$, Lof(#2)
    Close #2

    Print InBuffer$


I would assume that the above could would result in "This is a test" being printed to my screen, but I get back nothing.  I assume it's a simple usage error and if I had the source, I'd be glad to poke at it first to see where I've goofed up.  Since it's a black box to me for the time being, I thought I'd ask.
I'm mostly interested in using Input() as I'm trying to process XML in a memory-efficient way and loading entire large XML files into memory using Recall() and/or FileRead() would put me out of the running.

Next, support for brackets may be broken in the Instr() function (and possibly others) (or again, perhaps I'm just a bit slow today).

Print "!<testing!>",13,10

Works exactly as expected

However, I get compiler errors with each of the following...

  mov esi,Instr_(0,Test$(n),"<")
  mov esi,Instr_(0,Test$(n),"!<")


But something like the following works fine.

  mov esi,Instr_(0,test$(n),"x")


Thanks in advance for any help!
Title: Re: MasmBasic
Post by: eatstoomuchjam on December 05, 2009, 09:43:10 PM
Another problem -
I'm not certain why, but passing a value in a dd or in a register to Instr() as the first parameter results in a crash...
e.g.

.data
               curpos dd ?

.code
                mov curpos,Instr_(0,Test$(n)," ", 4)
                inc curpos
                Print Str$("%i",curpos)
                Print Str$("%i",Instr_(curpos,Test$(n)," ", 4)),13,10


In my case, that will print "2" (since the first space in the string being processed is at position #2) and then crash.
Title: Re: MasmBasic
Post by: jj2007 on December 05, 2009, 09:44:00 PM
Hello Jan (assuming that is a valid short name ;-)

First of all, welcome to the forum :thumbu
And welcome to MasmBasic. It's still far from being perfect, but I hope that I can help you overcome these problems one by one.
In case you use the RichMasm editor, select e.g. Print and press F1 for help. You would get this:
Quote MbPrint
   Print "Test", CrLf$, Chr$("the library", 13, 10)
   Print #1, esi, " is ", My$
Rem   - predefined strings CrLf$, Tb$, Spc1$, Spc2$, Spc4$, MbExeFolder$ do not bloat the exe
   - Unicode can be printed to a file as e.g. wPrint #1, wChr$(13, 10, "This is Unicode") or by defining a
     string like this: wData MyWide$, "This is Unicode", 0, followed by wPrint #1, offset MyWide$
Key   pri, pri1
Now that does look straightforward, but keep in mind that MasmBasic is not Basic: it's a Masm library, a kind of "inline Basic". Therefore, if you allocate...
.data
    InBuffer$ dd
... it means you allocated the 4 bytes that hold the pointer to the string. To read in the 16 bytes, you still need the buffer. There are (at least) two ways to do this:
1. You allocate it by hand, e.g. in the .data? section (but that requires that you know the size in advance):
.data
    InBuffer$ dd TheBuffer
.data?
TheBuffer db 20 dup(?) ; a few bytes more

2. You let (pun intended) MasmBasic do the job:
Quote    Open "O",#1,"C:\temp\file.txt"
    Print #1, "This is a test",13,10
    Close #1
    Open "I", #2, "C:\temp\file.txt"
    ; same: Let InBuffer$=New$(Lof(#2))
    Let InBuffer$=String$(Lof(#2), 0)
    Input #2, InBuffer$, Lof(#2)
    Close

Re brackets, that is a tricky problem with the assembler itself. Exclamation marks help sometimes but not always. What I usually do is define the brackets in the .data section:
.data
LeftB$ dd txLeftBracket
RightB$ dd txRightBracket
txLeftBracket db 60, 0
txRightBracket db 62, 0

Let me know if that is sufficient to get your code running, and don't hesitate to post here, or if it does not look of general interest, PM me.
Title: Re: MasmBasic
Post by: jj2007 on December 05, 2009, 10:06:16 PM
Quote from: eatstoomuchjam on December 05, 2009, 09:43:10 PM
Another problem -
I'm not certain why, but passing a value in a dd or in a register to Instr() as the first parameter results in a crash...

I can assure you this is not "by design". I hope I can fix it tonight... sorry!
Title: Re: MasmBasic
Post by: eatstoomuchjam on December 05, 2009, 10:11:35 PM
Thanks a lot!  I'll give your suggestions a try!

(And Dan is my name - you could call me that or ETMJ for short.  :) )
Title: Re: MasmBasic
Post by: eatstoomuchjam on December 05, 2009, 10:31:39 PM
You suggestions for both file input and for brackets seem to be working like a charm!

Thanks a lot!  I really dig MASMBASIC, btw.  It's pretty great to have some friendly string parsing functions available.
Title: Re: MasmBasic
Post by: jj2007 on December 05, 2009, 11:23:54 PM
Quote from: eatstoomuchjam on December 05, 2009, 10:31:39 PM
You suggestions for both file input and for brackets seem to be working like a charm!

Thanks a lot!  I really dig MASMBASIC, btw.  It's pretty great to have some friendly string parsing functions available.

Hi Dan,
Great to hear it works. It seems I could solve the Instr_ problem, too - see version 9b on top of this thread. Let's call it the Santa Claus edition :bg

Note that the default start position for Instr is 1, as for most Basic dialects. If you specify zero (or less), the search continues at the previous position plus one.

For the curious, here the new Instr_ macro:
Quote; A: has startpos:   INSTR(curpos, "Test", "Te", 2)   ; 4 args
; B: no startpos:   INSTR("Test", "Te", 2)   ; 3 args, last one immediate
; C: has startpos:   INSTR(curpos, "Test", "Te")   ; 3 args, last one not immediate
; D: no startpos:   INSTR("Test", "Te")      ; 2 args, or 3 and last one immediate
Instr_ MACRO sPos, Src$, Sub$, sMode
LOCAL last_imm
  ifnb <sMode>
   push sMode               ;; A: 4 args, easiest case
   push reparg_offset(Sub$)
   PushString Src$
   push sPos
  elseifnb <Sub$>
   last_imm INSTR <0123456789>, <Sub$>
   if last_imm
      push Sub$               ;; B: 3 args, last one immediate, so sPos=Src, Src=Sub
      push reparg_offset(Src$)      ;; Sub$
      PushString sPos         ;; Src$
      push 1                  ;; added: default startpos
   else
      push 0                  ;; C: 3 args, last one not immediate, so it has sPos, added: default mode
      push reparg_offset(Sub$)
      PushString Src$
      push sPos
   endif
  else
   push 0                  ;; D: 2 args, added: default mode
   push reparg_offset(Src$)      ;; Sub$
   PushString sPos         ;; Src$
   push 1                  ;; added: default startpos
  endif
 
call InstrCi            ;; invoke InstrCi, sPos, reparg_offset(Src$), reparg_offset(Sub$), sMode
  EXITM <edx>         ;; relative pos in edx, absolute in eax
ENDM
Title: Re: MasmBasic
Post by: eatstoomuchjam on December 06, 2009, 12:33:26 AM
Awesome.  I just gave the new one a try and not only did it fix the bug I'd run into before, but it also fixed the one I'd just logged back in to report.  :)
(Thanks for the reminder on 1-based strings in Basic - I'd run into that the hard way already.  :) )

I was also getting crashes when trying to use an array value as the search string...
e.g.

  Let curString="/test2/test"
  Dim Checks$(2)
  mov checkCount,2
  Let Checks$(0)="/test1"
  Let Checks$(1)="/test2/test"
  Let Checks$(2)="/test3/test/test"

  For_ p=0 to checkCount
    mov edi,Instr_(1,curString,Checks$(p))
  Next


Anyway, that seems to work now too... Thanks again!
Title: Re: MasmBasic
Post by: jj2007 on December 06, 2009, 08:21:53 AM
Quote from: eatstoomuchjam on December 06, 2009, 12:33:26 AM
I was also getting crashes when trying to use an array value as the search string...
e.g.

    mov edi,Instr_(1,curString,Checks$(p))

That one was related to the previous crash. Glad to see it works - keep me posted :bg
Title: MasmBasic/RichMasm keyboard shortcuts
Post by: jj2007 on December 06, 2009, 11:49:07 PM
Minor change in the RichMasm editor:
Alt K toggles between bookmarks and display of keyboard shortcuts as shown below.

db "Alt K  Toggle keys/bookmarks", 0  ; show/hide this text
db "Alt F  File menu", 0
db "Alt T  Format menu", 0
db "Alt Y  SysApps menu", 0
db "Alt H  Help menu", 0
db "Alt A  AutoCode", 0
db "Alt S  Save as", 0
db "Ctrl S  Save", 0
db "Ctrl P  Print", 0
db "Ctrl C  Copy", 0
db "CtShift C  Copy plain", 0  ; Control Shift copies plain text
db "Ctrl V  Paste", 0
db "CtShift V  Paste plain", 0
db "Ctrl D  Bookmark", 0
db "Ctrl K  HyperlinK", 0  ; insert hyperlink (prefilled if http... is on clipboard)
db "Ctrl G  Goto line", 0  ; also used for some special functions, e.g. fnt=80 for extra large font
db "CtShift O  Goto offset", 0  ; sets current line as zero and asks for an offset
db "Ctrl F  Find", 0
db "Ctrl R  Replace", 0
db "Ctrl down  Current as top line", 0
db "Ctrl up  Current as bottom", 0
db "Ctrl B  Bold", 0
db "CtShift B  Blue", 0
db "Ctrl E  Red (emphasize)", 0
db "Ctrl H  Hilight", 0
db "CtShift H  Hide", 0
db "Ctrl I  Italics", 0
db "Ctrl L  Large", 0   ; Control Shift L is XXL font
db "Ctrl N  Convert Number", 0  ; shows selected number in hex, dec and bin format
db "Ctrl U  Upper/Lowercase", 0
db "Alt left, F2  Go back", 0
db "Alt right  Go forward", 0
db "Alt L  List matches", 0
db "F1  Mb Help", 0
db "F2  Go back", 0
db "F3  Find selected", 0  ; finds all matches for selected text and shows them in a listbox
db "F4  Comment", 0  ; toggles comment
db "F5  JavaScript", 0  ; saves content as plain text to filename.js and activates browser
db "F6  Build & Run", 0  ; MASM: assemble, link, start executable
db "F7  Output window", 0  ; show/hide the F6 output window
db "F11  Copy2Forum", 0, 0  ; copy formatted code compatible with the Masm32 forum quote syntax
Title: Re: MasmBasic
Post by: ic2 on December 07, 2009, 02:13:38 AM
Wow jj2007  From Day-1 you came in with back-to-back projects in mind.  Be back soon.
Title: Re: MasmBasic
Post by: ic2 on December 07, 2009, 06:48:29 PM
I really done nothing ASM for a long time.  When I went dead-beat you were talking consoles and font's.  I came back last night to find those threads. I want to write a few web applications in ASM under Windows but 100% potable to FREEBSD and LINUX and with Window-7 I think Microsoft made it easy.  If I'm on the right track, a few of your old threads are going to get me started (consoles style system-font scaling, color font, etc).  Maybe old news by now, but here Mark Russinovich drops a clue about UNIX mode under Windows-7.  He say nothing about where is it or if it is the real deal.  But if you can write it under windows and it is build ready for a real linux/BSD machine with minimum modification, if any, that's going to make a easy dive :).  I'm crazy about Windows but not as a public server.

http://channel9.msdn.com/shows/Going+Deep/Mark-Russinovich-Inside-Windows-7-Redux/

http://channel9.msdn.com/shows/Going+Deep/Mark-Russinovich-Inside-Windows-7/

Anyway, I'm looking at RichMasm and when I size and place a program windows at my idea location on the screen, that's where I want it to be the next time I open it up.  How do we setwindowpos for RichMasm window?  I see no ini-file for RichMasm editor or a Windows registry key.  If you include x-y position, I hope you use a ini-files for RichMasm.
Title: Re: MasmBasic
Post by: ic2 on December 07, 2009, 11:58:55 PM
This is it, right ... your editor is a console, GUI style where you went beyond 16 bit command.com which is what cmd.exe for XP tried to leave DOS behind, but where win-system only show dialog style window for console so I'll take that back about inifile ... You got full-screen and I remember googling and concluded, there not a easy way to make adjustments if ever any.  If I'm guesting right, that will work but how about FASM.
Title: Re: MasmBasic
Post by: dedndave on December 08, 2009, 12:39:42 AM
sounds like a little terminology confusion to me
what we refer to as "console" programs are those that run at the command prompt, and are usually text-based apps
Title: Re: MasmBasic
Post by: jj2007 on December 08, 2009, 12:45:41 AM
ic2,
Not sure what you mean here. The editor is based on the RichEdit control - where do you see a console style...?
By the way, the ini file is already there, and fixing screen coordinates is possible. I attach here a temporary version 9i (intermediate because the MasmBasic Val() function has an unresolved bug).

- Check \masm32\RichMasm\RES\RichMasm.ini after extraction, and copy it to \masm32\RichMasm\user\RichMasm.ini
- add the following under [AppInfo]:
ScrX=200
ScrY=0
ScrW=700
ScrH=1000
ScrW and ScrH are expressed as 1000th of the available width, so these values give you roughly a centered window.

This latest version also has improved autoindenting, i.e. if you type .if eax, then Return, you get an extra tab. Same for .Rep, .else etc.

EDIT: Attachment removed, see new one at page 8
Title: Re: MasmBasic
Post by: ic2 on December 08, 2009, 05:08:55 PM
"sounds like a little terminology confusion to me"

dedndave, I even when back to school but we have done no ASM to-date and that was the main point of going back. Everything is LOGIC.  I could have use all of that time coding something sinceable, like ASM.  Now I don't even have the spare time to even think anymore.  No ASM is a heart breaker  :(

"where do you see a console style...?"

That was a stupid wild guest.  No person who understand computer should have concluded that.  Anyway, I just been trying to think of how I would relate MasmBasic to FASM or if the editor would assemble fasm code. Either way, school is out in a few days so I'm planing get back into ASM and understand the working of MasmBasic during my vacation.  I had big fun translating masm code to fasm last year.  A little tricky sometimes but it don't take much.  For what I read already ...

Great work JJ
Title: Re: MasmBasic
Post by: dedndave on December 08, 2009, 05:11:14 PM
logic is good - lol
learn all you can - it will help you write better code
Title: Re: MasmBasic
Post by: ic2 on December 13, 2009, 07:38:37 AM
Logic... Those people at the job who only taking the talk and walk the walk, but never wrote a line of code since the DOS days are the ones who are earning top dollar.  I might fuss a little but I like it, especially after hutch explained some C type logic question asked by me a few years ago.  The way he spit-it sold me, now I try harder.  As far as writing better code, the way I been reading, today processors (64bit) have taken away the ability for programmer to see all of true processing of the processor and with Windows-7 sub-sub-sub triple kernel to a General in a dress, even more can't be seen.  Deals have been made.  Its like the OS goal is to run even assembler at VB rate through system managers.  But like they say, for every action there is a equal but opposite reaction.  No company or super-man will never control how the rivers flows or where lighting canl strikes no matter how deep one try to hide his bloated Kernel.

Title: Re: MasmBasic
Post by: dedndave on December 13, 2009, 12:23:37 PM
i dunno - ms seems to be able to do as they please, and none of us can do much about it
intel has done things that make optimizing code more difficult, as well (they really sucked all the fun out of it - lol)
as programmers, we have to take the platform, as it exists, and make it do what we want it to
that means we are in a continuous learning cycle
Title: Re: MasmBasic
Post by: BytePtr on December 13, 2009, 09:26:28 PM
Nice stuff, it makes coding in MASM even easier.
Title: Re: MasmBasic
Post by: ic2 on December 14, 2009, 08:55:26 PM
Good point dedndave.
I'm not 100& sure either.  Watch those video links above and pay special attention when Mark Russinovich speak about Win-Win and sub-sub Kernel and what he had to say about back in the day "there was NO real Kernel mode".  He's honest, but a little piss ... He wrote Process Explorer so he got good reasons i guest, but he get over it.  But he will give you a  darn good clue of what's going on with pass Windows and the future of Windows-7.  He was just like us yesterday.

jj_2007,
If you don't have time for FASM just yet, for now, I think  RichMasm should .. if possible have a customizable tool bar, or any kind of tool bar to at lease do some basic editing type stuff, like select all, find and find next, etc.  Not sure if that is possible because of the dialog style window  (that I thought was console) but I see it does makes coding in MASM even easier as BytePtr indicated.  I know that "Rome" was not build overnight, so don't think i'm not trying to rushi you.
Title: Re: MasmBasic
Post by: jj2007 on December 14, 2009, 09:42:12 PM
Quote from: ic2 on December 14, 2009, 08:55:26 PM
jj_2007,
If you don't have time for FASM just yet, for now, I think  RichMasm should .. if possible have a customizable tool bar, or any kind of tool bar to at lease do some basic editing type stuff, like select all, find and find next, etc.  Not sure if that is possible because of the dialog style window  (that I thought was console) but I see it does makes coding in MASM even easier as BytePtr indicated.  I know that "Rome" was not build overnight, so don't think i'm not trying to rushi you.
Ic2,
I am a bit lost: Are we talking about the same software? RichMasm (http://www.masm32.com/board/index.php?topic=9044) (which is included in the MasmBasic (http://www.masm32.com/board/index.php?topic=12460) package) has the most comfortable search functions you can imagine. Try Control F, then Control R, or even easier, select one of your variables and hit F3. If you don't see a listbox with the results, you might need to click on the stripes icon above "Find".
I am getting really curious. Can you send a screenshot of what you actually see, please?
Title: Re: MasmBasic
Post by: hutch-- on December 14, 2009, 10:57:19 PM
 :bg

Why does this sound like the GFA basic editor of the middle 90s ?
Title: Re: MasmBasic
Post by: jj2007 on December 15, 2009, 12:05:19 AM
Quote from: hutch-- on December 14, 2009, 10:57:19 PM
:bg

Why does this sound like the GFA basic editor of the middle 90s ?

Hutch,
Although I have used the Gfa editor quite a lot, there is not much resemblance. Control F opens a find box in Ms Word, not in Gfa...
:wink
Title: Re: MasmBasic
Post by: ic2 on December 15, 2009, 03:20:26 AM
screenshots

>edit

Ok, now i 'm paying attention.  I like the way you got the find editbox ready to go and there is plenty of room to add more buttons to the right.  This is really difference.  I like it :)
Title: Re: MasmBasic
Post by: jj2007 on December 15, 2009, 08:08:49 AM
Quote from: ic2 on December 15, 2009, 03:20:26 AM
screenshots

Ok, I am relieved to see that we talk about the same software ;-)

Yes, my handling of the find box is different. That listbox is my favourite feature - select the global variable you are just working with, hit F3, and you got immediately the 10+ places in your 10,000 lines doc where you used MyGlobVar. Other use: Olly says you got an exception at mov eax, [esi]. Next line is sub eax, 3. You have 20 times mov eax, [esi], so that is not helpful. But type mov eax, [esi]**sub eax into the find box and you got it... One star means a same line joker, 2* means extend search to next line (note it will work only if there is one space between eax and [esi], otherwise [esi]**sub will do the job)

Re toolbar: There is a good reason why the buttons and bookmarks are on the right. Assembler code is vertical. Count the visible lines, and compare to other editors at same font size...

But I must admit that it is getting less user-friendly over time. The more I am working with it, the more it gets keyboard-oriented, and memorising a dozen function keys is not exactly noob-friendly. That is why WordStar and WordPerfect eventually lost against M$ ::)
Title: Re: MasmBasic
Post by: 2-Bit Chip on January 16, 2010, 12:40:11 AM
I will be using this now. Thank you.
Title: Re: MasmBasic
Post by: dedndave on January 16, 2010, 02:36:06 AM
you could always add a right-click context menu with a bunch of typing shortcuts, JJ
Title: Re: MasmBasic
Post by: jj2007 on January 16, 2010, 03:01:24 AM
Quote from: dedndave on January 16, 2010, 02:36:06 AM
you could always add a right-click context menu with a bunch of typing shortcuts, JJ

The keyboard shortcuts are toggled with Alt K and appear to the right where normally the bookmarks reside.
In case you mean the "expansion" strokes, e.g. ism ->invoke SendMessage, there are too many for a context menu. Below an excerpt from \masm32\RichMasm\RES\Keywords.ini

masmincs include \masm32\include\masm32rt.inc
mbincs include \masm32\MasmBasic\MasmBasic.inc §
clv ClearLocalVariables uses edi esi ebx ¨ PopUses §
exit §
clr §
s$( Str$(§
c$( Chr$(§
float$( Str$(§
string$(§
gf GetFiles *.asc §
exist(§
ex( Exist(§
kill §
opi Open "I", #1, §
opo Open "O", #1, §
lof( Lof(#1) §
inp1 Input #1, §
pri1 Print #1, §
pri Print §
fr$( FileRead$("¨")
new$(§
clo1 Close #1 ; file #1 closed §
clo Close §
dim Dim My$(ct) §
ins Insert My$(0) Let My$(0)="¨" §
del Delete My$(¨) §
erase Erase My$() §
swap §
let §
rec Recall "\Masm32\include\Windows.inc", L$() §
sto Store "MyFile.txt", L$(), ct ; write ct strings to file §
left$(§
right$(§
mid$(§
new$(§
win$(§
ltrim$(§
rtrim$(§
trim$(§
lower$(§
upper$(§
instr( Instr_(§
rinstr(§
asc(§
cvi(§
cvl(§
min( Min(eax, ¨) ; rv in edx §
max( Max(eax, ¨) ; rv in edx §
timer §
for_ For_ n=0 To ebx-1 ¨ Next §
ism invoke SendMessage,
mb MsgBox 0, "¨", "Hi", MB_OK
.rep .Repeat ¨ .Until 0
.whi .While 1 ¨ .Endw
deb deb 1, "¨", eax, ecx, edx ;, esi$, edi$
tmp$ tmp$ CATSTR <Myarg=>, <¨> % echo tmp$
ae ä
oe ö
ue ü
ret0 xor eax, eax ret
olly ExternDef f2sOlly:DWORD .if f2sOlly==123 INT 3 .endif §
alert( alert("Test ¨: ")

The ones I use most frequently are rep, deb and mb ;-)
Title: Re: MasmBasic
Post by: hutch-- on January 17, 2010, 12:24:07 AM
 :bg

JJ,

You may have to change the name of your project to WASMbasic if you are building it with JWASM.  :P
Title: Re: MasmBasic
Post by: dedndave on January 17, 2010, 01:06:31 AM
go for a comprimise, Jochen.....

JJwBasic     :8)
Title: Re: MasmBasic
Post by: jj2007 on January 17, 2010, 09:53:37 AM
Quote from: hutch-- on January 17, 2010, 12:24:07 AM
You may have to change the name of your project to WASMbasic if you are building it with JWASM.  :P
Quote from: dedndave on January 17, 2010, 01:06:31 AM
go for a comprimise, Jochen.....

JJwBasic     :8)

The full name is actually "Inline Basic for use with Microsoft Macro Assembler" :wink
Anyway, I had googled for MasmBasic and didn't find hits, so I assume the copyright is with me :8)
If only I could convince myself to fix that bloody Val() problem... on the positive side, when trying to use the character table for the Val function, I got so upset about having to scroll all the time between the char table in the data section and the code section that I decided to add a new feature to RichMasm - The Pinboard:
(http://www.webalice.it/jj2006/pics/Pinboard.png)
Select some lines of code, press Control F12, and from then on these lines appear in a greyish extra window on top of the main text window. No need to scroll... try it out. Bug warning re Val() persists.

Another new feature: If in your code you select for example Print and press F1, the MasmBasic help will pop up. If you had selected CreateWindowEx, you'll get the corresponding page from \masm32\RichMasm\help\WIN32.HLP. The MB help is handled by RichMasm, so if it doesn't find the entry, it passes the request on to WinHelp.
:bg
Title: Re: MasmBasic
Post by: dedndave on January 17, 2010, 11:46:12 AM
Quote"Inline Basic for use with Microsoft Macro Assembler"

Ibumma ? - nawwww
Title: News from the RichEdit war
Post by: jj2007 on January 17, 2010, 10:56:24 PM
Loading big sources into a RichEdit 3.0 control can be quite slow. RichEdit 4.1 is about a factor ten faster, but all newer versions of RichEdit, included as MSFTEDIT.DLL in Win XP and as RichEd20.dll in Office 11/12 are broken: for SF_TEXT, their EM_STREAMOUT message skips occasionally some bytes, making them thus unusable for coding. The EM_GETSELTEXT message shows the same symptoms.

EM_GETTEXTRANGE seems to work, but it exports CR only instead of CRLF as next line characters.

Intensive researchTM has led to a breakthrough, though:

*** The EM_GETTEXTEX message seems NOT broken. ***

AT YOUR OWN RISK: To test them in RichMasm, copy one of these to

\masm32\RichMasm\dll\RichEditOffice.DLL

After loading an Asc or Rtf doc, you can press F8 to see loading time and dll version used.

Best choice is the Office 11/RichEdit 5.0, usually under
C:\Program Files\Common Files\Microsoft Shared\OFFICE11\RICHED20.DLL

Second best (half as fast) is Office 12/RichEdit 6.0, usually under
C:\Program Files\Common Files\Microsoft Shared\OFFICE12\RICHED20.DLL
The latter requires MSPTLS.DLL in the RichMasm.exe path.

in case you don't own MS Office: The Office 5 RichEd20.dll (18.06.2007, 1103280 bytes) is included in the free Word Viewer downloadable here (http://www.microsoft.com/downloads/details.aspx?familyid=3657CE88-7CFA-457A-9AEC-F4F827F20CAC&displaylang=en).

Bug warning re Val() persists, but being able to use the newer dlls makes a difference in loading time...!
Title: Re: MasmBasic
Post by: jj2007 on January 19, 2010, 06:54:37 PM
That copying of dlls stuff was horribly complicated, so I thought it would be easier if RichMasm.exe located that dll. Here is the new version, speedier than ever. It checks first if the user has installed a specific dll, then the availability of the Office 11 RichEd20.dll, then the (slower) Office 12 version, and finally, if all those fail, it uses the standard Windows riched20.dll.

Here is a snippet showing how it is done:
mov esi, offset LibNameOffice
invoke LoadLibrary, esi ; user-copied \masm32\RichMasm\Dll\RichEditOffice.DLL
.if eax==0
mov esi, RichEditV$
invoke ExpandEnvironmentStrings, chr$("%COMMONPROGRAMFILES%"), esi, MAX_PATH
mov ebx, eax
invoke lstrcat, esi, chr$("\Microsoft Shared\OFFICE11\RichEd20.DLL")
invoke LoadLibrary, esi ; RichEd20.dll, Office 11 version
.if eax==0
mov byte ptr [esi+ebx+24], "2" ; convert Office11 to Office12
invoke LoadLibrary, esi ; RichEd20.dll, Office 12 version
.if eax==0
mov esi, offset LibName
invoke LoadLibrary, esi ; RichEd20.dll for poor people
.endif
.endif
.endif
mov RichEditUsed, esi


EDIT: Attachment removed - the version on top of thread is more recent.
Title: Replace$
Post by: jj2007 on February 08, 2010, 04:39:14 PM
A minor update to the MasmBasic library: Replace$, not yet well tested but it looks promising.

Quoteinclude \masm32\MasmBasic\MasmBasic.inc   ; get it here (http://www.masm32.com/board/index.php?topic=12460)

.code
start:
   mov edi, chr$("\masm32\MasmBasic\WinIncs.htm")   ; the output file
   push Timer
   Open "O", #1, chr$("\masm32\MasmBasic\WinIncs.htm")
   Let ebx=FileRead$("\masm32\include\Windows.inc")+FileRead$("\masm32\include\WinExtra.inc")
   ; The '<' and '>' chars will be misinterpreted as html tags and must therefore be removed
   Let ebx=Replace$(ebx, chr$(60), "&lt;")      ; < = less than; src, search, repl [, case] [, count]
   Let ebx=Replace$(ebx, chr$(62), "&gt;")      ; > = greater than
   Let ebx="<html><head><title>Windows.inc and WinExtra.inc</title></head><body>"+ebx+"</body></html>"
   Let ebx=Replace$(ebx, CrLf$, chr$("<br>", 13, 10))   ; HTML needs <br>
   Let ebx=Replace$(ebx, "struct", "<font color='red'><b>Struct</b></font>", 1+4)      ; ignore case, find whole word only
   Let ebx=Replace$(ebx, "union", "<font color='red'><b>Union</b></font>", 1+4)
   Let ebx=Replace$(ebx, "qword", "<font color='blue'><b>qword</b></font>", 1+4)
   Print #1, Replace$(ebx, "PROTO", "Proto", 1+4)   ; MixedCase looks nicer ;-)
   Close
   void Timer         ; replacing "<" and ">" slows this down a lot: on a P4, 600 ms instead of 80 without
   pop ecx
   sub eax, ecx
   Print Str$("%i ms for replacing text in wininc & winextra\nand writing it to", eax), edi
   Exit
end start
Title: Re: MasmBasic
Post by: jj2007 on March 16, 2010, 10:08:43 PM
New version attached at top of thread:

After some hesitation, I introduced AutoSave for the RichMasm editor. Testing assembler code is a recipe for serious crashes, and while RichMasm had already a "Last Good Version" feature (i.e. a copy of the last version that assembled without errors), it keeps now also the very latest version. After five seconds of no typing activity, and only if there were edits, a FileName.tmp will be saved. After a crash, if you open the latest FileName.asc, you can choose to use the saved tmp version.

Another new feature: The F1 key performs a chained search in a) the MasmBasic help file and b) \masm32\RichMasm\help\WIN32.HLP
For example, if Exit (a MasmBasic function) is selected, F1 will show the MasmBasic entry for Exit. If ExitProcess is selected, F1 checks in the MasmBasic guide, doesn't find it, and displays instead the Win32.hlp ExitProcess page.

The BASIC library has now over 60 functions, mostly in string handling and file I/O. Most recent additions are Space$() and a fast Rinstr. The FileRead$ and Replace$ functions are a bit more flexible now.  For example, this is perfectly legal code, i.e. it assembles fine with ml.exe and Jwasm (see previous post for a complete app):

Quote   Let esi=FileRead$("\masm32\include\Windows.inc")+FileRead$("\masm32\include\WinExtra.inc")
   Let ebx=Replace$(esi, "struct", "<font color='red'><b>Struct</b></font>", 1+4)   ; 1=ignore case, 4=find whole word only
Title: Re: MasmBasic
Post by: jj2007 on March 21, 2010, 05:21:28 PM
Update (attached at top of thread):
- minor bugfix with CrtDate$ and CrtTime$
- for reasons of consistency, New$ is now called with Let instead of mov, e.g. Let My$=New$(1024)
- small improvements of the editor:
@@: nop

Hitting Return after the nop produces now the correct indent, in spite of the label. Another change:
.if eax
nop
.endif

Hitting Shift Return after the nop produces the indent needed for .endif (while a normal Return will insert the same indent as nop).
Title: Re: MasmBasic
Post by: jj2007 on March 25, 2010, 08:25:35 PM
Update 25.3.10: RichMasm.exe now opens Unicode text files correctly. However, the preferred way to edit Unicode resource files is to embed them at the bottom of the *.asc source, see "New Masm source":

Controls with resources simple controls, rc embedded in main src
Controls with Unicode simple controls using Arabic Unicode

Title: Re: MasmBasic
Post by: jj2007 on March 27, 2010, 10:26:02 PM
Update 27.3.: Only a few lines had to be changed to make it print a qword directly:

include \masm32\MasmBasic\MasmBasic.inc

.code
MyQ dq 123456789123456789
start:
Print "A qWord integer: ", Str$(q:MyQ), CrLf$, CrLf$
inkey "press any key"
Exit
end start


The q: trick is needed because there is (to my knowledge) no way to distinguish between a qword and a real8 variable. If somebody knows a workaround, please let me know.
Title: Re: MasmBasic
Post by: jj2007 on March 29, 2010, 03:20:16 PM
29.3.: Inkey added:
Quote   Inkey Str$("\nThis file has %2f kBytes\nhit any key to get outta here", Lof("MbGuide.rtf")/1024)

Output:

This file has 67.0 kBytes
hit any key to get outta here

Inkey behaves exactly like Print but waits for a keystroke.
Title: Re: MasmBasic
Post by: jj2007 on April 03, 2010, 12:14:43 AM
Version 9v (at the bottom of the first post) features two new functions for comparing strings and entire files. Their speed is competitive - about a factor five faster than their CRT equivalents for StringsDiffer.

QuoteStringsDiffer
   .if StringsDiffer("Hello", "Hallo")
      MsgBox 0, "The two strings are different", "Hi", MB_OK
   .endif
   test eax, StringsDiffer("Hello", "Hallo")
   .if Zero?
      MsgBox 0, "The two strings are equal", "Hi", MB_OK
   .endif
Rem[/color]   returns DWORD in eax
Key   -
FilesDiffer
   .if FilesDiffer("MyFileA.txt", "MyFileB.txt")
      MsgBox 0, "The two files are different", "Hi", MB_OK
   .endif
   Let esi="MyFileA.txt"
   test eax, StringsDiffer(esi, offset MyFileB)
   .if Zero?
      MsgBox 0, "The two files are equal", "Hi", MB_OK
   .else
      MsgBox 0, "The two files are different", "Hi", MB_OK
   .endif
Rem[/color]   returns DWORD in eax
Timings:
Intel(R) Celeron(R) M CPU        420  @ 1.60GHz (SSE3)
5802    cycles for StringsDiffer
27860   cycles for crt_strcmp
179912  cycles for lstrcmp

7363    cycles for StringsDiffer (case-insensitive)
32968   cycles for crt__stricmp
179374  cycles for lstrcmpi


EDIT: New version with pre-P4 brand string and improved SSE check
Title: Re: MasmBasic
Post by: MichaelW on April 03, 2010, 03:29:59 AM
A 5X difference between StringsDiffer and crt_strcmp is more than a little surprising, but the 1000X difference running on my P3 system suggests that something is wrong.

58      cycles for StringsDiffer
61084   cycles for crt_strcmp
52757   cycles for lstrcmp

56      cycles for StringsDiffer
60943   cycles for crt_strcmp
52862   cycles for lstrcmp

51      cycles for StringsDiffer
61150   cycles for crt_strcmp
52673   cycles for lstrcmp

Title: Re: MasmBasic
Post by: jj2007 on April 03, 2010, 06:25:15 AM
Hi Michael,
Could you please add the first line of the timing, i.e. the one that shows the SSE level?
As far as I know, the P3 has no SSE2, but I have somewhere in the Init procedure this snippet:
  db 0Fh, 0A2h ; cpuid 1
  bt edx, 26 ; edx bit 26, SSE2
  .if !Carry?
invoke MessageBox, 0, chr$("Sorry, MasmBasic needs SSE2"), 0, MB_OK
invoke ExitProcess, -99
  .endif

And for me the real surprise is that you don't see that box... ::)
Regards,
Jochen
Title: Re: MasmBasic
Post by: MichaelW on April 03, 2010, 07:19:30 AM
The first line is:
☺☺☻♥ (SSE1)
Where the first characters are ASCII codes 1, 1, 2, and 3.

The message box does show up, but not until the case-insensitive tests so I assumed that the case-sensitive tests do not require SSE2.




Title: Re: MasmBasic
Post by: jj2007 on April 03, 2010, 10:09:44 AM
Quote from: MichaelW on April 03, 2010, 07:19:30 AM
The first line is:
☺☺☻♥ (SSE1)
Where the first characters are ASCII codes 1, 1, 2, and 3.

The message box does show up, but not until the case-insensitive tests so I assumed that the case-sensitive tests do not require SSE2.


Thanks, Michael. I'll have to do something about the brand string issue in the ShowCPU proc. [EDIT: done, see post above]

As to the tests: They are all SSE2, case-sensitive and in-sensitive, otherwise you can't explain the speed increase. See also the Compare two strings thread (http://www.masm32.com/board/index.php?topic=13701.msg107604#msg107604).

I checked why the 'SSE2 required' box didn't show up from the beginning: It's because I did not use any of the commands (Print, Let, Dim) that trigger the init procedure in which the SSE2 runtime test is hidden.

Does anybody know a way to force a macro execution before any other code is run, i.e. some automatic call after the start: label?
Title: Re: MasmBasic
Post by: sinsi on April 03, 2010, 10:30:45 AM
>Does anybody know a way to force a macro execution before any other code is run, i.e. some automatic call after the start: label?


start:
RunMyMacro

By definition any macro run immediately after the 'END label" label is the first code to run...
Title: Re: MasmBasic
Post by: jj2007 on April 03, 2010, 02:39:22 PM
Quote from: sinsi on April 03, 2010, 10:30:45 AM
>Does anybody know a way to force a macro execution before any other code is run, i.e. some automatic call after the start: label?


start:
RunMyMacro

By definition any macro run immediately after the 'END label" label is the first code to run...

Yes, that is an option. But I was looking for something really fool-proof, i.e. ...
include \masm32\MasmBasic\MasmBasic.inc

.code
start: ; <<<< magic happens here
Exit
end start

... where the magic code is contained in the library. What does work is 'calling' a macro in the .const section, it does 'execute' but only in the sense that assembly time variables etc can be set.
Title: Re: MasmBasic
Post by: oex on April 03, 2010, 02:49:16 PM
Maybe create a 'start' macro but I'm not aware of any way to execute code before .code start.... I have an init function of sorts that runs at the beginning of most of my apps to setup essential infos
Title: Re: MasmBasic
Post by: dedndave on April 03, 2010, 03:13:02 PM
i don't see any problem with requiring an MBInit function call, Jochen
if you were to make MB a DLL, they would have to initialize that, too
Title: Re: MasmBasic
Post by: jj2007 on April 03, 2010, 03:45:44 PM
Quote from: oex on April 03, 2010, 02:49:16 PM
Maybe create a 'start' macro but I'm not aware of any way to execute code before .code start

Quote from: dedndave on April 03, 2010, 03:13:02 PM
i don't see any problem with requiring an MBInit function call, Jochen
if you were to make MB a DLL, they would have to initialize that, too

Ok, I'll make it optional. Normally, a Dim or Let or Print will trigger it automatically. For the new ShowCPU code taking account of pre-P4 processors, I have inserted a conditional call to the Mb init function (i.e. it remains compatible with 'normal' Masm32 code).

; select the two lines and press Control X to cut
; code for printing brand string and SSE level
   push 1
   call ShowCpu   ; print brand string and SSE level
ShowCpu proc ; mode:DWORD
COMMENT @ Usage:
  push 0, call ShowCpu ; simple, no printing, just returns SSE level
  push 1, call ShowCpu ; prints the brand string and returns SSE level@
  pushad
  sub esp, 80 ; create a buffer for the brand string
  mov edi, esp ; point edi to it
  xor ebp, ebp
  .Repeat
  lea eax, [ebp+80000002h]
db 0Fh, 0A2h ; cpuid 80000002h-80000004h
stosd
mov eax, ebx
stosd
mov eax, ecx
stosd
mov eax, edx
stosd
inc ebp
  .Until ebp>=3
  push 1
  pop eax
  db 0Fh, 0A2h ; cpuid 1
  xor ebx, ebx ; CpuSSE
  xor esi, esi ; add zero plus the carry flag
  bt edx, 25 ; edx bit 25, SSE1
  adc ebx, esi
  bt edx, 26 ; edx bit 26, SSE2
  adc ebx, esi
  bt ecx, esi ; ecx bit 0, SSE3
  adc ebx, esi
  bt ecx, 9 ; ecx bit 9, SSE4
  adc ebx, esi
  dec dword ptr [esp+4+32+80] ; dec mode in stack
  .if Zero?
mov edi, esp ; restore pointer to brand string
  .Repeat
.Break .if byte ptr [edi]!=32 ; mode was 1, so show a string but skip leading blanks
inc edi
.Until 0
.if byte ptr [edi]<32
print chr$("pre-P4")
.else
print edi ; CpuBrand
.endif
.if ebx
print chr$(32, 40, "SSE") ; info on SSE level, 40=(
print str$(ebx), 41, 13, 10 ; 41=)
.endif
  .endif
  add esp, 80 ; discard brand buffer (after printing!)
  mov [esp+32-4], ebx ; move ebx into eax stack position - returns eax to main for further use
  ifdef MbBufferInit
MbBufferInit
  endif
  popad
  ret 4
ShowCpu endp
Title: Re: MasmBasic
Post by: Ghandi on April 03, 2010, 03:59:08 PM
Another option with regards to running code before the app is executed would be to make a boilerplate entrypoint routine which is set as the entrypoint of the application (/ENTRY:WinMBStartup) and then have the user set their entrypoint as a MasmBasic variable. Then they can code as if nothing else had happened and you can run your checks or initializations in a small startup stub then thunk over to the declared entrypoint. There is one more thing though, if you did it this way you would have to tell the user not to call ExitProcess (unless absolutely necessary) so you can perform cleanup after their code is finished executing.

I know it is possible to manually create a TLS directory in a MASM built executable but is there any way we can do it from a source level? If so, you could place your initialization code inside the TLS callback and it would be called and notified of process attach/detach and thread attach/detach so you could handle any other code (if need be) in there as well. The benefit of a TLS callback is that the coder would just code like normal and when the app is run the TLS gets called and then their entrypoint with no need to interact, thunk or otherwise jump/call/push ret to the entrypoint.

I saw a tool over on WinASM forum which offers to update a TLS entry in an executable by searching for a byte sequence which precedes the TLS information and then updating the PE header. I suppose if it were something you were really determined to achieve, you could always code your own tool which passes on the ml and link.exe calls and when the file is produced, update the PE header and checksum so that the process is transparent to the end user (ofc making them fully aware that such a thing will happen if they so choose).  Just more conjecture mate, discard it as you see fit. :)

Seeing as im typing at 2:19am i suppose i can say Happy Whatever to everybody (replace whatever with your holiday/season), hopefully everybody has a good time with family and friends without overindulging too much.

HR,
Ghandi
Title: Re: MasmBasic
Post by: qWord on April 03, 2010, 04:15:27 PM
Quote from: jj2007 on April 03, 2010, 02:39:22 PMinclude \masm32\MasmBasic\MasmBasic.inc

.code
start: ; <<<< magic happens here
Exit
end start

maybe this is enough magic for you  :bg:
_ EQU init()
init macro
@init:
xor eax,eax
xor edx,edx
jmp $+4; ret
EXITM <jmp @init> ; or <call ...>
endm

start:_

Title: Re: MasmBasic
Post by: jj2007 on April 03, 2010, 04:23:37 PM
Quote from: qWord on April 03, 2010, 04:15:27 PM
maybe this is enough magic for you  :bg:

start:_


No, that's horribly complicated, my friend :bg

Ok, after thoroughly balancing your contributions, I have updated the library. This is a valid MasmTM app now:

include \masm32\MasmBasic\MasmBasic.inc
Init
Inkey Str$("Your puter has run %3f hours since the last boot, give it a break!", rv(GetTickCount)/3600000)
Exit
end start
Title: Re: MasmBasic
Post by: Ghandi on April 03, 2010, 05:42:49 PM
A valid *Masm*  or a valid *MasmBasic* app? :P

HR,
Ghandi
Title: Re: MasmBasic
Post by: jj2007 on April 03, 2010, 08:39:52 PM
Quote from: Ghandi on April 03, 2010, 05:42:49 PM
A valid *Masm*  or a valid *MasmBasic* app? :P

HR,
Ghandi

The code assembles with ml.exe version 6.15 and higher, and with JWasm. The only difference to a "standard" Masm app is that you include 11 libraries instead of 10...

\masm32\include\masm32rt.inc:

      include \masm32\include\dialogs.inc       ; macro file for dialogs
      include \masm32\macros\macros.asm         ; masm32 macro file
      includelib \masm32\lib\masm32.lib
      includelib \masm32\lib\gdi32.lib
      includelib \masm32\lib\user32.lib
      includelib \masm32\lib\kernel32.lib
      includelib \masm32\lib\Comctl32.lib
      includelib \masm32\lib\comdlg32.lib
      includelib \masm32\lib\shell32.lib
      includelib \masm32\lib\oleaut32.lib
      includelib \masm32\lib\ole32.lib
      includelib \masm32\lib\msvcrt.lib
Title: MasmBasic Release Candidate
Post by: jj2007 on April 26, 2010, 10:52:46 AM
Over the weekend I found some time to fix the MovVal bug, and to add a few goodies. So I reset the counter and call it now the Release Candidate ;-)

For major changes, check the help file (see top of thread, open in RichMasm, WordPad or MsWord); inter alia, look for:

- two-dimensional string arrays: Dim My$(ebx+1000, 255), then Let My$(2, 3)="Hello World"+... is now valid MASM syntax.
- assigning strings to Mid$ etc.: Let Left$(My$, 5)="Hallo" is valid MASM syntax, and works as expected.
- ASCII to number conversion: Several number formats added, see the Valid Number Formats (http://www.masm32.com/board/index.php?topic=13806.0) thread for detail.
- Val(), MovVal, Str$(): xmm registers, qwords, Real10/8/4, dwords, reg32, reg8 now supported
- easy-to-use float comparisons:
QuoteMyPI_low   REAL10   3.14159
; MyPI_low   dd    3   ; you could use dwords, real4/8/10, or, as second arg only, reg32 and immediate values

         Fcmp MyPI_low, PI, medium  ; the "medium" (or high/low) precision is optional
         .if Carry?
            Print Str$("MyPI_low at %f is lower than the real PI\n", MyPI_low)
         .elseif Zero?
            Print Str$("MyPI_low at %f is exact\n", MyPI_low)
         .else
            Print Str$("MyPI_low at %f is higher than the real PI\n", MyPI_low)
         .endif
Output: MyPI_low at 3.141590 is lower than the real PI

I have done some bug testing, but you can never be entirely sure. For the time being, you can find the library as MasmBasicRC.zip at the top of this thread. Feedback welcome, as always.

Quote- Preservation of xmm registers:
  xmm0 and xmm1 are frequently used in the library - don't rely on them; you can use a plain Print Str$(xmm0),
  but other Print or Let statements may trash xmm0/xmm1, since the two regs are needed for Len().
  xmm2 is used by Fcmp, StringsDiffer and FilesDiffer
  xmm3 to xmm7 will never be trashed
Title: Re: MasmBasic
Post by: frktons on April 27, 2010, 08:36:37 PM
Great job  :U
As soon as I move a little into ASM I'll give a try to your lib.
Hoping it will be a stable release when I'll get to that point.  :P

Thanks
Title: Re: MasmBasic
Post by: dedndave on April 27, 2010, 08:45:29 PM
Jochen has put a lot of work into it
you can bet it generates some pretty fast code   :U
Title: Re: MasmBasic
Post by: jj2007 on April 28, 2010, 05:27:56 PM
Quote from: frktons on April 27, 2010, 08:36:37 PM
Great job  :U
As soon as I move a little into ASM I'll give a try to your lib.
Hoping it will be a stable release when I'll get to that point.  :P

Thanks, Frank. The release is stable in the sense of "it works fine", but I am still adding features. For example, the Recall function that loads a string array is comfortable but I often work with spreadsheets; so tonight I added a few lines that allow to access the elements of a spreadsheet e.g. as
Print Matrix$(1000, 5), i.e. print row 1000, column 5.
include \masm32\MasmBasic\MasmBasic.inc
Init ; get a fat csv file here: http://mdgs.un.org/unsd/mdg/Handlers/ExportHandler.ashx?Type=Csv
Print "Load a 13 MB csv file, and get the address of each single element:", CrLf$
push Timer()
Recall "D:\ZIP_TEMP\MDG_Export_20100428_130002671.csv", L$(), csv
mov ebx, eax ; save the line count
void Timer()
sub eax, [esp]
push eax
timings=1 ; disactive to see some real strings
ife timings
Print CrLf$, "Full string:", CrLf$, "[", L$(0), "]", CrLf$
For_ n=0 To 0
else
For_ n=0 To ebx-1
endif
For_ ct=0 To 64
if timings
void L$(n, ct) ; for timings
else
Print L$(n, ct), CrLf$
endif
Next
Next
void Timer()
sub eax, [esp+4]
Print Str$("Your puter needed %i ms", eax)
pop eax
pop edx
Inkey Str$(", of which %i ms for Recall", eax)
Exit
end start

So all I need is Recall CL$(), L$(), csv to have a spreadsheet matrix at my fingertips...

@Dave: Yeah, most of them are pretty fast, but getting the addresses from all elements of that 13MB file takes over a second... sloooow :wink

I attach the version with the csv reader temporarily. The csv (or tab) flag is not yet documented.
Title: Re: MasmBasic
Post by: jj2007 on April 30, 2010, 07:26:41 PM
Temporary rc2704 removed above, more stable rc3004 attached at top of thread. Inter alia, it can now read and write csv files - see attached demo.
It reads a 13 MB csv file in 32 milliseconds, roughly a factor 100 faster than ExcelTM :toothy
Title: Re: MasmBasic
Post by: frktons on May 02, 2010, 03:03:53 PM
Have you ever used the library in a PB program?
I mean is it a simple task calling the masm functions in your
library within a PB program?

Thanks

Frank
Title: Re: MasmBasic
Post by: jj2007 on May 02, 2010, 05:10:35 PM
Frank,
Afaik direct linking of obj files is not possible with PB, but nothing stops you from putting the required calls into a dll. Check

\masm32\RichMasm\Res\MiniDll.asc
\masm32\RichMasm\Res\MiniDll_call.asc

Otherwise, explain a bit what you need, or PM me.

P.S.: Spreadsheet example updated, see SpreadsheetDemo2.zip above.
Title: Re: MasmBasic
Post by: frktons on May 02, 2010, 05:15:14 PM
I was thinking about using your quick sort function inside a PB
program, instead of the PB Function that is a bit slow. This is
just a first idea, because if I learn how to use the lib you are building,
I could use many more functions as well.  :wink

Thanks
Title: Re: MasmBasic
Post by: dedndave on May 02, 2010, 10:23:04 PM
if you were to use Jochen's library in PB, you might have a few naming conflicts   :P
get past that, though - i think the PB community would really appreciate it
Title: Re: MasmBasic
Post by: frktons on May 03, 2010, 03:29:17 AM
Quote from: dedndave on May 02, 2010, 10:23:04 PM
if you were to use Jochen's library in PB, you might have a few naming conflicts   :P
get past that, though - i think the PB community would really appreciate it

Or maybe the PB community would really appreciate the possibility of using
faster code for some tasks  :lol

Well I'm thinking about a couple of ways of doing it:

- use the source of MASM quick sort and translate it into INLINE ASM
- use a DLL instead of a STATIC LIB

And there are probably other ways I'm not aware of.  ::)

Frank
Title: Re: MasmBasic
Post by: jj2007 on June 30, 2010, 08:18:13 AM
Bug fix: KSS (http://www.masm32.com/board/index.php?topic=13741.msg114059#msg114059) discovered that wInstr (i.e. the Unicode version of Instr_) did not deliver correct values. New version attached on top of thread.

Most important new function:
QuoteSetWin$
   SetWin$ hWnd="A new title for my app"
Rem[/color]   for main windows and controls; you can use string concatenation as in Let
Title: Re: MasmBasic
Post by: jj2007 on July 01, 2010, 09:39:14 PM
The wide (Unicode) version of Instr returned a match if the pattern was longer than the source. Fixed in MasmBasicRC010710.zip at top of thread.

Quoteinclude \masm32\MasmBasic\MasmBasic.inc
   
Init
   wData wSource, "Another test for seeing if wInstr works fine", 0
   wData wPattern, "wInstr WORKS", 0
   .if wInstr(offset wSource, offset wPattern, 1)   ; startpos default, src, pattern, 1=case-insensitive
      invoke MessageBoxW, 0, eax, wChr$("The match:"), MB_OK
   .else
      invoke MessageBoxW, 0, offset wPattern, wChr$("NO MATCH:"), MB_OK
   .endif
   
Exit
end start
Title: Re: MasmBasic
Post by: jj2007 on July 05, 2010, 03:50:07 PM
Finally I could convince the editor to remember window position and size. New version attached on top of thread (5 July).
Title: Re: MasmBasic
Post by: jj2007 on July 21, 2010, 04:56:42 PM
Version 22 July 2010 (attached at the bottom of post #1) features a major remake of the Recall macro. Inter alia, it will now ignore single LF characters in strings, and will not stumble over text files that end without a CRLF. Recall is actually pretty stable now: I have run it through a stress test with a randomised number of strings with variable (randomised) lengths, and the last version didn't choke any more for tens of Gigabytes. Which shows also that HeapAlloc is a safe way of organising Millions of small allocations.

Two new features are Cat$ and Clip$(), also in wide (Unicode) versions. SetWin$ and Win$() are now also available as Unicode versions.

QuoteRecall
   Recall "\masm32\include\winextra.inc", MyRec$()
   mov lc, Min(eax, 20)
   Print Str$("%i lines found", lc)
   For_ n=0 To lc-1
      Print Str$("\nRec %i\t", n)
      Print Left$(MyRec$(n), 50)
   Next
   Recall "MyFile.csv", MyRec$(), csv   ; loads a spreadsheet in comma separated values format
   Recall "MyFile.txt", MyRec$(), tab   ; loads a spreadsheet in tab-delimited format
Rem[/color]   - returns lines in eax (null if an error occurred), and the number of total bytes read in edx
   - see Store below for saving arrays
   - with the spreadsheet variants, single cells can be accessed via Let My$=MyRec$(row, column)[/b]

QuoteClip$, wClip$
   Print "[", Clip$(), "]"      ; displays the content of the clipboard
   MsgBox 0, Clip$(), "Text on the clipboard:", MB_OK   ; same as MessageBox
            MsgBox 0,\
            Cat$("The text on the clipboard:"+CrLf$+String$(33,"-")+CrLf$+Clip$(20)+CrLf$+String$(0,0)),\
            "MasmBasic:", MB_OK   ; displays a MessageBox with two horizontal delimiters
            MsgBox 0, Clip$(40), "The text on the clipboard, truncated to 40 chars:", MB_OK
            invoke lstrcpy, offset my40charbuffer, Clip$(40-1)   ; yep, don't forget space for the zero delimiter
Rem[/color]   - returns ptr in eax
   - you can truncate the content for security reasons, e.g. for use in a MessageBox
   - if no argument is specified, up to 160k will be copied into the internal buffer[/b]

QuoteCat$, wCat$
   MsgBox 0, Cat$("The content of the editbox is"+CrLf$+Win$(hEdit)), "Info", MB_OK
Rem[/color]   returns ptr in eax and MbCat$
   - Cat$ is meant to replace Let My$=... in MessageBox or similar situations
   - every use of Cat$ overwrites content in the dedicated Cat$ buffer; mov myptr, Cat$() is
     therefore pretty useless. If you want permanent strings, use Let[/b]
Title: Re: MasmBasic
Post by: jj2007 on August 26, 2010, 10:51:44 PM
27 August 2010 news:

Dim is no longer limited to string arrays. You can now use it for arrays of DWORDs, WORDs, BYTEs and even structures such as RECT etc:
Dim MyFloats(5)  As FLOATSTRUC
Dim Mybyte(99) as BYTE
Dim Ws(eax) As WNDCLASSEX


QuoteFLOATSTRUC STRUCT
f4   REAL4 ?
f8   REAL8 ?
f10   REAL10 ?
fsrect   RECT <?>
filler   WORD ?
FLOATSTRUC ENDS

   Dim MyFloats(5) As FLOATSTRUC      ; Create an array of structures in heap memory, with 5 elements
   fldpi      ; push PI on the FPU (3.14159265358979324)
   fst MyFloats(3, f4)      ; load PI into the REAL4 and REAL8 members
   fst MyFloats(3, f8)
   fstp MyFloats(3, f10)      ; load PI into the REAL10 member, and pop ST
   
Let MyFloats(4)=MyFloats(3)      ; copy array element #3 into array element #4
   Print Str$("\nTesting structures:\nResult 4, f10=%If\n", MyFloats(4, f10))   ; show the result (%If means full precision; use 0...9, A...I)
   MovVal MyFloats(4, f10), chr$("123.456e97")   ; convert an Ascii string, and move it directly into array member #4, f10 (the REAL10 member)
   Print Str$("Result 4, f10=%f\n", MyFloats(4, f10))   ; show the result (%f means default precision)
   
Let MyFloats(0)=MyFloats(4)      ; copy array element #4 into array element #0
   push esi      ; your responsibility to preserve esi
   MyFloats(
4:esi)      ; from now on, use esi for array element #3 - same as ASSUME
   fld MyFloats(f8)      ; push the REAL8 member onto the FPU
   fstp MyFloats(f10)      ; load the value into the REAL10 member, and pop ST
   Print Str$("Result ?, f10=%f\n", MyFloats(f10))   ; OK
   Print Str$("Result 4, f10=%f\n", MyFloats(4, f10))   ; OK
   MyFloats(
4:none[/color])      ; release esi, back to normal mode (where edx is used for every call)
   pop esi      ; restore esi
   Print Str$("Result 0, f10=%f\n", MyFloats(0, f10))   ; show the results for three array members and their REAL10 elements
   Print Str$("Result 3, f10=%f\n", MyFloats(3, f10))
   Print Str$("Result 4, f10=%f", MyFloats(4, f10))

etc... have fun :bg

P.S.: Typechecking rules apply, e.g.    movq xmm0, MyFloats(ecx, f8) works if f8 is a REAL8 member
Title: Re: MasmBasic
Post by: jj2007 on August 27, 2010, 06:55:51 PM
27 August 2010, minor bugfix: JWasm choked over wLet My$=wChr$("Test")+wCrLf$
Check version MasmBasic270810b.zip on top of this thread.
Title: Re: MasmBasic
Post by: jj2007 on September 13, 2010, 11:35:13 PM
Just discovered that the help file still has the old version for printing qwords and REAL4. Note that prefixes are no longer needed, except for Sqrt (I am working on that one) and if you want to use xmm regs in float mode:

Quoteinclude \masm32\MasmBasic\MasmBasic.inc
.data
MyReal4   REAL4   3.1416
MyPI   REAL10   3.14159265358979323846
MyQword   dq   0
MyR4   REAL4   0.0
V32QW   dq   36
V32R4   REAL4   36.0

   
Init
[/color]
   MovVal f:xmm0, Left$(Chr$("123.4567"), 6)      ; to use xmm regs in float mode, use the f:
   Print Str$("MyXmm=\t%f\n", f:xmm0)         ; prefix both for MovVal and Str$
   MovVal xmm0, Left$(Chr$("123.4567"), 6)      ; same xmm reg but in integer mode
   Print Str$("MyXmm=\t%f\n", xmm0)
   
   Print Str$("Square root QWord \t%If\n", Sqrt(q:V32QW))   ; q: qword prefix
   Print Str$("Square root Real4 \t%If\n", Sqrt(s:V32R4))   ; s: single prefix
   
   MovVal MyQword, Chr$("123.4567")         ; NO prefix required for
   Print Str$("MyQword=\t%f\n", MyQword)      ; qwords and
   MovVal MyR4, Chr$("123.4567")         ; REAL4 in MovVal, Str$
   Print Str$("MyR4=\t%f\n", MyR4)
   Fcmp MyReal4, MyPI
   .if !Carry?
      Inkey Str$("The rounded value %f", MyReal4), Str$(" is higher than the real PI, %Jf", MyPI)
   .else
      Inkey Str$("The rounded value %f", MyReal4), Str$(" is lower than the real PI, %Jf", MyPI)
   .endif
   Exit
end start

Since xmm regs can be used both as floats and as integers, the f: prefix is needed if you want to use it as a float reg (the assumption being that we use it more often for integers).
Title: Re: MasmBasic
Post by: Dharam on September 26, 2010, 10:28:03 PM
I still am not sure whether this file masmbasic.inc is availble for general testing or not.  It it is available, where is it?
Title: Re: MasmBasic
Post by: ecube on September 27, 2010, 01:51:18 AM
I wish to the source of masmbasic, THANKS  :thumbu
Title: Re: MasmBasic
Post by: jj2007 on September 27, 2010, 06:41:25 AM
Quote from: Dharam on September 26, 2010, 10:28:03 PM
I still am not sure whether this file masmbasic.inc is availble for general testing or not.  It it is available, where is it?

In the first post of this thread, a zip file is attached. Open it, and double-click on ReadMeMasmBasic.txt
Title: Re: MasmBasic
Post by: jj2007 on September 27, 2010, 07:50:51 AM
Quote from: E^cube on September 27, 2010, 01:51:18 AM
I wish to [see] the source of masmbasic, THANKS  :thumbu

Cube,

MB as such is not open source, sorry. However,
- MasmBasic.inc is visible - and there are all the macros
- if you are really curious, insert int 3 into the macro you want to investigate, and Olly will show you the way.

In case MB does not behave as a proper BASIC should, post your code here, and we'll investigate the bug if there is one (I currently know of one, but it's fairly exotic: Dim Something As BYTE will not work together with Print Str$(Something(123)).
Title: Re: MasmBasic
Post by: jj2007 on November 12, 2010, 10:13:12 PM
Update with three new functions: PopCount() (http://www.masm32.com/board/index.php?topic=15286.0), Percent (http://www.masm32.com/board/index.php?topic=15263.0)(), Rand (http://www.masm32.com/board/index.php?topic=11679.0)()
Note this is a beta, not thoroughly tested.

QuotePopCount
[/color]   PopCount(MySource, ecx)            ; standalone: set count to ecx
   mov ebx, 88888888h
   Print Str$("In ebx, %i bits are set", PopCount(ebx))   ; for use with Str$() etc
   void PopCount(ebx)               ; returns bitcount in eax
   mov MyVar, PopCount(MySource)
Rem   [/color]runs in about 7 cycles on a Celeron M; requires Init or at least one Str$(0) before


Percent, [/color]f4Percent, f8Percent, fpuPercent
[/color]            Print Str$("f4pc(srcr10, 33.33)=\t%If\n", f4Percent(srcr10, 33.33))   ; f4: returns REAL4
            Print Str$("f8pc(srcr10, 33.33)=\t%If\n", f8Percent(srcr10, 33.33))   ; f8: returns REAL8 e.g. for use with xmm regs
            Print Str$("fpupc(srcr10, pcr10)=\t%If\n", fpuPercent(srcr10, pcr10))   ; fpu: leaves result in ST(0)
            Print Str$("fpc(12345.678, ebx)=%f\n", f8Percent(12345.678, ebx))
            Print Str$("fpc(12345.6, ebx)=%f\n", f8Percent(12345.6, ebx))
            Print Str$("pc(12345.0, ebx)=%f\n", Percent(12345.0, ebx))      ; with immediate real source and reg32 percentage
            Print Str$("pc(srcdd, ebx)=%f\n", Percent(srcdd, ebx))         ; with DWORD source and reg32 percentage
            Print Str$("pc(12345, 20)=%f\n", Percent(12345, 20))         ; with immediate integer source and percentage
            movq xmm0, f8Percent(srcr10, 33.33)
            Print Str$("xmm0=%f\n", f:xmm0)
            movd xmm0, Percent(srcr10, 33.33)
            Print Str$("xmm0=%f\n", xmm0)
Rem   source can be almost anything, same for percentage


Rand
            Rand()                     [/color]; empty args = initialise using rdtsc
            Rand(0, 100, xmm1)      ; 0....+100, dest can be local/global REAL8 var or xmm
            Rand(0, ebx, MyReal8)   ; 0....ebx, dest can be local/global REAL8 var or xmm
            Rand(0, 100)               ; 0....+100, left on FPU in st(0)
            Rand(-5.5, 9.3)            ; -5.3...+9.3, left on FPU in st(0)
            Print Str$("-5.5, 9.3: ST(0)=\t%If\n", ST(0))
            void Rand(123)            ; leaves dword in eax
            mov ecx, Rand(123)      ; range 0...123
            mov ecx, Rand(MyDword)   ; range passed as dword variable
Rem   [/color]- high-speed RNG generates pseudo random sequence with excellent randomness
   - for testing, do not initialise; for release version, use Rand() before the innermost loop
   - credits to Alex Bagayev for his AxRand algo (http://www.masm32.com/board/index.php?topic=11679.msg122749#msg122749)

EDIT: Attachment removed, valid version is attached to top of thread, page 1
Title: Re: MasmBasic
Post by: Antariy on November 12, 2010, 10:19:40 PM
Jochen, is PopCount with lookup table?

Edited: Yes, I see - it is.
Title: Re: MasmBasic
Post by: jj2007 on November 12, 2010, 10:26:36 PM
Yes, generated on the fly during Init.
Title: Re: MasmBasic
Post by: jj2007 on November 12, 2010, 10:29:03 PM
Quote from: Antariy on November 12, 2010, 10:19:40 PM
Jochen which count of downloads have your archive from post above? Something interesting - I see 0, but I have downloaded it.

Alex, I have updated the archive with your correct name spelling in the MbGuide.rtf help file. That is why you see 0 downloads - it is a new archive. Note the tiny difference in the filename.
Title: Re: MasmBasic
Post by: Antariy on November 12, 2010, 10:35:15 PM
Quote from: jj2007 on November 12, 2010, 10:29:03 PM
Alex, I have updated the archive with your correct name spelling in the MbGuide.rtf help file. That is why you see 0 downloads - it is a new archive. Note the tiny difference in the filename.

Maybe that is reason. Some days ago - at time when I click on the link at Frank's tesd-bed thread, he are remove archive from post at the same time - and browser thread was freezed - very funny  :green2
Title: Re: MasmBasic
Post by: jj2007 on November 14, 2010, 12:05:47 AM
Alex pointed me to an omission in the documentation of Rand(): the higher end of the range is not included.

esi=-100, ebx=100; run 1=lowest, run 2=highest value
0, 100:    xmm1=        0.0
0, ebx:    xmm1=        0.0
esi, 0:    xmm1=        -100.000000000000000
esi, ebx:  xmm1=        -100.000000000000000
0, 100:    ST(0)=       0.0
-5, 9:     ST(0)=       -5.00000000000000000
-5.5, 9.3: ST(0)=       -5.50000000000000000
0, 1:      destR8=      0.0
0, -1:     destR8=      0.0
mov ecx, Rand(123):     0.0

0, 100:    xmm1=        99.9999999767170777
0, ebx:    xmm1=        99.9999999767170777
esi, 0:    xmm1=        -2.32829089411024093e-08
esi, ebx:  xmm1=        99.9999999534341697
0, 100:    ST(0)=       99.9999999767170911
-5, 9:     ST(0)=       8.99999999674039275
-5.5, 9.3: ST(0)=       9.29999999655413019
0, 1:      destR8=      0.999999999767170800
0, -1:     destR8=      -0.999999999767170911
mov ecx, Rand(123):     122.000000000000000


Generated by:
  Rand(0, 100, xmm1) ; 0...100 (exclusive), dest can be local/global REAL8 var or xmm
  Print Str$("0, 100:    xmm1=\t%If\n", f:xmm1)
  Rand(0, ebx, xmm1) ; 0...100 (exclusive), dest can be local/global REAL8 var or xmm
  Print Str$("0, ebx:    xmm1=\t%If\n", f:xmm1)
  Rand(esi, 0, xmm1) ; 0...100 (exclusive), dest can be local/global REAL8 var or xmm
  Print Str$("esi, 0:    xmm1=\t%If\n", f:xmm1)
  Rand(esi, ebx, xmm1) ; 0...100 (exclusive), dest can be local/global REAL8 var or xmm
  Print Str$("esi, ebx:  xmm1=\t%If\n", f:xmm1)
  Rand(0, 100) ; 0...100 (exclusive), left on FPU in st(0)
  Print Str$("0, 100:    ST(0)=\t%If\n", ST(0))
  fstp st ; correct FPU stack
  Rand(-5, 9) ; -5...+9, left on FPU in st(0)
  Print Str$("-5, 9:     ST(0)=\t%If\n", ST(0))
  fstp st ; correct FPU stack
  Rand(-5.5, 9.3) ; -5.3...+9.3, left on FPU in st(0)
  Print Str$("-5.5, 9.3: ST(0)=\t%If\n", ST(0))
  fstp st ; correct FPU stack
  Rand(0, 1, destR8) ; 0...1 (exclusive), dest can be local/global REAL8 var or xmm
  Print Str$("0, 1:      destR8=\t%If\n", destR8)
  Rand(0, -1, destR8) ; -1...0, dest can be local/global REAL8 var or xmm
  Print Str$("0, -1:     destR8=\t%If\n", destR8)
  void Rand(123) ; leaves dword in eax
  mov ecx, Rand(123) ; range 0...123
  Print Str$("mov ecx, Rand(123): \t%If\n\n", ecx)
Title: Re: MasmBasic
Post by: hutch-- on November 14, 2010, 01:16:04 AM
I still want a copy of the "Espresso Machine" code when it becomes available.  :bg
Title: Re: MasmBasic
Post by: dedndave on November 14, 2010, 02:57:41 AM
yah, Jochen - that Rand function isn't washing our dishes over here   :bg

Z sends a K
Title: Re: MasmBasic
Post by: jj2007 on November 14, 2010, 08:27:51 AM
Quote from: hutch-- on November 14, 2010, 01:16:04 AM
I still want a copy of the "Espresso Machine" code when it becomes available.  :bg

Hutch,
Please send the documentation of the interface. USB port, or is it one of those stone age machines that are addressed through the serial port?
:wink

Quote from: dedndave on November 14, 2010, 02:57:41 AM
yah, Jochen - that Rand function isn't washing our dishes over here   :bg

Dave,
If it was, it would be the World's fastest dish washer, of course - the macro version of AxRand runs in 13 cycles, and is 21 bytes short.

But the implementation would be a bit, ehm, challenging. My advice: Take a big hammer. After 13 minutes of hard work, your china will look sufficiently random :bg

Quote
Z sends a K
J sends 2 K :red  (to Z, not to you, of course)
Title: Re: MasmBasic
Post by: hutch-- on November 14, 2010, 08:53:33 AM
JJ,

I was hoping for SATA 6.
Title: Re: MasmBasic
Post by: jj2007 on November 14, 2010, 09:45:39 AM
Quote from: hutch-- on November 14, 2010, 08:53:33 AM
JJ,
I was hoping for SATA 6.

Hutch,
When I watch the barmen preparing coffee here in Italy, yes they are definitely very fast, but 6 Gbits/s...????
::)
Title: MasmBasic: Dll & Declare, wCL$(), Err$()
Post by: jj2007 on November 23, 2010, 11:03:29 PM
New version attached at the end of the first post (some lines above Dave's post (http://www.masm32.com/board/index.php?topic=12460.msg95704#msg95704)).

What's new?

Quoteinclude \masm32\MasmBasic\MasmBasic.inc      ; include this library
      Init      ; initialise the app
      Dll "shimgvw"      ; load the shell image view dll aka Windows Picture and Fax Viewer Library
      Declare ImageView_Fullscreen, 4      ; ImageView_Fullscreen expects 4 dwords
      void ImageView_Fullscreen(0, 0, wCL$(1), SW_SHOW)   ; we need the wide version of the commandline arg
      Err$(1)      ; there is no retval, so we have to test for errors
      Exit      ; do a clean exit, inter alia FreeLibrary
[/color]
end start

Dll "name" loads a dll with LoadLibrary
Declare dllfunction, #args defines a macro that can be used e.g. as mov eax, MyFunc(1, eax, 3)
Housekeeping (FreeLibrary) is done with the Exit statement
The example above needs a Unicode filename, therefore wCL$().
See reply 155 (http://www.masm32.com/board/index.php?topic=12460.msg124805#msg124805) for the PopCount and Rand() functions.
Title: Re: MasmBasic: Dll & Declare, wCL$(), Err$()
Post by: Antariy on November 23, 2010, 11:46:30 PM
Jochen, for Dll macro, I guess, you can return index of the DLL in EDX, in addition to EAX's handle.
Title: Re: MasmBasic: Dll & Declare, wCL$(), Err$()
Post by: jj2007 on November 24, 2010, 07:22:10 AM
Quote from: Antariy on November 23, 2010, 11:46:30 PM
Jochen, for Dll macro, I guess, you can return index of the DLL in EDX, in addition to EAX's handle.

Old:
MbDllCt = -4
Dll MACRO name
  invoke LoadLibrary, repargA(name)
  MbDllCt = MbDllCt + 4
  mov DllTable[MbDllCt], eax
ENDM


New:
MbDllCt = -4
Dll MACRO name
  invoke LoadLibrary, repargA(name)
  MbDllCt = MbDllCt + 4
  mov edx, MbDllCt  ; <-------------------- like this?
  mov DllTable[MbDllCt], eax
ENDM


Like this? But how would you use this value?
Title: Re: MasmBasic: Dll & Declare, wCL$(), Err$()
Post by: Antariy on November 24, 2010, 09:52:28 PM
Quote from: jj2007 on November 24, 2010, 07:22:10 AM
Like this? But how would you use this value?

Well, this can be convenient, can be. (maybe I'll want to replace handle of dll in the table) :P

:bg
Title: MasmBasic bugfix
Post by: jj2007 on November 27, 2010, 01:17:50 AM
Bugfix: CL$() returned the commandline correctly but unfortunately did not correct the stack properly :red
Use version 27.11.2010 on top of thread. It has also a slight improvement of the Declare macro.
The snippet below g-zips the file obtained from the commandline.

Quoteinclude \masm32\MasmBasic\MasmBasic.inc
   Init
   Dll "\masm32\RichMasm\zLib\zlib1.dll"  ; make sure zlib1.dll is present
   Declare gzopen, C:2
   Declare gzwrite, C:3
   Declare gzclose, C:1
   mov ebx, gzopen("TheTest.gz", "wb6")
   Let esi=FileRead$(CL$())
   mov ecx, gzwrite(ebx, esi, Len(esi))
   Inkey Str$("retval=%i, ", gzclose(ebx)), Str$("compressed=%i\n", ecx)
   Exit
end start
Title: Re: MasmBasic
Post by: dedndave on November 27, 2010, 03:02:30 AM
oops !
glad you fixed it, Jochen

Z sends a K - no tongue  :P
Title: Re: MasmBasic
Post by: jj2007 on November 27, 2010, 07:43:09 AM
Quote from: dedndave on November 27, 2010, 03:02:30 AM
Z sends a K - no tongue  :P
Hey, you are not jealous, are you?

@Alex: Set RetDllCt = 1 to get in edx the handle offset (mov DllTable[edx], eax)

QuoteRetDllCt = 0  ; default: don't return the offset
[/b]Dll [/color]MACRO name
  invoke LoadLibrary, repargA(name)
  test eax, eax
  ExternDef MbError0:NEAR
  je MbError0
  MbDllCt = MbDllCt + 4
  if RetDllCt
   push MbDllCt
   pop edx
   mov DllTable[edx], eax
  else
   mov DllTable[MbDllCt], eax
  endif
ENDM

Declare allows now C calling convention and variable # of args:
Quote   Declare gzwrite, C:3   ; C calling convention, three args
Quote   Dll "msvcrt"
   Declare sprintf, C:?   ; C calling convention, variable # of args
   void sprintf(offset msgtext, "%016I64u", i64)      ; low & high dword of i64 managed by macro
   Print offset msgtext, 13, 10
   ; Masm32 syntax for static link: invoke crt_sprintf, offset msgtext, offset format, i64
void means discard the retval (which is a rather useless "# of chars written" for sprintf).
Title: Re: MasmBasic
Post by: jj2007 on November 30, 2010, 10:34:22 AM
Update (attached on top of thread):

Quoteinclude \masm32\MasmBasic\MasmBasic.inc
   Init
   GetFiles \masm32\m32lib\*.asm
   ZipFiles "The_Masm32_lib"
   UnZipFiles "The_Masm32_lib", "\masm32\ZipTest"
   Inkey "Archive zipped & unzipped, everything ok?"
   Exit
end start

This full-fledged Windows console application assembles fine with Masm 6.15 and higher or JWasm, and
- zips the whole \masm32\m32lib\*.asm folder
- and unzips it to \masm32\ZipTest\masm32\m32lib\*.asm
Compression is roughly 10:1, with 53,775 bytes for The_Masm32_lib (for comparison: WinZip "Maximum portable": 182,884 bytes)

For options, see MbGuide.rtf in the MasmBasic package.
Title: Re: MasmBasic
Post by: jj2007 on December 13, 2010, 11:50:11 PM
Update (attached on top of thread): New AddFiles, AddFolders, SendData functions.

GetFiles has got companions, and has learnt to recurse into subdirectories:
QuoteGetFiles, AddFiles
   GetFiles filter [, startpattern] [, endpattern  or lines matching] [, case sensitivity and full mode]
   GetFiles *.inc      ; fill the Files$() array with *.inc files of the current directory
   AddFiles Help\*.hlp
|*.chm   ; add to the Files$() array hlp or chm files from the Help subfolder
   mov ebx, eax      ; eax=# of files found
   Print Str$("\nFound %i files matching *.inc:", ebx)
   For_ n=0 To ebx-1
      Print CrLf$, Files$(n)
   Next

QuoteGetFolders, AddFolders
   GetFolders         ; fill the Files$() array with folders and subfolders starting with the current directory
   AddFolders \Masm32\include\*      ; add to the Files$() array folders and subfolders of the specified directory
Rem[/color]   - returns # of created lines in eax and MbGetFileCount
   - can be combined with GetFiles/AddFiles

ZipFiles
   GetFiles[/color] \masm32\m32lib\*.asm
   ZipFiles "The Masm32 lib"   ; the minimum: just the name of the *.arc archive
   
; with archive name, file count, show, Launch console mode:
   ZipFiles "The_Masm32_lib", 10, SW_MINIMIZE,
CREATE_NEW_CONSOLE   ; use first 10 files and a minimised new console
Rem[/color]   - requires FreeArc in its default location (e.g. C:\Program Files\FreeArc\bin\Arc.exe)
   - creates archive in *.arc format
   - return value: see Launch
   - use MbZipLog = 1 to see the command lines in ZipLog.txt
Key   -

UnZipFiles

   
UnZipFiles "The_Masm32_lib"      ; unzip The_Masm32_lib.arc, restoring the tree on the current drive
   ; with archive name, a new destination folder, show, Launch console mode:
   UnZipFiles[/color] "The_Masm32_lib", "\masm32\ZipTest", SW_MINIMIZE, CREATE_NEW_CONSOLE   ; unzip the tree to new folder
Rem[/color]   - requires FreeArc in its default location (e.g. C:\Program Files\FreeArc\bin\Arc.exe)
   - creates archive in *.arc format
   - return value: see Launch
   - use MbZipLog = 1 to see the command lines in ZipLog.txt

For Inter-Process Communication, the SendData/CopyData$() pair is easy to use:
QuoteCopyData$()
   SetWin$ hEdit="Just received:"+CrLf$+CopyData$()+CrLf$+"--- end of data ---"      ; use directly to set a window content
   Let My$="Just received:"+CrLf$+CopyData$()+CrLf$+"--- end of data ---"      ; store away for later use
Rem[/color]   - for receiving data from other apps; for use inside a WM_COPYDATA message handler, for example:
  SWITCH uMsg
  CASE WM_COPYDATA
      Let My$=CopyData$()+CrLf$+"received "+Time$

For sending data, use SendData

SendData
   SendData "MyClient", Win$(hEdit)
   SendData "MyClient", "How are you?"
Rem[/color]   - returns DWORD in eax: 0=no client found
   - can also be used from a Win32 console application
Title: Re: MasmBasic
Post by: jj2007 on December 14, 2010, 10:00:36 PM
With bugfixes, version 141210b is attached on top of thread. Note the syntax for Timer has changed - before it was Timer(), but I have now found a way to convince MASM 6.15, 9.0 and JWasm to accept that there are no brackets. In general, I try to avoid useless trailing brackets; there are a few exceptions, such as
Let My$=Clip$()    ; get all available text from clipboard
Let My$=Clip$(100) ; get up to 100 bytes

Let My$=CL$(0)     ; get arg #0, i.e. the current executable
Let My$=CL$()      ; get first arg of the commandline (i.e. #1 is the default arg)
Let My$=CL$(2)     ; get second arg of the commandline


The Server/Client example for IPC with SendData/CopyData$ has been improved, too.

Alex (Antariy) asked me if GetFiles checks for maximum recursion depth. Actually, it doesn't, and tests seem to prove that it doesn't matter. There is an old thread discussing this:

Quote from: zooba on June 24, 2007, 01:02:16 PM
The stack reserves the size specified by the linker but it doesn't commit it until you try and access it. It detects attempted accesses using a guard page, so the first time you attempt to access a page that hasn't been committed, Windows will catch an exception and commit it. However, it only guards one page, which is the next uncommitted page. Attempting to access the page beyond the guard page will cause an access violation exception.

The critical sentence here is "Attempting to access the page beyond the guard page will cause an access violation exception". A recursive FindFirstFile proc allocates a few hundred bytes per recursion, and thus will never throw an exception. Attached is a zip archives that extracts two zero byte files to a 48 levels deep folder ("use folder names" option in WinZip required). Test it with this snippet:

include \masm32\MasmBasic\MasmBasic.inc ; http://www.masm32.com/board/index.php?topic=12460
Init
GetFiles \masm32\RichMasm\*.rt ; recurse until you find files with extension *.rt
push eax
For_ n=0 To eax-1
PrintLine Str$("#%i\t", n), Files$(n)
Next
pop eax
Inkey Str$("\n%i files found", eax)
Exit
end start


The test also reveiled that WinXP stops at a total names length of 256 bytes, i.e. even when using single letter folder names, the theroretical maximum recursion level is apparently 256.
Title: Re: MasmBasic
Post by: dedndave on December 14, 2010, 10:11:18 PM
Jochen,
i know, with XP, you can't go as deep with
CD c:\a\a\a\a...\a\a\a
as you can with
CD c:\a
CD a
CD a
CD a
...
CD a
CD a
CD a

the point being, it matters if it is root-relative or current-relative
Title: Re: MasmBasic
Post by: jj2007 on December 14, 2010, 10:34:19 PM
Unzip the archive to C:\, then go to the last level and try an mkdir dedndave...

Re Client/Server example: If you want some fun, try (in \masm32\RichMasm\Res\Server.asc):
case IdEdit
  push esi
  Let esi=Win$(hEdit)+CrLf$+FileRead$("\Masm32\include\Windows.inc")+FileRead$("\Masm32\include\WinExtra.inc")
  SendData "MyClient", esi, hWnd
  Clr$ esi
  pop esi


Type something while MyClient is active... it feels like Microsoft Word :green
Title: Re: MasmBasic
Post by: Antariy on December 15, 2010, 01:09:01 AM
Quote from: jj2007 on December 14, 2010, 10:00:36 PM
Alex (Antariy) asked me if GetFiles checks for maximum recursion depth. Actually, it doesn't, and tests seem to prove that it doesn't matter. There is an old thread discussing this:

Quote from: zooba on June 24, 2007, 01:02:16 PM
The stack reserves the size specified by the linker but it doesn't commit it until you try and access it. It detects attempted accesses using a guard page, so the first time you attempt to access a page that hasn't been committed, Windows will catch an exception and commit it. However, it only guards one page, which is the next uncommitted page. Attempting to access the page beyond the guard page will cause an access violation exception.

The critical sentence here is "Attempting to access the page beyond the guard page will cause an access violation exception".

My point was not trying to access beyond guard page, untill you did'n allocate more than 4 KB this would not occur. With using of your macro for clearing local variables, this will not occur even with over 4 KB buffers.
My point is: you just can reach end of all space allocated for stack, if recursive function take too many data as local variables. At least, WFD structure have size over 300 bytes, and for each level of recursion this will increase linearly. If proc have other fat local data, then you just *can* reach end of the stack, with funny exception (and probably without any Windows "Error reporting" message) :lol
Title: Re: MasmBasic
Post by: dedndave on December 15, 2010, 01:32:06 AM
the stack has a lot of room to work in win 32   :bg
Title: Re: MasmBasic
Post by: Antariy on December 15, 2010, 02:20:19 AM
Quote from: dedndave on December 15, 2010, 01:32:06 AM
the stack has a lot of room to work in win 32   :bg

Dave, this discussion is not interesting. I dislike to to rend the air with such conversations.
BUT, for example, imagine that your recursive function have 600 (only 600!!!) bytes of local variables. And >300 from them - the WFD structure only.
So, for 128 levels (for example) of recursion, you will grab 128*600=75 KB of the stack space. At point of 1 meg default linking stack space, this is not so small. You shouldn't decise that "almost all stack is mine". In some relatively deep call you will get a stack overflow, and exit without any "error message", since SEH cannot work in this case.
Of course, you "will get a stack overflow" only for 50/50, dependedly from case and application. But this lottery should not pleasing you.

:P

P.S. TotalCommander in near back have funny stack overflows by many cases, if you don't trust me :P
Title: Re: MasmBasic
Post by: dedndave on December 15, 2010, 04:16:02 AM
75 Kb is nothing - lol
you can do a lot of recursions with that much stack space
and....
i think windows will cache out some memory to disk to make space available for more stack, if needed

now, i understand that it may be limited for a driver - but we aren't talking about drivers   :P
Title: Re: MasmBasic
Post by: jj2007 on December 15, 2010, 08:10:16 AM
Quote from: dedndave on December 15, 2010, 04:16:02 AM
75 Kb is nothing - lol
you can do a lot of recursions with that much stack space

I agree. In the extreme case of 48 levels, GetFiles uses 28K. At the theoretical maximum of 256 levels, you need about 140,000 bytes, but a little test shows that you have 1,036,228 bytes of stack available:

include \masm32\include\masm32rt.inc
.code
start:
xor ecx, ecx
.Repeat
push eax
add ecx, 4
.Until 0
exit
end start


You need Olly to test it, as it will crash silently.
Title: Re: MasmBasic
Post by: dedndave on December 15, 2010, 11:21:53 AM
still - i liked Alex's statement the best - lol
QuoteDave, this discussion is not interesting.
:P
Title: Re: MasmBasic
Post by: Antariy on December 15, 2010, 02:24:50 PM
Quote from: dedndave on December 15, 2010, 04:16:02 AM
75 Kb is nothing - lol
you can do a lot of recursions with that much stack space
and....
i think windows will cache out some memory to disk to make space available for more stack, if needed

now, i understand that it may be limited for a driver - but we aren't talking about drivers   :P

Still, Dave... You are not under DOS, and should not decide that you can do almost anything with 512 bytes of stack.

Your program runs under system, and you never can know in which level your code would be called.
So, you should always (always!) decide that your resources are limited.

If some of yours procs was called in some deep code (for example some callback), then you can reach the end even with small local data :P

Decide that your resources as limited as maximally possible :P
Title: Re: MasmBasic
Post by: Antariy on December 15, 2010, 02:27:55 PM
I agree. In the extreme case of 48 levels, GetFiles uses 28K. At the theoretical maximum of 256 levels, you need about 140,000 bytes, but a little test shows that you have 1,036,228 bytes of stack available:

Jochen, this is just one case. I make "speech" in general, I'm not R.E. your latest library yet.

You need Olly to test it, as it will crash silently.

Yes:

Quote from: Antariy on December 15, 2010, 02:20:19 AM
In some relatively deep call you will get a stack overflow, and exit without any "error message", since SEH cannot work in this case.

"Bye-Bye" Windows message is default SEH for the thread.
Title: Re: MasmBasic
Post by: jj2007 on December 15, 2010, 04:18:41 PM
So I hope we can agree that MasmBasic GetFiles cannot cause a stack overflow unless a mentally sick person uses up 94% of the stack space with some odd recursion algo and then, from that low stack level, calls GetFiles on a folder that has the theoretical maximum of 125 levels of subfolders (yes it is 125, not 256, because 125*x\=250, and more Windows won't tolerate (http://www.google.it/url?sa=t&source=web&cd=37&ved=0CMgCEBYwJA&url=http%3A%2F%2Fwww.annoyances.org%2Fexec%2Fforum%2Fwinxp%2Ft1140521018&rct=j&q=folders%20windows%20maximum&ei=-ecITfv_JdP54gbp56CfAQ&usg=AFQjCNGDyG7d8ZcD1hVN_RDqZe7yo9pJ8A&cad=rjt)).
Title: Re: MasmBasic
Post by: Antariy on December 16, 2010, 01:16:33 AM
Quote from: jj2007 on December 15, 2010, 04:18:41 PM
So I hope we can agree that MasmBasic GetFiles cannot cause a stack overflow unless a mentally sick person uses up 94% of the stack space with some odd recursion algo and then, from that low stack level, calls GetFiles on a folder that has the theoretical maximum of 125 levels of subfolders (yes it is 125, not 256, because 125*x\=250, and

Yes, with MB it is almost OK. But you should not search for "mentally sick person". Again, *how you can decide, which is stack "loading" when your code was called in Window/DialogProc, for example?*. Maybe, it is already 94% "full" - you cannot prove inverse... and straight, too :green2
Title: Re: MasmBasic
Post by: jj2007 on December 16, 2010, 01:30:37 AM
Hi Alex,
If you can show me at least one real (i.e. not purely hypothetical) application that uses >900k of stack, we should continue the discussion. For info: RichMasm, source code 13,000 lines, uses at most 696 bytes (yes, bytes, not kBytes) of stack.
If that real application then sees an urgent need to search, from that dangerously low stack level, all available files, using in the worst possible scenario another 70k, then I will declare you a guru. Otherwise I might add you to a long list of persons who look desperately for problems where problems do not exist.
Take care,
Jochen
Title: Re: MasmBasic
Post by: jj2007 on December 16, 2010, 01:46:31 AM
Quote from: Antariy on December 16, 2010, 01:40:26 AM
I have give you one "real application" - TotalCommander as example.

You are confusing things. Yes TC has had stack overflow problems, but it's a bug (http://www.pubbs.net/201004/wine/19999-bug-22333-new-total-commander-application-freezes-when-the-current-directory-field-is-editable-and-you-right-click-a-regul.html), not behaviour "by design". Give me an app that is designed to use up its stack to the last drop...
Title: Re: MasmBasic
Post by: dedndave on December 16, 2010, 01:47:51 AM
QuoteYou can put me in any list you want

careful, Alex - that could bite ya   :bdg

i would say any program that met those conditions was poorly designed, to begin with
i would say MasmBasic is pretty safe, in this regard

as for the topic - you may want to split it to another thread
we are making a mess out of Jochen's MasmBasic stuff
Title: Re: MasmBasic
Post by: Antariy on December 16, 2010, 01:49:21 AM
Quote from: jj2007 on December 16, 2010, 01:46:31 AM
Quote from: Antariy on December 16, 2010, 01:40:26 AM
I have give you one "real application" - TotalCommander as example.

You are confusing things. Yes TC has had stack overflow problems, but it's a bug (http://www.pubbs.net/201004/wine/19999-bug-22333-new-total-commander-application-freezes-when-the-current-directory-field-is-editable-and-you-right-click-a-regul.html), not behaviour "by design". Give me an app that is designed to use up its stack to the last drop...


P.S. One application more.

In XP (and almost in 2000) has existing ShimEngine, or Application Compatibility mode, as you know.
And one from switches on the compatibility layers is "StackSwap". Its description:

Quote
Many APIs use much more stack space on NT than Win9x. This compatibility fix is command line driven and takes a list of APIs that will be hooked, making them use no stack. The format the command line is "MODULENAME!APINAME[:X]; MODULENAME!APINAME[:X] ..." where X is 0 : fill old stack with zeroes 1 : fill old stack with pointers 2 : fill old stack with pointers to pointers by default, no stack filling occurs.

And it's by default is applied to, for example MSVC 6.0 IDE - very real application... or not?
By the way, when you run many applications, they can already beed covered by ShimEngine. You should find Application Compatibility Toolkit to see which applications was covered by it.


P.P.S. TotalCommander have *design* problem. It was not limit the deep of the recursion, for example, in search and in regular expressions. Now it doing limitation, and because this it works.
Title: Re: MasmBasic
Post by: jj2007 on December 16, 2010, 02:00:02 AM
Quote from: Antariy on December 16, 2010, 01:49:21 AM
In XP (and almost in 2000) has existing ShimEngine, or Application Compatibility mode

Try this Google search for ShimEngine "stack overflow" (http://www.google.it/search?num=50&hl=en&newwindow=1&client=firefox-a&hs=lTO&rls=org.mozilla%3Aen-GB%3Aofficial&q=ShimEngine+%22stack+overflow%22&aq=f&aqi=&aql=&oq=&gs_rfai=). An impressing 4 hits, none of them related to the problem.

QuoteP.P.S. TotalCommander have *design* problem. It was not limit the deep of the recursion, for example, in search and in regular expressions. Now it doing limitation, and because this it works.

Apps that perform a recursion that can end up using 1,000,000 bytes of stack are indeed poorly designed, and may be a security risk (http://securitytracker.com/alerts/2006/Dec/1017458.html). GetFiles uses at most 7% of that.

But if it makes you happy, I will add to the GetFiles guide the remark "Do not use if you are currently using more than 90% of your stack". By the way, when you arrive at that low level, you should also refrain from using any Windows API, as you have demonstrated yourself above.

@Dave: Thanks, good idea to split the thread. This debate is extremely hypothetical...
Title: Re: MasmBasic
Post by: Antariy on December 16, 2010, 02:06:30 AM
Quote from: jj2007 on December 16, 2010, 02:00:02 AM
Try this Google search for ShimEngine "stack overflow" (http://www.google.it/search?num=50&hl=en&newwindow=1&client=firefox-a&hs=lTO&rls=org.mozilla%3Aen-GB%3Aofficial&q=ShimEngine+%22stack+overflow%22&aq=f&aqi=&aql=&oq=&gs_rfai=). An impressing 4 hits, none of them related to the problem.

Because the authors of the programs is not brave enough to confirm such design overlook (since it is one from the baddest).
To confirm that something is design overlook, but not bug, needed brave. For example, yesterday I've sented one bloated fast code to you for looking and testing. And it is contain one design overlook - it is not check the tail of string. I've fixed it already.
But, to be honest, two other's algos is overlooked, too. Just replace nulls before gltestA to crlfs, like this:  :wink


align 16
db crlf, crlf, crlf, crlf, crlf
gltestA db "A test", 10, "string", 10, crlf, 10, 10


Title: Re: MasmBasic
Post by: Antariy on December 16, 2010, 02:10:42 AM
Quote from: jj2007 on December 16, 2010, 02:00:02 AM
By the way, when you arrive at that low level, you should also refrain from using any Windows API, as you have demonstrated yourself above.

No, at the last page of the stack you can still do almost anything (except GUI stuff) what you want - just use NativeAPI. NativeAPI in general do only fast checking for parameters, and calls to the kernel. Kernel's stack is different from user-mode stack. So, you can do anything heavy data processing at last page of the stack with NativeAPI, to say that.

Quote from: jj2007 on December 16, 2010, 02:00:02 AM
But if it makes you happy, I will add to the GetFiles guide the remark "Do not use if you are currently using more than 90% of your stack".

Again, read some my previous post carefully. With MB recursive search almost all is OK. You only use ~620 bytes, in maximal 128 levels.

Just:
1.) I speak in general.

2.) Reread line 1.) :P
Title: Re: MasmBasic
Post by: MusicalMike on December 23, 2010, 07:54:06 PM
I have to say, putting a BASIC syntax layer ontop of Assembly language is a really cool idea. I don't do much windows assembly language programming these days as I use Macs and linux boxes now days. It would be really cool if this macro system could be ported to nasm, or fasm. (gas is probably a lost cause for this)
Title: Re: MasmBasic
Post by: jcfuller on December 23, 2010, 08:08:14 PM
Quote from: MusicalMike on December 23, 2010, 07:54:06 PM
It would be really cool if this macro system could be ported to nasm, or fasm. (gas is probably a lost cause for this)

Or JWASM (Linux)

James
Title: Re: MasmBasic
Post by: jj2007 on December 23, 2010, 08:29:45 PM
Thanks, folks. MB code assembles fine with JWasm, although there is a minor problem with macros expanding inside quoted strings (http://sourceforge.net/tracker/?func=detail&aid=3142937&group_id=255677&atid=1126895).

The bigger problem with Linux is that MB uses quite a number of Windows APIs. I have zero experience with Linux, so I can only guess that Wine might be a solution... otherwise, one would have to go through the 100+ routines and check how to replace them with native Linux equivalents. If you are curious, see attached list of used Windows API calls.
Title: Re: MasmBasic
Post by: frktons on December 23, 2010, 08:36:28 PM
Hi Jochen, I'd like to ask you a beginner question.
I tried to assemble and run your TestMasmbasic example for testing JWASM, but I used MASM32 package
and I get the following error during the execution.
What did I miss?

(http://www.masm32.com/board/index.php?action=dlattach;topic=12460.0;id=8691)
Title: Re: MasmBasic
Post by: jj2007 on December 23, 2010, 09:51:54 PM
Hi Frank,
The error is mine, and it's a simple one:

   test eax, FilesDiffer("Windows.inc", "\masm32\include\windows.inc", 1)   ; 1=case-insensitive
   .if Zero?
      Print "Files are equal, case-insensitive", CrLf$
   .else
      mov MyPos, edx   ; edx trashed by first Str$
      Print Str$("Files differ by %i", eax), Str$(" at pos %i, case-sensitive\n", MyPos)
   .endif

In my installation, I have a copy of windows.inc in the same folder as TestMasmBasic.asc, so it finds a file to compare with the second file. Copy \masm32\include\windows.inc to the current folder, and it will work (hopefully). Sorry for that.
Title: Re: MasmBasic
Post by: frktons on December 23, 2010, 10:00:43 PM
OK Jochen. Moving the include file to the current folder solved the problem.
I guess you're going to fix it in the next release anyway, don't you?  :bg
Title: Re: MasmBasic
Post by: jj2007 on December 23, 2010, 10:19:44 PM
Quote from: frktons on December 23, 2010, 10:00:43 PM
OK Jochen. Moving the include file to the current folder solved the problem.
I guess you're going to fix it in the next release anyway, don't you?  :bg

I might introduce something like this:
   Let esi=FileRead$("\masm32\include\windows.inc")
   Let Mid$(esi, Instr_(esi, "echo WARNING"))="echo Warning"
   FileWrite "MyCopyOfWindows.inc", esi
   test eax, FilesDiffer("MyCopyOfWindows.inc", "\masm32\include\windows.inc", 1)   ; 1=case-insensitive
:bg
So it would not contradict the two lines before the FilesDiffer:
   ; compare a local copy of windows.inc against the original; only difference,
   ; at the very end: "echo Warning" instead of "echo WARNING"
Title: Re: MasmBasic
Post by: frktons on December 23, 2010, 11:15:35 PM
Quote from: jj2007 on December 23, 2010, 10:19:44 PM
Quote from: frktons on December 23, 2010, 10:00:43 PM
OK Jochen. Moving the include file to the current folder solved the problem.
I guess you're going to fix it in the next release anyway, don't you?  :bg

I might introduce something like this:
   Let esi=FileRead$("\masm32\include\windows.inc")
   Let Mid$(esi, Instr_(esi, "echo WARNING"))="echo Warning"
   FileWrite "MyCopyOfWindows.inc", esi
   test eax, FilesDiffer("MyCopyOfWindows.inc", "\masm32\include\windows.inc", 1)   ; 1=case-insensitive
:bg
So it would not contradict the two lines before the FilesDiffer:
   ; compare a local copy of windows.inc against the original; only difference,
   ; at the very end: "echo Warning" instead of "echo WARNING"


Well, a better idea could be to copy the windows.inc to all the folders on the disk, just
to be sure none of them misses it  :lol
Title: Re: MasmBasic
Post by: jj2007 on December 26, 2010, 01:58:28 AM
Update 26.12. (attached on top of thread):
- bug in RichMasm editor fixed (http://www.masm32.com/board/index.php?topic=15735.0)
- bug in FilesDiffer fixed (falsely returned "files are equal" if they were equal but of different length)
- fixed: Timer, Time$, Date$ used to expand multiple times; while this had no impact on the output, it generated unnecessary extra code.
- there is a remaining problem with JWasm: Print "This is Files$(0): ", Files$(0) expands the macro within the quoted text.
  Workaround: use offset txThisIsFiles or similar in .data section (or wait for a new version of JWasm).

New function: Let My$=Input$ reads a line from the console and assigns it to a string variable.
QuoteInput$
   Let esi="["+Input$("Type something and hit Enter: ")+"]"
   Print "You typed ", esi
   Print "You typed [", Input$("Type something and hit Enter: "), "]"
   Let My$=Input$()
   PrintLine "You typed: ", My$

Use with mov is possible:
   mov My$, Input$()
   Print My$
... but be aware that you get a pointer to a circular buffer that will eventually be overwritten after a bunch of other functions have used it. If you need the text permanently, use Let (which will give you a string on the heap).
Title: Re: MasmBasic
Post by: jj2007 on December 27, 2010, 12:40:47 AM
Update 27.12. introduces a minor feature with Store (marked in red):

QuoteStore
   Store "MyWin1.inc", MyRec$()      ; store the whole array excluding trailing empty strings
   Store "MyWin1.inc", MyRec$(), 1000   ; store the first 1000 strings of the array

   Open "O", #1, MyFileName$
   Store #1, MyRec$(), 20      ; store the first 20 strings
   Store #1, MyOtherRec$()      ; add the complete array not including trailing empty strings
   Close #1
Rem[/color]   - will trigger runtime error if file cannot be opened
   - if a file name is being used, the file will be closed after writing the strings
   - for #n, the file remains open for writing, allowing e.g. to write several arrays to the same file
[/b]

The following app demonstrates its usage:
Quoteinclude \masm32\MasmBasic\MasmBasic.inc
   Init
   push Timer
[/size]   Recall "\Masm32\include\Windows.inc", L$()
   deb 4, "Windows.inc", edx
   Recall "\Masm32\include\WinExtra.inc", E$()
   deb 4, "WinExtra.inc", edx
   Open "O", #1, "WinAll.inc"
   Store #1, L$()   ; write complete arrays to disk,
   Store #1, E$()   ; not including trailing empty lines
   Close
   deb 4, "WinAll.inc  ", Lof("WinAll.inc")   ; deb 4 writes debug info to console
   void Timer
   pop edx
   Inkey Str$("\nThat was fast: %i ms", eax-edx)
   
Exit
end start

Output:
Windows.inc     edx             849788
WinExtra.inc    edx             807877
WinAll.inc      eax             1657665

That was fast: 32 ms
Title: Re: MasmBasic
Post by: jj2007 on January 02, 2011, 11:46:58 PM
Update 3 January fixes the problem with printing DWORD...BYTE array elements, plus a minor bug with MovVal (could fail if the FPU was already full).

include \masm32\MasmBasic\MasmBasic.inc
Init
Dim MyDWords(9) As DWORD
Dim MyWords(9) As WORD
Dim MyBytes(9) As BYTE
For_ n=0 To 9
m2m MyDWords(n), n ; mem to mem
m2m MyWords(n), n ; mem to mem for words...
m2m MyBytes(n), n ; ... and bytes
shl MyDWords(n), 1 ; shift left, i.e. *2
shl MyWords(n), 1
shl MyBytes(n), 1
Next
For_ n=0 To 9
Print Str$("dw=%i\t", MyDWords(n)), Str$("w=%i\t", MyWords(n)), Str$("b=%i\n", MyBytes(n))
Next
Inkey "OK"
Exit
end start

Output:
dw=0    w=0     b=0
dw=2    w=2     b=2
dw=4    w=4     b=4
dw=6    w=6     b=6
dw=8    w=8     b=8
dw=10   w=10    b=10
dw=12   w=12    b=12
dw=14   w=14    b=14
dw=16   w=16    b=16
dw=18   w=18    b=18

New archive on top of thread.
Title: Re: MasmBasic
Post by: Farabi on January 06, 2011, 08:44:58 AM
Pretty cool jochen.  :U Awesome
Title: Re: MasmBasic
Post by: jj2007 on January 16, 2011, 03:34:56 AM
What's new in version 16 January 2011 attached on top of this thread?

1. ToolTips:
WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
SWITCH uMsg
CASE WM_CREATE
... (create controls)
ToolTips TTS_BALLOON
ToolTips hButton1, "Press this button"
ToolTips hButton2, wRes$(103) ; Unicode from resource file, e.g. russian or chinese
ToolTips hEdit, wRes$(104) ; "type some text"
ToolTips end


2. New Loc function, see Seek, Loc and Lof thread (http://www.masm32.com/board/index.php?topic=15879.0)
3. The Dim command works now fine for structures and "type" arrays, e.g. Dim MyWords(99) As WORD
4. Store and Recall work now for structure and "type" arrays.

Quoteinclude \masm32\MasmBasic\MasmBasic.inc

FLOATSTRUC STRUCT   ; a colourful mix of formats
f4       REAL4 ?
f8       REAL8 ?
f10      REAL10 ?
fsrect   RECT <?>
filler   WORD ?   ; 40 bytes
FLOATSTRUC ENDS


   
Init[/color]
   Dim MyFS(99) As FLOATSTRUC   ; 100 strucs à 40 bytes = 4000 bytes
   Dim L$(99)    ; same # of strings
   For_ n=0 To 99
      Let L$(n)=Str$("String %i",n)   ; set the strings
      Let esi=Str$(n+4000)   ; create the strings "4000", "4001"
      MovVal MyFS(n, f4), esi   ; load the REAL4 member of the structure
      Let esi=Str$(n+8000)   ; create the strings "8000", "8001"
      MovVal f:xmm0, esi   ; load xmm0 as a float and...
      movlps MyFS(n, f8), xmm0   ; ...just for fun, shove it into the REAL8 member
      ffree st(7)   ; don't forget the FPU
      fldpi
      fimul n
      fstp MyFS(n, f10)   ; PI*n
      mov eax, n
      mov MyFS(n, fsrect.left), eax
      add eax, 100
      mov MyFS(n, fsrect.top), eax
      add eax, 100
      mov MyFS(n, fsrect.right), eax
      add eax, 100
      mov MyFS(n, fsrect.bottom), eax
      add eax, 100
      mov MyFS(n, filler), ax   ; filler is word sized
   Next
   Open "O", #7, "StrucStore.dat"   ; open a file for output
   Store #7, MyFS()   ; write all array elements
   Store #7, L$()   ; append the strings, too
   Close #7
; variants:
;   Store #7, MyFS(20)   ; write element 20 only
;   Store #7, MyFS(21), 9   ; write element 21-29

   Dim MyReadFS(99) As FLOATSTRUC   ; 100 strucs * 40 bytes = 4000 bytes
   Open "I", #1, "StrucStore.dat"
   Recall #1, MyReadFS()
   Print Str$("The file pointer is now at byte %i\n", eax)
   Recall #1, MyRead$()
   Close
   For_ n=0 To MyReadFS(?)-1
         .if n<5 || n>99-5
            Print Str$("\n%i\t", n)      ; \n is C style CrLf
            Print Str$("%i\t", MyReadFS(n, f4))
            Print Str$("%i\t", MyReadFS(n, f8))
            Print Str$("%5f\t", MyReadFS(n, f10))
            Print Str$("%i\t", MyReadFS(n, fsrect.left))
            Print Str$("%i\t", MyReadFS(n, fsrect.right))
            Print Str$("%i\t", MyReadFS(n, filler))
         .elseif n==50
            Print CrLf$, "..."
         .endif
   Next
   PrintLine CrLf$
   For_ n=0 To MyRead$(?)-1   ; struct(?) yields # of elements
         .if n<5 || n>99-5
            PrintLine Str$(n), Tb$, "[", MyRead$(n), "]"
         .elseif n==50
            PrintLine "..."
         .endif
   Next
      Inkey "-- ok --"
   
Exit
end start

Output:
The file pointer is now at byte 4000

0       4000    8000    0.0     0       200     400
1       4001    8001    3.1416  1       201     401
2       4002    8002    6.2832  2       202     402
3       4003    8003    9.4248  3       203     403
4       4004    8004    12.566  4       204     404
...
95      4095    8095    298.45  95      295     495
96      4096    8096    301.59  96      296     496
97      4097    8097    304.73  97      297     497
98      4098    8098    307.88  98      298     498
99      4099    8099    311.02  99      299     499

0       [String 0]
1       [String 1]
2       [String 2]
3       [String 3]
4       [String 4]
...
95      [String 95]
96      [String 96]
97      [String 97]
98      [String 98]
99      [String 99]


The example creates an array of structures and an associated array of strings, fills both arrays and writes them sequentially to a file.
Then, a new structure with the same # of elements is being created, and Recall fills it from file; while the file is still open, Recall loads also the strings.
The Recall for the structures requires that the array exists and matches the amount of bytes stored before.
The Recall for the strings creates the new string array automatically, and the # of elements depends on the disk file.
See also MbGuide.rtf for further detail.

The disassembly will show that filling the structure is not very efficient, because the offset into memory is loaded every time. This can be shortened by the equivalent to ASSUME:

MyFS(ebx:n) ;   element n now relative to ebx

Quote      MyFS(ebx:n)
      movlps MyFS(f8), xmm0   ; ...just for fun, shove it into the REAL8 member
      ffree st(7)   ; don't forget the FPU
      fldpi
      fimul n
      fstp MyFS(f10)   ; PI*n
      mov eax, n
      mov MyFS(fsrect.left), eax

The full example is attached.
Title: MasmBasic under the hood: new repeated strings macro
Post by: jj2007 on January 16, 2011, 05:58:14 PM
The typical implementation of chr$("abc") tends to create some superfluous data that may bloat the executable; superfluous because in "proper" assembler we would rather create once the MyAbc db "abc", 0 and reuse offset MyAbc as often as we need this.
Readability is better if we can see the "abc", though, therefore MasmBasic now reuses already created strings automatically. In practice, this will occasionally save a few bytes, unless you have a highly repetitive database or whatever code.

Quoteinclude \masm32\MasmBasic\MasmBasic.inc
  ; ramax = 0      ; uncomment, i.e. set to zero to test the repeated strings feature
  Init
  Dim rc(3) As RECT
  .if Exist("StoredRect.dat")
   Open "I", #1, "StoredRect.dat"
   Recall #1, rc()   ; get array values from file
   PrintLine "Data loaded from file"
  .else
   xor ebx, ebx
   .Repeat
      rc(esi:ebx)   ; assign esi to element ebx
      lea eax, [100+ebx*8]   ; load test values into the array
      mov rc(left), eax
      mov rc(top), eax
      add eax, 120
      mov rc(right), eax
      mov rc(bottom), eax
      inc ebx
   .Until ebx>3
   Open "O", #1, "StoredRect.dat"
   Store #1, rc()
   Close #1
   PrintLine "Data saved to file"
  .endif
  xor ebx, ebx
  .Repeat
   rc(esi:ebx)   ; assign esi to element ebx
   Print Str$("\nElement %i.", ebx), Str$("left=  \t%i", rc(left))
   Print Str$("\nElement %i.", ebx), Str$("top=   \t%i", rc(top))
   Print Str$("\nElement %i.", ebx), Str$("right=\t%i", rc(right))
   Print Str$("\nElement %i.", ebx), Str$("bottom=\t%i", rc(bottom)), CrLf$
   inc ebx
  .Until ebx>3
  Inkey Str$("\n%i strings created, ", ract), Str$("%i repeated strings found", found)
  Exit
end start

Output:
...
Element 3.left=         124
Element 3.top=          124
Element 3.right=        244
Element 3.bottom=       244

10 strings created, 5 repeated strings found
Title: Re: MasmBasic
Post by: dedndave on January 16, 2011, 06:09:57 PM
if you modify the string ?
maybe give them a way to create a unique string, if desired ?
Title: Re: MasmBasic
Post by: jj2007 on January 16, 2011, 06:20:30 PM
Quote from: dedndave on January 16, 2011, 06:09:57 PM
if you modify the string ?
Then it's no longer the same string, and you'll create a new one. The macro is case sensitive.

Quote
maybe give them a way to create a unique string, if desired ?
Honestly, I don't see a need to have the same static string twice in memory, but you can either use Masm32 chr$(), or use a .data entry:
Quote  .if Exist(chr$("StoredRect.dat"))
   .data
   MyUniqueFile   db "StoredRect.dat", 0
   .code
   Open "I", #1, offset MyUniqueFile
   Recall #1, rc()   ; get array values from file

Both do, imho, not add any advantage over the simple
Quote  .if Exist("StoredRect.dat")
   Open "I", #1, "StoredRect.dat"
   Recall #1, rc()   ; get array values from file

Even more efficient:
Quote  Dim rc(3) As RECT
  mov esi, Chr$("StoredRect.dat")
  .if Exist(esi)
   Open "I", #1, esi
   Recall #1, rc()   ; get array values from file
Title: Re: MasmBasic
Post by: dedndave on January 16, 2011, 06:42:17 PM
that takes care of it - they can use chr$   :P

i was thinking of a case where they may assign the same string twice
then, modify one version of it for one purpose and use the unmodified version somewhere else
Title: Re: MasmBasic
Post by: jj2007 on January 18, 2011, 11:32:24 PM
... and one more update: The ArrayFill command was missing.

Quoteinclude \masm32\MasmBasic\MasmBasic.inc   ; Press F6 to assemble & link
FLOATSTRUC STRUCT
f4       REAL4 ?
f8       REAL8 ?
f10      REAL10 ?
fsrect   RECT <?>
filler   WORD ?

FLOATSTRUC ENDS
.data
   TheQ   QWORD 123456789012345678
   fls   FLOATSTRUC <12.34, 12345.6789, 123456789.123456789, <12, 34, 56, 78>, 123>
.data?
   TheQ2   QWORD ?   ; create non-
   fls2   FLOATSTRUC <?>   ; initialised copies
   
Init [/color]
   Open "O", #7, "Stored.dat"   ; open for output
   Dim MyWordArray(5) As WORD   ; create an array of words in heap memory, with 5 elements
   ArrayFill MyWordArray(), 12345   ; fill the array
   Store #7, TheQ   ; store the QWORD
   Store #7, fls   ; store the structure
   Store #7, MyWordArray()   ; and the 6 elements of the array
   Dim My$(3)
   ArrayFill My$(), "Wow, strings created on "+Date$+", "+Time$
   Store #7, My$()   ; write also the complete string array
   Close #7   ; close the file

   Dim MyWordArray2(5) As WORD   ; create another array of words in heap memory, with 5 elements
   Open "I", #5, "Stored.dat"   ; open for input
   Recall #5, TheQ2   ; get the QWORD
   Recall #5, fls2   ; the complete structure
   Recall #5, MyWordArray2()   ; and the array
   Recall #5, MyNew$()   ; last but not least, get the strings back
   Close #5   ; close the file

   PrintLine "Recalled from file:"
   Print Str$("TheQ2=%i\n", TheQ2)
   Print Str$("fls2.f4=%f\n", fls2.f4)
   Print Str$("fls2.f8=%Gf\n", fls2.f8)
   Print Str$("fls2.f10=%If\n", fls2.f10)
   Print Str$("fls2.fsrect.left=%i\n", fls2.fsrect.left)
   Print Str$("fls2.filler=%i\n", fls2.filler)
   Print Str$("The array, #5=%i\n", MyWordArray2(5))
   For_ n=0 To My$(?)-1
      PrintLine Str$("n%i\t", n), MyNew$(n)
   Next
   Inkey "Simple, isn't it?"
   
Exit
end start
OPT_Tmp2Asm   1

Output:
Recalled from file:
TheQ2=123456789012345678
fls2.f4=12.34000
fls2.f8=12345.67890000000
fls2.f10=123456789.123456789
fls2.fsrect.left=12
fls2.filler=123
The array, #5=12345
n0      Wow, strings created on 19.01.2011, 00:33:37
n1      Wow, strings created on 19.01.2011, 00:33:37
n2      Wow, strings created on 19.01.2011, 00:33:37
n3      Wow, strings created on 19.01.2011, 00:33:37
Simple, isn't it?


Store and Recall can now handle global or local variables and structures, too.
Title: Simple multilingual window
Post by: jj2007 on January 21, 2011, 12:38:08 AM
Update of 20 January contains inter alia a modified ToolTips macro allowing to change the text.
The attached example uses this macro to display tooltips in English, Russian, Arabic and Chinese - provided you have the language packs installed.
Title: Re: MasmBasic
Post by: hutch-- on January 22, 2011, 02:12:01 AM
JJ,

Something in the demo is using ANSI. Its probably just the label (STATIC) control that in English says "Enter Text Here". If you select any of the other languages it shows ??????. I keep the east asian fonts loaded so that is not the problem. With the text message it shows arabic and chinese fonts with no problems in the edit control but not the static control.
Title: Re: MasmBasic
Post by: jj2007 on January 22, 2011, 02:27:44 AM
Quote from: hutch-- on January 22, 2011, 02:12:01 AM
JJ,

Something in the demo is using ANSI. Its probably just the label (STATIC) control that in English says "Enter Text Here". If you select any of the other languages it shows ??????. I keep the east asian fonts loaded so that is not the problem. With the text message it shows arabic and chinese fonts with no problems in the edit control but not the static control.

Hutch,

Interesting. My (old, previously posted) version works fine, although the static displays always English, by design. Attached a new version that displays the welcome in the static window in four languages. For assembly, the latest MB build of 21 Jan (http://www.masm32.com/board/index.php?topic=12460) is recommended.

Note the SkelWinMB_rsrc.asc is for use with the RichMasm editor. The resource section is at the end of the file, and gets exported to an rc file when you hit F6 for Build & Run. This is handy because you can directly edit your resources in the main source. WordPad and MS Word can read RTF, too, but they can't export the rc, of course.
(http://www.masm32.com/board/index.php?action=dlattach;topic=12460.0;id=8802)
(MultiLingual.zip is the image, do not open)
Title: RichMasm editor
Post by: jj2007 on January 27, 2011, 08:57:59 PM
Although RichMasm is not necessary to use the MasmBasic library, the editor is part of the MasmBasic package. I polished it a little bit, and added a help feature for MasmBasic. When hovering over a Basic keyword such as wMsgBox, an excerpt from the MB Guide will be displayed below or above with a greenish background. Example:
(http://www.masm32.com/board/index.php?action=dlattach;topic=12460.0;id=8818)

If you click fast enough into the green area, you can actually copy an example for pasting into the main edit window.
The next major MB update will include the new RichMasm and MbGuide.rtf versions, but I post them already here in case somebody wants to test it.
Title: Re: MasmBasic
Post by: Farabi on January 28, 2011, 03:06:41 PM
Thanks jochen your package is good for beginner.  :U
Title: Re: MasmBasic
Post by: jj2007 on January 29, 2011, 12:41:01 AM
Quote from: Farabi on January 28, 2011, 03:06:41 PM
Thanks jochen your package is good for beginner.  :U

Thanks for the feedback, Farabi :U

In the meantime, I have added Unicode versions for Lower$/Upper$ and Left$/Mid$/Right$. Example:

Quoteinclude \masm32\MasmBasic\MasmBasic.inc   ; download (http://www.masm32.com/board/index.php?topic=12460.0)
   Init[/b]

   ; Unicode message boxes:
   wLet esi="Hello, What Is The Purpose Of This String?"
   wMsgBox 0, wCat$(wLower$(wLeft$(esi, 5))), "hello", MB_OK
   wMsgBox 0, wCat$(wUpper$(wMid$(esi, 8, 4))), "WHAT", MB_OK
   wMsgBox 0, wCat$(wLower$(wRight$(esi, 7))), "string?", MB_OK

   ; same boxes but ANSI:
   Let esi="Hello, What Is The Purpose Of This String?"
   MsgBox 0, Cat$(Lower$(Left$(esi, 5))), "hello", MB_OK
   MsgBox 0, Cat$(Upper$(Mid$(esi, 8, 4))), "WHAT", MB_OK
   MsgBox 0, Cat$(Lower$(Right$(esi, 7))), "string?", MB_OK

   Exit
end start

The attached example contains also two 'wide' message boxes with Chinese text; it looks as if upper and lowercase exist in Chinese - can somebody confirm (or not) that the text makes sense? Thanks.

EDIT: Assembly of the attached source requires at least MB version 29 January 2011 attached to the first post of this thread.
Title: Re: MasmBasic
Post by: jj2007 on February 01, 2011, 01:50:01 AM
Unicode to console (or file) with version 1 Feb 2011:

Quoteinclude \masm32\MasmBasic\MasmBasic.inc   ; Download (http://www.masm32.com/board/index.php?topic=12460)
   Init
   wPrint wRes$(1201), wCrLf$   ; print a Unicode string from the resource stringtable, e.g. in Chinese
   wInkey wChr$("Hit any key")   ; of course, you don't need Unicode to print English ;-)
   [/size]Exit
end start

Output:
在這裡輸入文字
Hit any key


See MbGuide.rtf for details. Printing Unicode to the console is very tricky, see e.g. the WriteConsoleW thread (http://www.masm32.com/board/index.php?topic=13696.msg107459#msg107459)... make sure to test your code not only on your own machine.
Title: Re: MasmBasic
Post by: dedndave on February 01, 2011, 12:15:34 PM
you got it to work   :U
Title: Re: MasmBasic
Post by: jj2007 on February 01, 2011, 04:58:34 PM
Quote from: dedndave on February 01, 2011, 12:15:34 PM
you got it to work   :U

Well, kind of. DOS prompt and launch from RichMasm work properly, and I just checked from Start/Run and Explorer and - surprise, surprise! - it worked. The previous version didn't ::)

Unicode with controls works always, with CreateWindowExW of course.
Quote         invoke CreateWindowExW, WS_EX_CLIENTEDGE, wChr$("edit"), NULL,
            WS_CHILD or WS_VISIBLE or WS_BORDER\
            or ES_LEFT or ES_AUTOHSCROLL or ES_MULTILINE, 0, 0, 0, 0,
            hWnd, IdEdit, hInstance, NULL
         mov hEdit, eax                     ; we have created an edit window
         sm eax, WM_SETFONT, hButFnt, 1      ; you may choose the small font here
         invoke SetWindowLongW, hEdit,      ; we subclass the edit control
         GWL_WNDPROC, SubEdit
...
         wSetWin$ hEdit=wRes$(123)
Title: Re: MasmBasic
Post by: dedndave on February 13, 2011, 03:10:49 AM
Jochen,
i have been reading documentation regarding resource files - trying to learn stuff   :P
i was reading the section about the "langID" and "charsetID" parameters of the VERSIONINFO block, when your boggle came to mind
maybe proper version info would make the results more reliable   :U

http://msdn.microsoft.com/en-us/library/aa381058%28v=vs.85%29.aspx

(scroll down to about half the page)

you might also look into the resource file #pragma statement
Title: Re: MasmBasic
Post by: jj2007 on February 13, 2011, 07:25:19 AM
Thanks, Dave, will look into it, although a) it works fine now, b) charsetID 1200=Unicode has been among the values showing the odd behaviour...
Title: Re: MasmBasic
Post by: dedndave on February 13, 2011, 10:49:04 AM
i noticed there is another value for "international"
not sure how it would differ from unicode - but...
Title: Re: MasmBasic
Post by: jj2007 on February 13, 2011, 11:36:32 PM
Dave,
I use...
  BLOCK "VarFileInfo"
  BEGIN
    VALUE "Translation", 0x0404, 65001
  END

... and the Version tab in "File properties" correctly shows Chinese (Taiwan). My suspicion was that the OS loader would use this info to set the console output page. Nope, it doesn't - the page is stuck at 850, and the console output is garbage.

Except with MasmBasic: wPrint wRes$(StringID) works like a charm. The secret is hidden in MB's wPrint macro :bg
Title: Re: MasmBasic
Post by: dedndave on February 14, 2011, 02:47:44 AM
it is strange - lol
microsoft hasn't documented this thing very well   :P
Title: Re: MasmBasic
Post by: jj2007 on March 02, 2011, 09:36:54 PM
For those who use the MakeFont macro: There is a bug in line 1260 of \masm32\MasmBasic\MasmBasic.inc - pop edi instead of pop esi
It will be fixed in the next update.

push esi
push edi
mov esi, offset fontname
lea edi, [edx+LOGFONT.lfFaceName]
push SIZEOF fontname
pop ecx
rep movsb
pop edi
pop esi ; <<<<<<<<<<<<<<<
Title: Mixed programming with C and MasmBasic
Post by: jj2007 on March 07, 2011, 09:52:45 PM
Just for fun, here an example how C and MasmBasic can be mixed. Output:
25+35=          60
25*4=           100
(25+35)*10=     600
123=            123

Quoteinclude \masm32\include\masm32rt.inc   ; inspired by Vortex (Erol) 28.8.2006 (http://www.masm32.com/board/index.php?topic=5594.msg41609#msg41609)
include ImportC.inc

ImportC jjSum, 2   ; sums up x+y
ImportC jjMult, 2   ; multiplies x with y
ImportC jjXyz, 3   ; sums up x+y, then multiplies result with z
ImportC jjNoArgs, 0   ; accepts no args and returns always 123

.code
start:   mov ebx, esp      ; little check if the stack is OK after using these C functions

   print "25+35=    ", 9
   invoke jjSum, 25, 35
   print str$(eax), 13, 10

   print "25*4=    ", 9
   invoke jjMult, 25, 4
   print str$(eax), 13, 10

   print "(25+35)*10=", 9
   invoke jjXyz, 25, 35, 10
   print str$(eax), 13, 10

   print "123=    ", 9
   invoke jjNoArgs
   print str$(eax), 13, 10

   print "Stack test:", 9
   sub ebx, esp
   .if Zero?
      inkey "OK"
   .else
      inkey str$(ebx)
   .endif
   exit
end start

RichMasm options:
extra option for linker:
OPT_DebugL   jjCalc.obj
extra commandline before assembly:
OPT_BatA   "%ProgramFiles%\Microsoft Visual Studio 9.0\VC\bin\cl.exe" /c /Oty2 /Zl /Gs /GS- /FojjCalc.obj /Fa jjCalc.cpp

Here the utterly sophisticated C program:
extern "C"
int _stdcall jjMult(int x , int y)
{
  return(x*y);
}

extern "C"
int _stdcall jjSum(int x , int y)
{
  return(x+y);
}

extern "C"
int _stdcall jjXyz(int x, int y, int z)
{
  return((x+y)*z);
}

extern "C"
int _stdcall jjNoArgs()
{
  return(123);
}


The ImportC macro (attached) will become part of the next MasmBasic release.
Title: Unicode: wLet problem with JWasm
Post by: jj2007 on March 15, 2011, 01:44:28 PM
Minor change in \masm32\MasmBasic\MasmBasic.inc, line 3816:

Old:
wLet MACRO args
  MbWideLet = 1024
  % Let args   ; JWasm needs the %
ENDM

New:
wLet MACRO args
  MbWideLet = 1024
  Let args   ; JWasm needed a %
ENDM

Make sure you use JWasm version 2.05 (http://www.japheth.de/JWasm.html#jwdownload) or higher.
Title: MasmBasic CombSort
Post by: jj2007 on April 01, 2011, 04:25:26 PM
Following a discovery that Masm32 CombSortA fails with certain FPU settings (http://www.masm32.com/board/index.php?topic=16350.msg135341#msg135341), I rewrote a new algo for MasmBasic. It is slightly faster than CombSortA, slightly slower than nrQsortA, and handles both ascending and descending sort in the same routine (i.e. the code size is twice as good as it seems because the Masm32 variants need 2* their size for ascending + descending).

The algo will be added to the next release, but some timings would be welcome.


Intel(R) Celeron(R) M CPU        420  @ 1.60GHz (SSE3)
1293963 cycles for nrQsortA
1603816 cycles for CombSortA
1459890 cycles for MbCombSort

Items:  10000
198      bytes for nrQsortA
112      bytes for CombSortA
123      bytes for MbCombSort

Prescott P4 timings:
Items:  10000
2821448 cycles for nrQsortA
3350106 cycles for CombSortA
2316684 cycles for MbCombSort

2158186 cycles for nrQsortA
2476503 cycles for CombSortA
2564312 cycles for MbCombSort

2127466 cycles for nrQsortA
2650659 cycles for CombSortA
3063289 cycles for MbCombSort

Title: Re: MasmBasic
Post by: aker on April 02, 2011, 07:10:25 AM
C:\Libya>MasmBasicSort.exe
Genuine Intel(R) CPU           T2400  @ 1.83GHz (SSE3)
0 errors for nrQsortA
0 errors for ShakeSort
0 errors for CombSortA
0 errors for MbCombSort
0 errors for MbCombSort

Items: 10000
Masm32:
11      3.000000e+20
10      3000.000
9       123.4560
8       100.0010
7       99.99900
6       99.00000
5       1.000001
4       1.000000
3       0.9999990
2       3.000000e-20
1       0.0
0       -3000.000

JJ up:
11      3.000000e+20
10      3000.000
9       123.4560
8       100.0010
7       99.99900
6       99.00000
5       1.000001
4       1.000000
3       0.9999990
2       3.000000e-20
1       0.0
0       -3000.000

JJ down:
11      -3000.000
10      0.0
9       3.000000e-20
8       0.9999990
7       1.000000
6       1.000001
5       99.00000
4       99.99900
3       100.0010
2       123.4560
1       3000.000
0       3.000000e+20

More?

1339651 cycles for nrQsortA
1653383 cycles for CombSortA
1492463 cycles for MbCombSort

1347008 cycles for nrQsortA
1629444 cycles for CombSortA
1501308 cycles for MbCombSort

1341482 cycles for nrQsortA
1656582 cycles for CombSortA
1514172 cycles for MbCombSort

1318246 cycles for nrQsortA
1646944 cycles for CombSortA
1517919 cycles for MbCombSort

1347515 cycles for nrQsortA
1641691 cycles for CombSortA
1499894 cycles for MbCombSort

1335777 cycles for nrQsortA
1663117 cycles for CombSortA
1508589 cycles for MbCombSort

1318036 cycles for nrQsortA
1639635 cycles for CombSortA
1484425 cycles for MbCombSort


Items:  10000
198      bytes for nrQsortA
112      bytes for CombSortA
123      bytes for MbCombSort

--- ok ---

C:\Libya>
Title: Re: MasmBasic
Post by: six_L on April 02, 2011, 08:04:13 AM
QuoteIntel(R) Core(TM) i3 CPU         550  @ 3.20GHz (SSE4)
0 errors for nrQsortA
0 errors for ShakeSort
0 errors for CombSortA
0 errors for MbCombSort
0 errors for MbCombSort

Items: 10000
Masm32:
11   3.000000e+20
10   3000.000
9   123.4560
8   100.0010
7   99.99900
6   99.00000
5   1.000001
4   1.000000
3   0.9999990
2   3.000000e-20
1   0.0
0   -3000.000

JJ up:
11   3.000000e+20
10   3000.000
9   123.4560
8   100.0010
7   99.99900
6   99.00000
5   1.000001
4   1.000000
3   0.9999990
2   3.000000e-20
1   0.0
0   -3000.000

JJ down:
11   -3000.000
10   0.0
9   3.000000e-20
8   0.9999990
7   1.000000
6   1.000001
5   99.00000
4   99.99900
3   100.0010
2   123.4560
1   3000.000
0   3.000000e+20

More?

1235063   cycles for nrQsortA
1360410   cycles for CombSortA
1283783   cycles for MbCombSort

1226742   cycles for nrQsortA
1371924   cycles for CombSortA
1305272   cycles for MbCombSort

1236347   cycles for nrQsortA
1385884   cycles for CombSortA
1306424   cycles for MbCombSort

1228710   cycles for nrQsortA
1361012   cycles for CombSortA
1298305   cycles for MbCombSort

1253573   cycles for nrQsortA
1371595   cycles for CombSortA
1306666   cycles for MbCombSort

1270989   cycles for nrQsortA
1378449   cycles for CombSortA
1302128   cycles for MbCombSort

1228358   cycles for nrQsortA
1361976   cycles for CombSortA
1302989   cycles for MbCombSort


Items:   10000
198    bytes for nrQsortA
112    bytes for CombSortA
123    bytes for MbCombSort

--- ok ---

Title: Re: MasmBasic
Post by: jj2007 on April 06, 2011, 12:17:01 AM
Thanks a lot, Aker and six_L.

The new function called ArraySort is now implemented in the 6 April 11 release attached to the thread's top post (http://www.masm32.com/board/index.php?topic=12460).
Here are some timings comparing it to the Masm32 library functions; the latter do not handle Real4 arrays, so I added a Dword example. Here, ArraySort is 1-2% slower than CombSortA, although I saw it 6% faster in a different but more complex setting. The Masm32 quicksort is faster for high element counts, but below about 2,000 elements, the comb sorts are faster. Note "cycles per element" refers to the average of all 4 algos.

Intel(R) Celeron(R) M CPU        420  @ 1.60GHz (SSE3)
100000 array elements:
15359   kCycles for ArraySort, Real4
13244   kCycles for ArraySort, Dword
12973   kCycles for CombSortA, Dword
9093    kCycles for nrQsortA,  Dword
130 cycles per element

20000 array elements:
2191    kCycles for ArraySort, Real4
2133    kCycles for ArraySort, Dword
2062    kCycles for CombSortA, Dword
1709    kCycles for nrQsortA,  Dword
104 cycles per element

4000 array elements:
341     kCycles for ArraySort, Real4
331     kCycles for ArraySort, Dword
310     kCycles for CombSortA, Dword
313     kCycles for nrQsortA,  Dword
83 cycles per element

800 array elements:
51      kCycles for ArraySort, Real4
49      kCycles for ArraySort, Dword
46      kCycles for CombSortA, Dword
57      kCycles for nrQsortA,  Dword
66 cycles per element

160 array elements:
8       kCycles for ArraySort, Real4
7       kCycles for ArraySort, Dword
6       kCycles for CombSortA, Dword
10      kCycles for nrQsortA,  Dword
53 cycles per element

32 array elements:
1       kCycles for ArraySort, Real4
1       kCycles for ArraySort, Dword
1       kCycles for CombSortA, Dword
2       kCycles for nrQsortA,  Dword
49 cycles per element
Title: Sorting is boring
Post by: jj2007 on April 06, 2011, 12:28:35 AM
... unless your sort algo takes care of the original order, too, so that you can keep track of the records.

Here is a simple example: Results of a 100 m sprint are ordered alphabetically by the boys' names. Simply sorting the REAL4 variables in Times100 would lead to nowhere, as the association to the names would be lost. ArraySort can swap the pointers to the "sort key" Boys, too - and thus the results can be displayed nicely, as shown below.

Quoteinclude \masm32\MasmBasic\MasmBasic.inc   ; Press F6 to assemble & link
.data
Times100
   REAL4 12.3, 12.1, 14.3, 14.5, 15.7, 16.3, 16.3, 23.5, 22.4, 12.4
Boys   dd Boy1, Boy2, Boy3, Boy4, Boy5, Boy6, Boy7, Boy8, Boy9, Boy10
Boy1   db "Alan", 0
Boy2   db "Bob", 0
Boy3   db "Chris", 0
Boy4   db "Dave", 0
Boy5   db "Edgar", 0
Boy6   db "Frank", 0
Boy7   db "Geoffrey", 0
Boy8   db "Hutch", 0
Boy9   db "Ian", 0
Boy10   db "John", 0
   
Init
   ; sort the results of a sprint
   mov esi, offset Times100
   Elements=sizeof Times100/4
   ArraySort esi
:Elements, offset Boys      ; sort esi, and adjust the Boys array accordingly
   PrintLine "Results of the last 100 m sprint"
   PrintLine "Rank", Tb$, "Time", Tb$, Tb$, "Name"
   For_ ebx=0 To Elements-1
      PrintLine Str$(ebx+1), Tb$, Str$("%3f secs \t", MemR4(esi, ebx)), Boys[4*ebx]   ; MemR4 allows
Str$(Real4 ptr [esi+4*ebx])
   Next
   Inkey CrLf$, "-- press any key --"
   
Exit
end start

Results of the last 100 m sprint
Rank    Time            Name
1       12.1 secs       Bob
2       12.3 secs       Alan
3       12.4 secs       John
4       14.3 secs       Chris
5       14.5 secs       Dave
6       15.7 secs       Edgar
7       16.3 secs       Frank
8       16.3 secs       Geoffrey
9       22.4 secs       Ian
10      23.5 secs       Hutch *)


*) I swear I didn't plan to put him on the last rank. It must be a bug in ArraySort :bg

Excerpt from the manual:

QuoteMbArraySort
            m2m ebx, 1000               ; we want 1000+1 elements (arrays are zero-based, 0...1000=1001)
            Dim MyR4(ebx) As REAL4
            Dim MyDW(ebx) As DWORD
            Dim KeyArr(ebx) As DWORD
            .Repeat
               Rand(-888.888, 999.999)         ; fill the Real4 array with random numbers between -888 and +999
               fstp MyR4(ebx)
               mov MyDW(ebx), Rand(1000)      ; same for the dword array, numbers between 0 and 1000
               mov KeyArr(ebx), ebx         ; we may need to know the original position before sorting
               dec ebx
            .Until Sign?
            lea edi, MyDW(0)               ; get the start address of the dword array
            ; ArraySort edi                  ; illegal - arrays are not zero terminated, so we must know the count
            ArraySort edi:Elements         ; edi is pointer to a dword array; Elements is # of dwords
            lea edi, MyR4(0)               ; get the start address of the Real4 array
            ArraySort REAL4 ptr edi:Elements   ; same but with single floats array (and we must declare them)
            ArraySort MyR4()               ; sort a MasmBasic Real4 array ascending
            ArraySort MyR4(+)            ; same, the + is optional
            ArraySort MyR4(+:123)         ; same but first 123 elements only
            mov ecx, 123
            ArraySort MyR4(+:ecx)         ; same but using a register (or any other dword variable)
            ArraySort MyR4(-)               ; sort a MasmBasic Real4 array descending
            ArraySort MyR4(-:123)         ; same but first 123 elements only
            lea esi, KeyArr(0)               ; load start address of an array containing keys (e.g. original position)
            ArraySort MyR4(-), esi         ; sort Real4 array descending, keep key values with Real4 values
            ArraySort MyR4(+), KeyArr(), fill      ; use key array directly, fill with original order (0, 1, 2, ... n) before sorting

Rem   - no return value (all regs unchanged)
   - use for DWORD and REAL4 arrays; for strings, see QSort
   - uses a very fast CombSort variant, may be faster than QuickSort for low elements counts (<10,000)
   - Real4 and Dword use the same algo; the only difference is that the Real4 variant applies an extra
     pass to invert the order of negative elements. Speedwise there is no measurable difference
[/b]
Title: Re: MasmBasic
Post by: dedndave on April 06, 2011, 02:06:17 AM
i put a girls name in there, and it froze up   :red
maybe i should pick a name that doesn't start with "Z" ?
Title: Re: MasmBasic
Post by: jj2007 on April 06, 2011, 07:32:24 AM
Quote from: dedndave on April 06, 2011, 02:06:17 AM
i put a girls name in there, and it froze up   :red
maybe i should pick a name that doesn't start with "Z" ?

Give Z a kiss, and post the code that freezes, if any :naughty:
Title: Re: MasmBasic
Post by: dedndave on April 06, 2011, 11:29:46 AM
you know i was pulling your leg, my friend   :P
Title: Re: MasmBasic
Post by: jj2007 on April 22, 2011, 06:56:33 AM
See here (http://www.masm32.com/board/index.php?topic=16480.msg136683#msg136683) for a MasmBasic example with tooltips that show off when the user has CapsLock set and tries to type something in the edit control. You need to replace VK_SHIFT with VK_CAPITAL in the source.
Title: Re: MasmBasic
Post by: jj2007 on April 25, 2011, 07:44:38 PM
Following an exchange of views in the UniEdit thread (http://www.masm32.com/board/index.php?topic=16537.msg137122#msg137122), I updated RichMasm.exe (included in the MasmBasic package attached to the first post of this thread (http://www.masm32.com/board/index.php?topic=12460)). Now Unicode RC files that for whatever reason lack the byte order mark (BOM (http://en.wikipedia.org/wiki/Byte_order_mark)) are still recognised as Unicode and saved accordingly.

Note that this is a pretty superfluous feature because with RichMasm, the contents of the resource files can simply be added to the bottom of the *.asc source, under "end start":

Quote...
end start

Rsrc
STRINGTABLE
BEGIN
   401,   "Введите текст  здесь"   ; "Enter text here" in Russian
   402,   "Нажмите на эту кнопку"   ; "Click on this button" in Russian
   403,   "Добро пожаловать"   ; "Welcome" in Russian
END
Rsrc

Pressing F6 (=assemble, link and run) triggers also the export of the text between the two Rsrc markers to a Unicode *.rc file. To use this feature with "real" Unicode, you need MasmBasic's wRes$() macro, e.g. as wSetWin$ hEdit=wRes$(401).
Title: Re: MasmBasic
Post by: jj2007 on May 01, 2011, 11:51:49 PM
Minor update, see top of thread (http://www.masm32.com/board/index.php?topic=12460.0). The editor (RichMasm.exe) barks now if it was not started from its native location, i.e. \masm32\RichMasm\RichMasm.exe

Remember to extract to the root of your Masm32 drive using folder names. This adds two folders to your Masm32 installation: \masm32\MasmBasic and \masm32\RichMasm. You can move the RichMasm folder (including all its sub-folders) into the MasmBasic folder, but not the other way round (but it's not very sensible to do that since updates extract to \masm32\RichMasm).

The May 2 update also solved a problem with Input$ when used directly e.g. for MovVal. This snippet works now:
Quoteinclude \masm32\MasmBasic\MasmBasic.inc   ; Download (http://www.masm32.com/board/index.php?topic=12460)
.data?
Num1   REAL8 ?

   Init
   MovVal Num1, Input$("Type a number and hit Enter:  ")
   Inkey Str$("Your numbers is %f", Num1)
   Exit
end start
Title: Re: MasmBasic
Post by: BytePtr on May 15, 2011, 09:34:36 AM
Got this error: "Sorry, MasmBasic needs SSE2."


Too bad. Im not going to buy new PC because of MasmBasic.

Sad, i thought i could use it. But it seems, i must forget it.
Title: Re: MasmBasic
Post by: TmX on May 15, 2011, 11:54:38 AM
Quote from: BytePtr on May 15, 2011, 09:34:36 AM
Got this error: "Sorry, MasmBasic needs SSE2."


Too bad. Im not going to buy new PC because of MasmBasic.

Sad, i thought i could use it. But it seems, i must forget it.

Are you using an old CPU, prior to Pentium 4?
Title: Re: MasmBasic
Post by: jj2007 on May 15, 2011, 05:27:31 PM
Quote from: BytePtr on May 15, 2011, 09:34:36 AM
Got this error: "Sorry, MasmBasic needs SSE2."
Too bad. Im not going to buy new PC because of MasmBasic.

Sorry for that. SSE2 was introduced ten years ago...

I actually wrote MasmBasic to overcome the limitations of an old 16-bit Basic dialect that I still use frequently; so MB is not meant to support old hardware.

There are actually people who claim that 32-bit assembler is obsolete now. Given that 16-bit Windows apps still work fine on the latest Win7 64-bit professional editions, and that the added value of going from 16 to 32 bits was much, much higher than the step from 32 to 64, I am optimistic that a 32-bit SSE2 language will be useful for some decades to come :bg
Title: Re: MasmBasic
Post by: BytePtr on May 15, 2011, 08:26:38 PM
Quote from: TmX on May 15, 2011, 11:54:38 AMAre you using an old CPU, prior to Pentium 4?

AMD Duron, 1.6 GHz.

Of course i would like to have new and more powerful PC, with tons of RAM and video memory and very fast HDD.

But i don't play any high end games, (what i play only is: GTA1, GTA2, GTA3, Vice and San), that's all, and they all work perfectly on my PC), i can watch my movies with my current PC fine, i can make my all development on this PC fine.

Basically im just wasting my money with buying new PC or making new from different new pieces. Because i will never use that power.

And i didn't know that AMD Duron doesn't support SSE2, i thought it does.

jj2007, no problems, if i find some good offers or something like that, i will of course upgrade.
I can sell old parts, add some money and make new PC from pieces (best available in my town PC shops).

And i can test MasmBasic again.
Title: Re: MasmBasic
Post by: qWord on May 15, 2011, 08:33:40 PM
Quote from: BytePtr on May 15, 2011, 08:26:38 PMi can watch my movies with my current PC fine
just for interest: also HD films?
Title: Re: MasmBasic
Post by: BytePtr on May 15, 2011, 08:36:54 PM
Nope, i don't care much about that, HD or not, i will watch movie once and that's enough, if i see the action, that's all i need.
Of course preferably better quality than Youtube offers for example. Not their HD but these, 640x480, etc resolutions in fullscreen.


But about MasmBasic, when i first saw this topic, i thought: wow, finally, compiler that makes programming with assembler alot easier.
But it's actually INC file.

But that's not the problem, i looked into manual and .INC file, looks very interesting and useful.
Hopefully i can soon test it.


Keep up the good work, JJ2007.
Title: Re: MasmBasic
Post by: dedndave on May 16, 2011, 02:24:35 AM
the AMD Duron supports SSE (1)
maybe you can get some functionality - or at least, see how it works - to help you in writing your own code

on the other hand, maybe Jochen can work in some non-SSE fallbacks   :P
Title: Re: MasmBasic
Post by: jj2007 on May 23, 2011, 11:25:10 PM
Quote from: BytePtr on May 15, 2011, 08:36:54 PM
Keep up the good work, JJ2007.

Thanks :bg

Update 23 May 2011 (below top of thread (http://www.masm32.com/board/index.php?topic=12460)):

1. Interface to GNU Scientific Library (see this thread (http://www.masm32.com/board/index.php?topic=16725.msg139088#msg139088))
  Note this does NOT imply that MasmBasic gets a GNU licence. You can use the GSL as you like, but MasmBasic source code remains copyrighted and closed source - so make sure you understand the implications of using an external library with a GNU license (http://www.masm32.com/board/index.php?topic=15439.0).

2. CreateInvoke - a quick way to use invoke for dynamically linked routines:

Quoteinclude \masm32\MasmBasic\MasmBasic.inc
   
Init
[/color]
   mov ebx, rv(LoadLibrary, Chr$("urlmon"))
   mov
CreateInvoke(Web2File, 5*DWORD), rv(GetProcAddress, ebx, Chr$("URLDownloadToFileA"))
   
invoke Web2File, 0, Chr$("http://www.masm32.com/board/index.php?action=unread", 59, "all"), Chr$("NewReplies.htm"), 0, 0
   invoke FreeLibrary, ebx
   Inkey Str$("\nCongrats, the file has %i bytes. See it now?\n", Lof("NewReplies.htm"))
   .if al=="y"
      Inkey FileRead$("NewReplies.htm")
   .endif
   Exit
end start

Variants:
   mov CreateInvoke(zebox1, 4*dword), MessageBox
   invoke zebox1, 0, Chr$("Text"), Chr$("Title"), MB_OK
   mov CreateInvoke(zebox2, dword, :Dword, dWord, :DWORD), MessageBox
   invoke zebox2, 0, Chr$("Text"), Chr$("Title"), MB_OK
Title: MasmBasic bug warning
Post by: jj2007 on May 24, 2011, 02:35:49 PM
The version of 23 May had a bug in its implementation of gsl - it used STDCALL instead of C.
The good news is that fixing the bug required adding a "C" variant of CreateInvoke:

Quoteinclude \masm32\MasmBasic\MasmBasic.inc   ; Download (http://www.masm32.com/board/index.php?topic=12460)
   Init

;   whateverproc = any proc or result of GetProcAddress etc
   mov CreateInvoke(whatever1, 3*dword, REAL8), whateverproc
;   mov CreateInvoke(whatever2, vararg), whateverproc   ; Error A2094: Vararg requires C calling convention
   mov CreateInvokeC(whatever3, dword, REAL8, dword, REAL4), whateverproc
   mov CreateInvokeC(whatever4, vararg), whateverproc

;   example how to use the created invoke:
   invoke whatever3, 123, FP8(123.456), 456, FP4(456.789)
   Inkey "OK"
   
Exit

whateverproc proc  thedd1, thereal8:REAL8, thedd2, thereal4:REAL4
   PrintLine "Ciao"  ; could do something more useful, actually :wink
   ret
whateverproc endp

end start

Download is here (http://www.masm32.com/board/index.php?topic=12460) as usual.
Title: Re: MasmBasic
Post by: jj2007 on June 13, 2011, 10:25:10 PM
Update 14 June 2011 (archive (http://www.masm32.com/board/index.php?topic=12460)):

- CatchRTE:
MasmBasic can throw a variety of runtime errors, such as "file not found" etc. ; note that
after showing them, MB will call ExitProcess. This can lead to tricky situations if you use
MB in a dll. To prevent killing your main process, use MbCatchRTE as follows:
   MyAlgo proc uses esi edi ebx arg1, arg2
   LOCAL var1, var2
            MbCatchRTE SafeRet   ; any label will do
            ... code that may trigger a runtime error...
   SafeRet:   ret      ; will gracefully return, with pop ebx edi esi and retn 2*4
   MyAlgo endp


- Erase works now also for numeric arrays.
Title: Re: MasmBasic
Post by: jj2007 on June 17, 2011, 07:58:35 PM
Update 17 June:
1. minor Str$() change - this is now legal syntax:
.code
MyR8 REAL8 123.456
start: mov esi, offset MyR8
Print Str$("Wow, a Real whatever: %f\n", REAL8 PTR [esi])


2. Print #1:numbytes, ptrBuffer could misbehave for large buffers because it HeapAlloc's a buffer for the buffer. No problem for buffers under 300MB, but well, some BloatWareTM products require really fat files, so we now have a PrintBuffer macro that is much less versatile but respects the limits of the OS.
QuotePrintBuffer
[/color]   PrintBuffer #1:eax, esi   ; #file:bytes, pBuffer - corresponds to Print #1:eax, esi syntax
   PrintBuffer #1, esi, eax   ; #file, pBuffer, bytes - same code generated but different syntax
Rem   - returns # of bytes written in edx, Win API WriteFile return code in eax
   - use this macro instead of e.g. Print #1:eax, esi to avoid memory problems
Key   pb1
Title: Re: MasmBasic
Post by: jj2007 on June 29, 2011, 10:27:24 PM
30 June 2011:

- There are still some fans of console apps around, so the goodies today are Locate and Input$. More in the Windows Console Input (http://www.masm32.com/board/index.php?topic=16920.msg141271#msg141271) thread.

- Reading and writing to the registry could be a lot easier:
QuoteGetRegVal
   PrintLine GetRegVal("HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment","Path", "no path found"), CrLf$
   EnvVars equ "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment"   ; long paths: use an equate
   Print GetRegVal(EnvVars,"PROCESSOR_IDENTIFIER", "unknown"), CrLf$   ; get to know your CPU...
   print GetRegVal(EnvVars, "PROCESSOR_IDENTIFIER", "unknown"), 13, 10   ; same with Masm32 print macro
   PrintLine GetRegVal("HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment","PROCESSOR_IDENTIFIER", "unknown"), CrLf$            ; same with full path
   PrintLine GetRegVal("HKCR\.doc", 0, "documents"), " are files with ending *.doc"
   PrintLine GetRegVal("HKEY_CLASSES_ROOT\.bax", 0, "unknown"), " are files with ending *.bax"
   ; this line would fail with a run-time error because the key does not exist and there is no default value given:
   ; PrintLine GetRegVal("HKEY_CLASSES_ROOT\.bax", 0), " are files with ending *.bax"
   PrintLine GetRegVal("HKCU\Console","FaceName", "Arial"), " is your default console font"   ; works fine
   ; this line would produce garbage because GetRegVal can only be first para in Let and Print combinations:
   ; PrintLine "Your default console font is ", GetRegVal("HKCU\Console","FaceName", "Arial")
   ; workaround with Cat$ (no need for cleanup with Clr$):
   PrintLine Cat$("Your default console font is "+GetRegVal("HKCU\Console","FaceName", "Arial"))
   ; workaround with a permanent string, e.g. in esi:
   Let esi=GetRegVal("HKCU\Console","FaceName", "Arial")
   PrintLine "Your default console font is ", esi, " with FontFamily ", Hex$(GetRegVal("HKCU\Console","FontFamily"))
   Clr$ esi   ; if you don't use esi in another Let esi=..., a Clr$ esi should free the heap
Rem   - returns in eax either a pointer to a string, or a DWORD
   - if you provide a default value, GetRegVal returns it even if the key and/or the value are not present
Key   grv(

SetRegVal
   SetRegVal "HKCU\TheKey","TheValueName", "NewString")
   SetRegVal "HKEY_CURRENT_USER\Console\JJ", "NewValue", 12345      ; creates new REG_DWORD
   SetRegVal "HKCU\Console\JJ", "NewValue", 54321            ; changes existing value
   SetRegVal "HKEY_CURRENT_USER\Console\JJ", 0, "New default value"   ; 0: sets (Default) to a string
   ; do not replace an existing REG_SZ with a dword - this will produce an exception:
   ; SetRegVal "HKEY_CURRENT_USER\Console\JJ", 0, 123
   ; existing REG_DWORD receives a DWORD string pointer - this works but is meaningless and bug-prone:
   ; SetRegVal "HKEY_CURRENT_USER\Console\JJ", "NewValue", "A string"
   ; tries to create a new key, will fail with a run-time error:
   ; SetRegVal "HKEY_CURRENT_USER\Console\NoSuchKey", "NewValue", 123
Rem   - returns in eax the original new value
   - you are not allowed to create a new key, but you can create a new REG_SZ or REG_DWORD value
Key   -
[/color]

The rules are simple:
  if key found: return string or dword in eax
  if key or value not found:
   - get with default: return default dword or string
   - get, no default: trigger run-time error
   - set: always run-time error

Sample output:
C:\Programmi\ImageMagick-6.6.5-Q8;%SystemRoot%\system32;%SystemRoot%;%SystemRoot
%\System32\Wbem;D:\DB_CIRCS\WEBSITE\0_SERVER\PhpBin;D:\masm32\bin;D:\masm32\incl
ude;C:\Programmi\FreeArc\bin

x86 Family 6 Model 14 Stepping 8, GenuineIntel
x86 Family 6 Model 14 Stepping 8, GenuineIntel
x86 Family 6 Model 14 Stepping 8, GenuineIntel

Word.Document.8 are files with ending *.doc
unknown are files with ending *.bax
Lucida Console is your default console font
Your default console font is Lucida Console
Your default console font is Lucida Console with FontFamily 00000036
Title: Re: MasmBasic
Post by: jj2007 on June 30, 2011, 09:35:18 AM
Small but significant change in version 30Juneb: The user can choose if a GetRegVal/SetRegVal failure triggers a run-time-error (with ExitProcess etc - default behaviour), or just a 'failure flag' in edx. Check MbRegValRTE in \masm32\MasmBasic\MbGuide.rtf
Title: Re: MasmBasic
Post by: jj2007 on July 09, 2011, 10:47:33 PM
One more hint related to the registry: If you plan to create a new string value, the 30Juneb version will create a REG_DWORD instead (there is no problem with existing REG_SZ values). Replace line 1295 of \masm32\MasmBasic\MasmBasic.inc as follows:
Quote  tmp$ SUBSTR <rkNew>, 1, 1
  is INSTR <"'>, tmp$
  if is

Quote  tmp$ SUBSTR <rkNew>, 1, 1
  is INSTR <"'(>, tmp$
  if is

The added ( allows to use e.g. (eax) to force a string value. Most MasmBasic string macros return some variant of (eax) in brackets anyway.

Quoteinclude \masm32\MasmBasic\MasmBasic.inc
   Init
   mov eax, chr$("Masm32 is great!!")
   SetRegVal "HKCU\Console", "FancyNewValue", (eax)  ; force REG_SZ
   Inkey "ok?"
   Exit
end start
Title: Masm and DDE
Post by: jj2007 on July 14, 2011, 09:55:58 AM
Update 14 July here (http://www.masm32.com/board/index.php?topic=12460) with docu for DDE conversations with Ms Word:

Quote   SendWordCommands INIT   ; prepare a DDE session; Word must be running
   .if eax
      SendWordCommands "[FileNewDefault:InsertFile °\"D:\Masm32\include\Windows.inc°\"]"
      SendWordCommands Chr$("[InsertFile ", 34, "D:\Masm32\include\WinExtra.inc", 34, "]")
      Let esi=FileRead$("\masm32\RichMasm\OpenDocInWord.bas")
      SendWordCommands esi   ; send the contents of the BAS file
      SendWordCommands "[MsgBox °\"Cute°\"]"   ; show a box in Ms Word
   .else
      MsgBox 0, "MS Word doesn't answer", "Sorry", MB_OK
   .endif
   SendWordCommands EXIT


Rem   - swc init returns the DdeConnect retval in eax
   - DDE uses ancient WordBasic; get the help file here (http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=7035) ; to make it appear in
     RichMasm's Help menu, save it as \masm32\RichMasm\Help\WrdBasic.hlp
   - a sequence is included in [squared brackets]
   - multiple commands can be separated by a colon (:)
   - for strings, use either the escape sequence °\" (Alt 248, 92, 34) or Chr$("xx", 34, "xx") - see above
   - you can also use Let or Cat$ to send commands to MS Word
   - it is your responsibility to respect legality when using this feature
Title: Re: MasmBasic
Post by: qWord on July 14, 2011, 12:19:43 PM
hi jj,
what nice tool/script are you using for creating this highlighted code in quotes? - self made?
Title: Re: MasmBasic
Post by: jj2007 on July 14, 2011, 04:34:13 PM
Quote from: qWord on July 14, 2011, 12:19:43 PM
hi jj,
what nice tool/script are you using for creating this highlighted code in quotes? - self made?

Yes. As you might know :bg, RichMasm stands for Rich Text Format Masm editor - and it has a special key (F11) that puts the selected text onto the clipboard in the Forum's format. Not perfect, sometimes I have to correct little things by hand, but overall I believe that individual colouring improves readibility. What I can't stand is automatic Christmas tree highlighting of the mov eax, byte ptr [esi] sort...
Title: Re: MasmBasic
Post by: qWord on July 15, 2011, 03:05:15 AM
Quote from: jj2007 on July 14, 2011, 04:34:13 PMYes. As you might know :bg, RichMasm stands for Rich Text Format Masm editor - and it has a special key (F11) that puts the selected text onto the clipboard in the Forum's format.
I've seen, that key words could be add, by modifying the file Keywords.ini - unfortunately this doesn't match my requirements. (AFAIKS)
Now I've written a small program, that transform text currently  on the clipboard  (keyword highlightning, tab->space)  :P
Title: Re: MasmBasic
Post by: jj2007 on July 15, 2011, 10:01:37 AM
Quote from: qWord on July 15, 2011, 03:05:15 AM
I've seen, that key words could be add, by modifying the file Keywords.ini - unfortunately this doesn't match my requirements.

Hi qWord,
\masm32\RichMasm\Res\Keywords.ini does something else: you type e.g. ism[space] in RichMasm, and invoke Sendmessage, gets inserted. Other example: if you type .rep[space], you get...
   .Repeat
      ¨
   .Until 0
... and the red double-dot in the middle is selected, so that you can just continue typing, e.g. dec ecx or whatever. That is a just a feature which saves typing, but for me it has become incredibly important.

The "F11 forum highlighter", in contrast, takes what is currently selected in the editor and converts the colours etc:

@@:
  Open "I", #1, RecFiles$
  cmp eax, INVALID_HANDLE_VALUE
  jne @F
   Open "O", #1, RecFiles$   ; no recent files list yet, let's create one
   Print #1, offset txHelp2   ; "Res\RichMasmGuide.asc", default first file
   Close #1
   jmp @B
@@:
  Input #1, edi, Lof(#1)
;  deb 1, "New recent files list:", $edi
  Close 1

The blue text stems from using the keyboard feature: if you type opi [space], you get Open "I", #1,. Same for the grey comments: RichMasm changes the colour to grey if you press TAB, ; - but you can always change the colour afterwards, such as in recent files above.
The other colours, green for the "good" jump, red for the "bad" one, are inserted by hand. I use such colours sparingly to highlight specific code elements, often for very tricky code sequences. When I reexamine such code after some months, the colours help me to understand why I made certain stupid-looking choices ;-)

Now if you copy the same selected text and run your exe, the result is this:
@@:
  Open "I", #1, RecFiles$
  cmp eax, INVALID_HANDLE_VALUE
  jne @F
    Open "O", #1, RecFiles$ ; no recent files list yet, let's create one
    Print #1, offset txHelp2    ; "Res\RichMasmGuide.asc", default first file
    Close #1
    jmp @B
@@:
  Input #1, edi, Lof(#1)
;  deb 1, "New recent files list:", $edi
  Close 1


That is probably not what you intended...??
Title: Re: MasmBasic
Post by: qWord on July 15, 2011, 04:29:58 PM
hi,
Quote from: jj2007 on July 15, 2011, 10:01:37 AMThat is probably not what you intended...??
:bg it has diffrent sets own keywords, which are automatically colored - your example simply doesn't use the right keywords. Also it automatically convert tabs to spaces.
Quote    ldl x=3.5, a=1, b=5, _c=1

    fSlv y = a*x^2+b*x +_c
    print "a*x^2+b*x +_c = "
    print real4$(y),13,10

    mov sz[0],0
    print cat$(ADDR sz,"the logarithm of 12 to base 3 is: ",real8$( @fSlv8(x= logbx(3,12) ) )),13,10
    mov sz[0],0
    print cat$(ADDR sz,"3^",real8$(x)," = ",real8$( @fSlv8(x= 3^x))),13,10     

    .if fEQ( 1 , 2.E-7 ) || fGT( @fSlv4(x^2) , y )
        print "whatever",13,10
    .endif

    fSlv y = 1*2+3*4.0 +_c {i2,r4}
   
    .if fEQ( 1.2 , x {r8})
        ;...
    .endif

Beginning I've just thought, that all highlighting is done automatically by RichMasm. Also it can only highlight keywords (from keyword.ini) with one color?. You may add some 'remember coloring' or 'remember this keyword' function.

Quote from: jj2007 on July 15, 2011, 10:01:37 AM
Other example: if you type .rep[space], you get...
   .Repeat
      ¨
   .Until 0
... and the red double-dot in the middle is selected, so that you can just continue typing,
that's really nice

qWord
Title: Re: MasmBasic
Post by: jj2007 on July 15, 2011, 07:16:45 PM
Quote from: qWord on July 15, 2011, 04:29:58 PM
I've just thought, that all highlighting is done automatically by RichMasm.

Only a few are highlighted automatically, by typing the keyboard shortcut for the MasmBasic keywords, or by typing push xxx or tab:

   Open "O", #1, "Test.txt"   ; MasmBasic keyword
   push esi   ; push & pop
   Print #1, "Test"   ; comments
   pop esi   ; push & pop
   Close #1   ; MasmBasic keyword

All text can be formatted manually. I tend to write FPU code in blue to distinguish it a bit, but it's merely a matter of taste.
I will reflect on conversion of tabs to spaces for the Forum export. The browsers don't provide enough indent for tabs.
Title: MasmBasic bug warning
Post by: jj2007 on July 27, 2011, 08:47:06 AM
Relax - this is for JWasm (http://www.japheth.de/JWasm.html#jwdownload) users only...

As reported in bug report 3142937 of 23.12.2010 (http://sourceforge.net/tracker/?func=detail&aid=3142937&group_id=255677&atid=1126895), Jwasm has problems with macros that appear inside quoted text. This is difficult to reproduce without using MasmBasic, but below is a snippet showing the effect. Use the workaround in case you stumble over this problem.

Again: there is no problem for users of Microsoft Macro Assembler aka MASM.


Quoteinclude \masm32\MasmBasic\MasmBasic.inc   ; download (http://www.masm32.com/board/index.php?topic=12460)
   Init
   GetFiles *.txt   ; put text files of current folder into Files$() array
   Let Files$('A')=String$(8,"abc")   ; prefill Files$(65) (A=Ascii 65)

;   RichMasm (http://www.masm32.com/board/index.php?topic=12460) options (if you use another IDE, change the assembler option accordingly, and don't forget to set console assembly):
;   OPT_Assembler   Jwasm   ; requires \masm32\bin\JWASM.EXE
;   OxPT_Assembler   ml   ; the x disables this option - delete to use \masm32\bin\ML.exe
   ; 0+1=trigger error, 2=show incorrect result in Jwasm, 3=workaround
   TheCase=2


   ; we try to print the prefilled Files$(65)
   ife TheCase
      ; wrong syntax for String$, so Jwasm (trying to expand) complains with Error A2220
      Print Chr$("This text was put as String$(8) into Files$('A'): "), CrLf$, Files$('A')
   elseif TheCase eq 1
      ; same wrong syntax for String$, echo only - but Jwasm (trying to expand) complains
      % echo Print Chr$("This text was put as String$(8) into Files$('A'): "), CrLf$, Files$('A')
   elseif TheCase eq 2
      ; correct syntax for String$, Jwasm expands silently, we see ( eAx) instead of String$(32767, 0)
      Print Chr$("This text was put as String$(8,'abc') into Files$('A'): "), CrLf$, Files$('A')
   else
      ; workaround - split the quoted text to confuse Jwasm:
      Print Chr$("This text was put as Str", "ing$(8,'abc') into Fil", "es$('A'): "), CrLf$, Files$('A')
   endif
   Inkey Files$(65)
   Exit
end start

; expected output:
This text was put as String$(8, 'abc') into Files$('A'):
abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc

; JWasm, TheCase=2 (the two eax are the exitm values of the string$() and files$() macros):
This text was put as ( eAx) into ( EaX):
abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc

Note this snippet works fine with recent Jwasm versions:
   Dim My$(1)
   Let My$(0)="This is string zero"
   Let My$(1)="This is string one"
   Print "These are My$(0) and My$(1): ", CrLf$, My$(0), CrLf$, My$(1)
Title: Improved Clip$() - Ansi and Unicode
Post by: jj2007 on August 22, 2011, 07:36:53 AM
Clip$() did not work properly, inter alia because of the problems mentioned in the GetClipboardText thread (http://www.masm32.com/board/index.php?topic=17279.0). The new archive of 21 August (here (http://www.masm32.com/board/index.php?topic=12460)) fixes these problems and adds a new functionality, namely a check if any new text is on the clipboard - a handy function if, for example, you want to build a database of snippets copied from various websites.

Clip$, wClip$
      Print "[", Clip$(), "]"            ; displays the content of the clipboard
      MsgBox 0, Clip$(), "Text on the clipboard:", MB_OK      ; same as MessageBox
      MsgBox 0,\
      Cat$("The text on the clipboard:"+CrLf$+String$(33,"-")+CrLf$+Clip$(20)+CrLf$+String$(0,0)),\
      "MasmBasic:", MB_OK            ; displays a MessageBox with two horizontal delimiters
      MsgBox 0, Clip$(40), "The text on the clipboard, truncated to 40 chars:", MB_OK
      invoke lstrcpy, offset my40charbuffer, Clip$(40-1)      ; yep, don't forget space for the zero delimiter
      .Repeat
            void Clip$(30)                        ; this loop waits for changes on the clipboard
            .if !Zero?
               PrintLine "New clipboard content=[", eax, "]"      ; non-zero means new valid content available
            .endif
            invoke Sleep, 1                     ; note: "new" is defined as (len(string)+first dword) different
      .Until signed rv(GetKeyState, VK_ESCAPE)<0
Rem   - returns ptr in eax,  to Null$ if clipboard is empty
   - you can truncate the content for security reasons, e.g. for use in a MessageBox
   - if no argument is specified, up to 160k will be copied into the internal buffer

The Unicode version is named wClip$():

Quoteinclude \masm32\MasmBasic\MasmBasic.inc   ; download (http://www.masm32.com/board/index.php?topic=12460)
   Init
   wMsgBox 0, wCat$("Found on clipboard: ["+wClip$()+"]"), "This is Unicode:", MB_OK
   Exit
end start
(http://www.masm32.com/board/index.php?action=dlattach;topic=12460.0;id=9661)
Title: MasmBasic update: ArrayMinMax & ArraySearch
Post by: jj2007 on September 22, 2011, 10:04:48 PM
Some minor bugfixes and two new functions. Download version 23 September from top of thread (http://www.masm32.com/board/index.php?topic=12460).

ArrayMinMax
            Dim[/color] MyR4(9) As REAL4
            ArrayMinMax MyR4()         ; min in eax, max in edx - both as "pushable" REAL4
            push edx
            push eax
            ffree st(7)
            fld REAL4 ptr [esp]
            Print Str$("The Real Min=\t%Df\n", ST(0))
            pop edx
            ffree st(7)
            fld REAL4 ptr [esp]
            Print Str$("The Real Max=\t %Df\n", ST(0))
            pop edx
            fstp st
            fstp st
            Dim MyDw(9) As DWORD
            ArrayMinMax MyDw()         ; uses ArraySort syntax
            push edx
            Print Str$("The dw Min=\t%i\n", eax)
            pop edx
            Print Str$("The dw Max=\t %i\n", edx)
Rem            no return value

ArraySearch
            ; mov eax, ArraySearch(pSrc, sizeof Src, pattern [, size])      ; src, len(src), pattern, byte/word/dword
            Print Str$("Len %i\n", ArraySearch(esi, sizeof Src, 0, BYTE))      ; look for a nullbyte
            mov eax, dword ptr bins                     ; where bins is db "al", 0, 0
            Print Str$("Pos %i\n", ArraySearch(esi, sizeof Src, eax, WORD))   ; word given in eax
            Print Str$("Pos %i\n", ArraySearch(esi, sizeof Src, 6c61h, WORD))   ; immediate word
            Print Str$("Pos %i\n", ArraySearch(esi, sizeof Src, "al", WORD))   ; same but as string
            Print Str$("Pos %i\n", ArraySearch(esi, sizeof Src, MyPattern, word))   ; taken from mem, i.e. "al" is MyPattern dd "la"
            Print Str$("Pos %i\n", ArraySearch(esi, sizeof Src, "algo", DWORD))   ; dword as string
            Print Str$("Pos %i\n", ArraySearch(esi, sizeof Src, 'algo'))      ; same, dword assumed
            Print Str$("Pos %i\n", ArraySearch(esi, sizeof Src, "olgo", DWORD))   ; this one won't be found
Rem            - returns offset into first occurrence of pattern: if src is "This is my algo", then
              pattern algo as dword will not be found (eax=-1), but for "This was my algo", pos 12 would be returned
              pattern my as word will be found at pos 8
              pattern i as byte will be found at pos 2
            - ArraySearch uses SSE2 and is fast: it searches a 400 byte string more than four times
              as fast as repne scasd and 5 times as fast as BinSearch
            - by specifying zero as a byte pattern, you can use ArraySearch as a Len() substitute;
              however, MasmBasic Len() is twice as fast
            - do not confuse with Masm32 BinSearch, which finds patterns at "odd" positions, too, i.e.
              in the example above, invoke BinSearch, 0, chr$("This is my algo"), 16, chr$("al"), 3 would
              return a valid position 11
[/color]
Title: Re: MasmBasic
Post by: jj2007 on September 23, 2011, 07:14:27 AM
Here is a crispy little PureMasmTM example showing how to use the new functions:
- create a floating point array
- fill it with random numbers
- display them unsorted and sorted
- write them to disk
- read them back
- sort them

include \masm32\MasmBasic\MasmBasic.inc   ; library download (http://www.masm32.com/board/index.php?topic=12460)
ShowProperties   PROTO: DWORD
ArrayWrite = 0   ; equates just for
ArrayRead = 1      ; the ease of reading

   Init
   [/color]mov ebx, 999   ; you may play with this number for speed tests

   Dim MyR4w(ebx) As REAL4   ; this would work also for a DWORD array
   Dim MyR4r(ebx) As REAL4   ; create an array to hold the data from file

   ; ------- writing --------------
   Rand()   ; create a seed using rdtsc
   For_ n=0 To ebx
      Rand(-33.33, 55.55)   ; push random numbers on the FPU stack
      fstp MyR4w(n)   ; pop them to an array element
   Next
   Open "O", #1, "Real4.dat"   ; we create a file for output
   Store #1, MyR4w()   ; write them to file, unsorted
   Close
   
ArrayMinMax MyR4w()   ; get the minimum and maximum values
   push edx   ; save max to stack (edx is a REAL4)
   push eax   ; save min to stack (eax is a REAL4)
   Print "Unsorted:"
   invoke ShowProperties, ArrayWrite   ; show the first and last items
   
ArraySort MyR4w()
   Print Str$("\n\nMin of the write array is %f\n", REAL4 PTR [esp])
   pop eax
   Print Str$("Max of the write array is %f\n", REAL4 PTR [esp])
   pop eax
   invoke ShowProperties, ArrayWrite   ; show the first and last items
   Erase MyR4w()

   ; ------- reading --------------
   Open "I", #2, "Real4.dat"   ; we open the file for input
   Recall #2, MyR4r()   ; read data into array
   Close
   
ArrayMinMax MyR4r()   ; calculate minimum and maximum
   push edx   ; save max to stack (edx is a REAL4)
   push eax   ; save min to stack (eax is a REAL4)
   
ArraySort MyR4r()
   Print Str$("\n\nMin of the read array is %f\n", REAL4 PTR [esp])
   pop eax
   Print Str$("Max of the read array is %f\n", REAL4 PTR [esp])
   pop eax
   invoke ShowProperties, ArrayRead   ; show the first and last items
   Inkey CrLf$, CrLf$, "bye"
   
Exit

ShowProperties proc ModeRead
  For_ ecx=0 To ebx                     ; ecx is safe to use if there are no Windows API calls
     lea eax, [ebx-3]
   .if ecx<3 || ecx>eax               ; show the first and last three items
      Print CrLf$, Str$(ecx), Tb$
      .if ModeRead
         Print Str$(MyR4r(ecx))    ; show the number read from file
      .else
         Print Str$(MyR4w(ecx))    ; show the numbers that will be written to file
      .endif
   .else
        mov eax, ebx
        sar eax, 1                     ; halfway...
        .if ecx==eax
         Print CrLf$, "..."            ; ... insert a separator
      .endif
   .endif
  Next
  ret
ShowProperties endp
end start


Sample output:
Unsorted:
0       26.34964
1       -16.69160
2       32.47115
...
997     51.35131
998     48.90986
999     -31.98609

Min of the write array is -33.18150
Max of the write array is 55.54166

0       -33.18150
1       -33.13496
2       -33.10025
...
997     55.31524
998     55.42580
999     55.54166

Min of the read array is -33.18150
Max of the read array is 55.54166

0       -33.18150
1       -33.13496
2       -33.10025
...
997     55.31524
998     55.42580
999     55.54166
Title: Re: MasmBasic
Post by: juozas on September 24, 2011, 08:15:41 AM
Hi, Thanks for the update :D Works great. The editor works ok and compiles fine. But SkelMasmBasic example doesn't output all output as expected, I get this is:
QuoteThe command line: This
0 files found:
No.     Bytes   Name
#1      -1
The highlighted (bold) ones doesn't look all right to me, is this ok? It still doesn't look ok even i change compiler and linker to jwasm and polink. OS: WinXP Pro SP3 Fully Updated.

The versions of updated binaries I have are as shown below (I have backups of old ver. too):
ml.exe Version 6.15; poasm, polink, polib, porc Versions 6.00.*; rc.exe Version 6.1; wrc.exe Version 1.9

Also the editor hangs while trying to load another file (TestMasmBasic) from the menu or by draggin' in...

The zipped screenshot attached.
Title: Re: MasmBasic
Post by: jj2007 on September 25, 2011, 11:53:23 PM
Hi juozas,
thanks for the feedback:

The command line: This
OPT_Arg1   This is a command line with many spaces

Try OPT_Arg1   "This is a command line with many spaces"

Quote0 files found:
No.     Bytes   Name
#1      -1
If you run GetFiles *.asm on an empty folder, that is what you get: 0 files found. Since a For loop is run at least once (in contrast to a While..Endw loop), the file size returns -1, i.e. an error.

Re the editor hangs: I have done many improvements "under the hood", and yes it hangs if you use the Open file dialog. You can "unhang" it, though, by clicking on a bookmark or by searching something. But that is indeed a fat ugly bug which will be fixed hopefully today :red

EDIT: the bug is fixed. New version on top of thread. Inter alia, Open File via the file menu and dragn' drop work fine now.
Title: Bug chasing: New deb macro for monitoring changes in WndProc
Post by: jj2007 on October 01, 2011, 06:49:22 PM
The deb macro in version 30Sept2011 (http://www.masm32.com/board/index.php?topic=12460) can now monitor changes to global variables (actually, to any variables including reg32).
The variable to watch is marked e.g. as deb 4, "Change for ...", chg:MyGlobalVar
Here is a demo using a marginally modified \masm32\examples\exampl02\mdidemo\mditest.asm (see attachment):

WndProc proc hWin:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
    LOCAL var, caW, caH, hDC, tbH, sbH, mdihWnd
    LOCAL Rct:RECT
    LOCAL Ps:PAINTSTRUCT
    LOCAL tbab:TBADDBITMAP
    LOCAL tbb:TBBUTTON
    LOCAL cc:CLIENTCREATESTRUCT

    deb 4, "Top of WndProc", chg:hClient

Output to console:
Top of WndProc  chg:hClient     1116898
# uMsg #        WM_PARENTNOTIFY


... which is kind of surprising since hClient is being set in WM_CREATE.
To solve the mystery, we use three more "normal" deb calls as follows:

WndProc proc hWin:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
    LOCAL var, caW, caH, hDC, tbH, sbH, mdihWnd
    LOCAL Rct:RECT
    LOCAL Ps:PAINTSTRUCT
    LOCAL tbab:TBADDBITMAP
    LOCAL tbb:TBBUTTON
    LOCAL cc:CLIENTCREATESTRUCT

    deb 4, "Top of WndProc", chg:hClient
    .if uMsg == WM_CREATE
        ...
        deb 4, "Before CwEx", hClient
        invoke CreateWindowEx,WS_EX_CLIENTEDGE,
                              ADDR mdiCl,NULL,
                              WS_CHILD or WS_CLIPCHILDREN or \
                              WS_VISIBLE or WS_VSCROLL or WS_HSCROLL,
                              0,0,0,0,hWin,NULL,hInstance,ADDR cc
        mov hClient, eax
        deb 4, "After CwEx", hClient

    .elseif uMsg == WM_PARENTNOTIFY
        deb 4, "ParentNoti", hClient

New output to console:
ParentNoti      hClient         0
ParentNoti      hClient         0
Before CwEx     hClient         0
ParentNoti      hClient         0
After CwEx      hClient         2034354
Top of WndProc  chg:hClient     2034354
# uMsg #        WM_PARENTNOTIFY

Now we see that indeed WndProc is being called during CreateWindowEx.
Title: Re: MasmBasic
Post by: dedndave on October 01, 2011, 07:14:57 PM
several times   :P

the entire list represents all messages received by WndProc prior to execution of the message loop
i placed dummy messages into the list (handle=00000000) to mark entry and exit of WM_CREATE code
notice that, WM_CREATE returning to the OS seems to coincide with CreateWindowEx returning to the caller

http://www.masm32.com/board/index.php?topic=16633.msg138337#msg138337

that is only an example window that had 6 control windows (i think that's right)
the results will vary, of course, from program to program
Title: Re: MasmBasic
Post by: jj2007 on October 01, 2011, 08:51:55 PM
Yep, now I remember that thread :bg

Dave, there is a little trick to get your list of messages:

WndProc proc hWin:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
    LOCAL whatever
    deb 4, "Top of WndProc", chg:msgCounter
    inc msgCounter      ; every message triggers a change...

Output:
Top of WndProc  chg:msgCounter  1
# uMsg #        WM_GETMINMAXINFO
Top of WndProc  chg:msgCounter  2
# uMsg #        WM_NCCREATE
Top of WndProc  chg:msgCounter  3
# uMsg #        WM_NCCALCSIZE
Top of WndProc  chg:msgCounter  4
# uMsg #        WM_CREATE
Top of WndProc  chg:msgCounter  5
# uMsg #        WM_NOTIFYFORMAT
Top of WndProc  chg:msgCounter  6
# uMsg #        WM_QUERYUISTATE
Top of WndProc  chg:msgCounter  7
# uMsg #        WM_PARENTNOTIFY
Top of WndProc  chg:msgCounter  8
# uMsg #        WM_NOTIFYFORMAT
Top of WndProc  chg:msgCounter  9
# uMsg #        WM_QUERYUISTATE
Top of WndProc  chg:msgCounter  10
# uMsg #        WM_PARENTNOTIFY
Title: Re: MasmBasic
Post by: dedndave on October 01, 2011, 10:52:59 PM
well - i did things differently - lol
in that example, i used a circular buffer - filled it with the 4 WndProc parameters for each message
when the message loop started, i stopped putting things into the buffer and displayed them

the idea was to avoid possible infinite loops
now, i have a program that outputs messages in a seperate window/instance
Title: Re: MasmBasic
Post by: ToutEnMasm on October 02, 2011, 05:26:39 PM

I have try to test masmbasic.
Having two masm32 directories in two differents disk,I have renamed the masm32 in richmasm.
And it isn't a supported option   "couldn't find ......."
If i can made a suggestion ,rename your masm32 directory (easy way ,an editor made it)
                                     or use this functions (allow use of relative path to the application)
Quote
   invoke  GetModuleFileName,hInstance,addr appPath,sizeof appPath
   invoke GetFullPathName,addr appPath,sizeof appPath,addr CheminCompose,addr PointeNomCourt
Title: Re: MasmBasic
Post by: jj2007 on October 02, 2011, 06:10:10 PM
Cher Yves,

The archive has path names, and must be extracted to the root of your masm32 drive. Requesting that MasmBasic should work with different folder names is like requesting that Masm32 should work with \bin renamed to \mybin - it won't work.

Besides, MB just adds two folders to your \masm32 installation (\masm32\RichMasm and \masm32\MasmBasic), with one exception: \masm32\bin\mspdb_MasmBasic_Readme.txt
So there is actually no risk that it would interfere with your Masm32 installation. That is indeed the whole point of having MB: It should work smoothly in parallel to Hutch' Masm32 package, so that coders can profit from both worlds.

Thanks anyway for trying. At a certain point, I got inspired by your EditMasm project. RichMasm took a slightly different direction then, but as far as I know we are the only two guys in the assembler world who insist that individual formatting à la MS Word is a good idea :bg

Cheers,
Jochen
Title: Re: MasmBasic
Post by: ToutEnMasm on October 02, 2011, 06:25:04 PM

I know that you don't agree with me.I have tried to do it.
Something is wrong
Quote
Requesting that MasmBasic should work with different folder names is like requesting that Masm32 should work with \bin renamed to \mybin - it won't work.
It is possible (but without interest),just change all path in your source code (a baby game for cherche,a tool of mine) and your batch path (same tool).
:P

Title: Re: MasmBasic
Post by: jj2007 on October 02, 2011, 08:49:00 PM
Yves,

There is nothing wrong with MasmBasic provided that you extract it with "use folder names" to the root of the drive where your masm32 package is installed, e.g. to D:\

Practically all sources in \masm32\examples work just fine if you replace the usual entry stuff as follows:
include \masm32\MasmBasic\MasmBasic.inc
;    include \masm32\include\masm32rt.inc


Sometimes the include files are hidden away in extra files, e.g. \masm32\examples\exampl08\barchart\barchart.inc - in these cases, you can delete the whole section...
      include \masm32\include\windows.inc
...
      includelib \masm32\lib\msvcrt.lib

... although it is not necessary - if you leave the *.inc as is, the assembler will issue some warnings about duplicate files but it still works fine if you add this in line 8 of \masm32\examples\exampl08\barchart\barchart.asm:

      option casemap :none      ; case sensitive
      include \masm32\MasmBasic\MasmBasic.inc
      include barchart.inc      ; local includes for this file

MB will not work if you use the assembler that is included with Masm32, i.e. ml.exe version 6.14. Version 6.15 is the required minimum because of the SSE2 code used in MasmBasic. You can use JWasm (http://www.japheth.de/JWasm.html#jwdownload) as well.

Of course, if other people had similar problems in getting MasmBasic running, I would have to dig into detail. But that seems not to be the case, so I assume that your installation is somewhat special. Or does somebody have the same problems as Yves? Grateful for feedback - here is the simplest available test app:

include \masm32\MasmBasic\MasmBasic.inc   ; download (http://www.masm32.com/board/index.php?topic=12460)
   Init
   Credits
   Exit
end start

If you like a more interesting example, here is one with the debug macro:

include \masm32\MasmBasic\MasmBasic.inc   ; download (http://www.masm32.com/board/index.php?topic=12460)

.data
xx0   QWORD 123456789012345678
xx1   REAL8 1234567.890

   Init
   movlps xmm0, xx0   ; load a large integer
   movlps xmm1, xx1   ; load a double
   fldpi         ; feed the FPU
   push eax
   push eax
   fst REAL8 PTR [esp]   ; load a well-known double
   movlps xmm2, REAL8 PTR [esp]
   deb 1, "Some of your regs:", eax, ebp, ST(0), xmm0, f:xmm1, f:xmm2
   Exit
end start
Title: Re: MasmBasic
Post by: jj2007 on October 05, 2011, 10:34:45 PM
Update 6 October: Count counts the number of occurrences of a pattern inside a buffer. The Unicode equivalent is called wCount, as usual. Count is pretty fast, it processes more than 400 MB per second, see attachment.

Example #1 counts how many equ can be found in Windows.inc:

include \masm32\MasmBasic\MasmBasic.inc   ; download (http://www.masm32.com/board/index.php?topic=12460)
 
Init[/color]
  Let esi=FileRead$("\Masm32\include\Windows.inc")      ; Create a buffer for Windows.inc
  Print Str$("%i chars read\n", Len(esi))
  Print Str$(" Count equ=\t%i\n\n", Count(esi, Chr$("equ"), 1))      ; Count equ (1=case-insensitive)
  .if Exist("\Masm32\include\WindowsWide.inc")      ; to test wCount, open the ANSI version in an editor and save it as UNICODE
      wLet esi=FileRead$("\Masm32\include\WindowsWide.inc")      ; Let or wLet are the same for a plain FileRead$()
      Print Str$("%i chars read, including BOM", wLen(esi)), Str$(", filesize=%i\n", LastFileSize)
      Print Str$("wCount equ=\t%i\n", wCount(esi, wChr$("equ"), 1))
  .endif
  Inkey "Hit any key"
 
Exit
end start

Output:
849788 chars read
Count equ=     14955
849789 chars read, including BOM, filesize=1699578
wCount equ=    14955


Example #2 extracts function names from all *.inc files and counts the DWORD paras for each of them:

include \masm32\MasmBasic\MasmBasic.inc   ; Download (http://www.masm32.com/board/index.php?topic=12460) & install, then press F6 to assemble & link
   
Init
   push Timer
   Dim Proto$(200000)   ; 55,000 would be enough
   xor edi, edi
   GetFiles \masm32\include\*.inc   ; put all *.inc filenames into the Files$() array
   For_ n=0 To eax-1
      Let Proto$(edi)="### "+Files$(n)
      inc edi
      Recall Files$(n), IncFile$()   ; load all strings from Files$(n) into a new IncFile$() array
      For_ ecx=0 To eax-1
         mov esi, IncFile$(ecx)   ; Let not needed, since we will not modify the string
         .if Instr_(esi, "PROTO", 5)   ; edx is pos of first PROTO - we subtract 2 to arrive at the last char of the function name
            xchg edx, ebx   ; we need a non-volatile reg32
            Let Proto$(edi)=Left$(esi, ebx-2)+Str$("@%i", Count(esi, "DWORD", 5))   ; e.g. CreateWindowExA@12
            inc edi
            .Break .if edi>=Proto$(?)
         .endif
      Next
      .Break .if edi>=Proto$(?)
   Next
   Store "\masm32\RichMasm\Res\MbProtos.dat", Proto$(), edi   ; write edi strings to file
   pop ecx
   Inkey Str$("Analysing %i files", n), Str$(" took %i ms\n", Timer-ecx), Str$("%i PROTOs found, written to\n\masm32\RichMasm\Res\MbProtos.dat\n", edi-n)
   
Exit
end start

Output:
Analysing 345 files took 312 ms
53518 PROTOs found, written to
\masm32\RichMasm\Res\MbProtos.dat


The file \masm32\RichMasm\Res\MbProtos.dat:
### \masm32\include\1394bus.inc
Bus1394RegisterPortDriver@1
### \masm32\include\acledit.inc
DllMain@3
FMExtensionProcW@3
SedDiscretionaryAclEditor@13
SedSystemAclEditor@12
SedTakeOwnership@14
### \masm32\include\aclui.inc
CreateSecurityPage@1
...
### \masm32\include\xactsrv.inc
XsCaptureParameters@2
XsCheckSmbDescriptor@2
XsConvertServerEnumBuffer@8
Title: Re: MasmBasic
Post by: jj2007 on October 09, 2011, 11:47:07 PM
Update 10 Oct: Open and Print accept now a non-immediate #number, so that you can create and write multiple files in a loop.

include \masm32\MasmBasic\MasmBasic.inc   ; download (http://www.masm32.com/board/index.php?topic=12460.0)
   Init[/size]
   For_ ebx=0 To 3
      Open "O", #ebx, Str$("File_%i.dat", ebx)
   Next
   For_ ebx=0 To 3
      wPrint #ebx, wStr$("This is file %i", ebx)   ; Unicode, just for fun
   Next
   Close
   Inkey "4 files created & written"
   
Exit
end start
Title: Re: MasmBasic
Post by: jj2007 on October 19, 2011, 10:16:12 PM
Update 20 October - download on top of thread (http://www.masm32.com/board/index.php?topic=12460):

- bugfix: mov eax, Val("123.456") would return the right value (123) but wrong # of chars used in edx.
- no easy fix for this one: cells in a two-dimensional string array loaded from a tab-delimited textfile cannot be directly concatenated in Let or Print. Example:

include \masm32\MasmBasic\MasmBasic.inc   ; download (http://www.masm32.com/board/index.php?topic=12460)
   Init
   Recall "MyTabFile.txt", MyCellArray$(), tab   ; load a tab-delimited text file (same for csv format)
   PrintLine "A1=", MyCellArray$(0,0)   ; show the cell in the upper left corner

   Print "fails:", Tb$
   PrintLine "A2=", MyCellArray$(1,0), Tb$, "A3=", MyCellArray$(2, 0)   ; fails miserably showing twice the same cell

   Print "works:", Tb$
   Print "A2=", MyCellArray$(1,0), Tb$, "A3="   ; workaround: separate the two cells
   PrintLine MyCellArray$(2, 0)

   Dim MyArray$(3, 3)      ; "hand-made" two-dimensional string arrays are organised differently
   Let MyArray$(0, 1)="This is 01"
   Let MyArray$(1, 0)="this is 10"
   PrintLine MyArray$(0, 1), ", and ", MyArray$(1, 0)   ; no problem for the hand-made array
   Exit
end start

- new function CurDir$():
   Let esi=CurDir$()+"MyFile.txt"      ; e.g. D:\masm32\RichMasm\Res\MyFile.txt
   Let esi=CurDir$(0)+"\MyFile.txt"   ; same output, the (0) means "do not append a backslash"

- new function ExpandEnv$():
   PrintLine "Architecture is ", ExpandEnv$("%PROCESSOR_ARCHITECTURE%, the OS is %OS%, and the CPU is"), CrLf$,\
   ExpandEnv$("%PROCESSOR_IDENTIFIER%")
   PrintLine "This is the full path: [", ExpandEnv$("%ProgramFiles%\Microsoft Office\OFFICE11\WINWORD.EXE"), "]"
   Let esi="This is the full path: ["+ExpandEnv$("%ProgramFiles%\Microsoft Office\OFFICE11\WINWORD.EXE")+"]"
Architecture is x86, the OS is Windows_NT, and the CPU is
x86 Family 6 Model 14 Stepping 8, GenuineIntel
This is the full path: [C:\PROGRA~1\Microsoft Office\OFFICE11\WINWORD.EXE]


- last but not least, following some tests in the RevString thread (http://www.masm32.com/board/index.php?topic=17560.0) (based on a much older thread (http://www.masm32.com/board/index.php?topic=14041.0)), Mirror$() accepts now non-immediate args:
   cmp eax, Mirror$("Masm")      ; easier than cmp eax, "msaM"
   PrintLine Mirror$("Masm32 is great")   ; uses an entry in the .data section
   Let esi=Mirror$("Masm32 is great")
   PrintLine esi         ; shows    taerg si 23msaM
   Let esi=Mirror$(esi)
   PrintLine esi         ; back to   Masm32 is great

Enjoy :bg
Title: Re: MasmBasic
Post by: jj2007 on October 21, 2011, 07:29:16 PM
Incremental update - the Unicode version of ExpandEnv$:

include \masm32\MasmBasic\MasmBasic.inc
   Init
   wPrint wChr$("This is the full path in Unicode: ["), wExpandEnv$("%ProgramFiles%\Microsoft Office\OFFICE11\WINWORD.EXE", 1), wChr$("]"), wCrLf$

   wMsgBox 0, wCat$("This is the full path: ["+wExpandEnv$("%ALLUSERSPROFILE%", 1)+"]"), "Unicode:", MB_OK
   wMsgBox 0, wCat$("This is the full path: ["+wExpandEnv$("%ProgramFiles%\Microsoft Office\OFFICE11\WINWORD.EXE", 1)+"]"), "Unicode:", MB_OK
   Exit
end start

An optional "...xxx", 1 forces ExpandEnv$ to deliver the long name of a path. This will not work for constructs like ExpandEnv$("%PROCESSOR_ARCHITECTURE%, the OS is %OS%, and the CPU is %PROCESSOR_IDENTIFIER%"), of course.

Only two files, MasmBasic.inc and MbGuide.rtf, changed, therefore the "incremental" update attached.
EDIT: See below, full update of 24 Oct on top of thread.

There is a good overview of available preset environment variables here (http://ss64.com/nt/syntax-variables.html). Note the dynamic variables mentioned there (e.g. %TIME%) will not expand.

Here is a mini-app showing your current environment variables:

include \masm32\MasmBasic\MasmBasic.inc   ; download (http://www.masm32.com/board/index.php?topic=12460)
   Init
   push esi
   call GetEnvironmentStrings
   xchg eax, esi
   push esi
@@:   lodsb
   dec al
   jns @B
   mov [esi-1], 10
   lodsb
   dec al
   jns @B
   pop eax
   pop esi
   Inkey eax
   Exit
end start


P.S.: I wonder what %ProgramFiles% shows on a Chinese Windows version... ::)
Title: Bug warning
Post by: jj2007 on October 24, 2011, 07:32:29 PM
Str$() returned wrong values for structure members. Fixed in version 24 Oct 2011:

include \masm32\MasmBasic\MasmBasic.inc   ; download (http://www.masm32.com/board/index.php?topic=12460)
.data
pxy   POINT <12, 34>
   Init
   Inkey Str$("The point coordinates are %i and ", pxy.x), Str$(pxy.y)
   Exit
end start

Apologies to those 20 who downloaded the buggy version.

Minor improvements:

a) wChr$ accepts now a register or variable - handy if you got an ANSI string but need a Unicode string e.g. for GdiPlus:

   mov eax, Chr$("This is an ANSI string")
   wPrint wChr$("Not true: "), wChr$(eax)

b) Unicode to console printing is now more likely to succeed, but you may need to set console properties by hand to Lucida console:

include \masm32\MasmBasic\MasmBasic.inc
   Init
   wInkey wRes$(801)   ; needs a string in the resource file as shown below
   Exit
end start

STRINGTABLE
BEGIN
   801,   "أدخل النص هنا"               ; "Enter text here" in Arabic
END

Unicode and console is a tricky story, but so far the snippet above works for me. Internally, it uses
invoke SetConsoleOutputCP, CP_UTF8
and it sets the console color (see ConsoleColor in MbGuide.rtf). Note that if one of these two actions is not performed, the console will not display Arabic or Chinese characters properly, even if you have set Lucida Console. Note also that some colors work, others don't, and it depends basically on whether the puter booted with the left or the right foot. It is messy - Windows developers apparently have lost interest in console apps.
Title: Re: MasmBasic
Post by: jj2007 on October 28, 2011, 09:11:29 PM
Update 28 October:
- minor bugfix in RichMasm (the tooltips over URLs did not disappear)
- a wrapper for GdipDrawImageRectI (sample app attached - a simple image viewer for jpg, bmp, gif and png files)

ImgPaint
   GetFiles *.jpg         ; load all jpg files in this folder and below
   AddFiles *.png         ; add all png files
   
[/b]ImgPaintInfo 0, Files$(ImgCounter)   ; load image file in slot 0 and return image dimensions - width in eax, height in edx
   ImgPaint hStatic, 0, Files$(ImgCounter)   ; use in the WM_PAINT handler to fill static control with Globe.ico; take slot 0 (of 30)
   ImgPaintClr 2         ; unload image file in slot 2
Rem   - [/b]ImgPaintInfo can be used to adjust the dimensions of the control that takes the image
   - ImgPaint should be called from the WM_PAINT handler
   - ImgPaint accepts most common image formats, e.g. bmp, gif, png and jpg
   - ImgPaintClr frees memory, if really needed. The Exit macro frees all loaded images automatically
   - 30 slots are available, i.e. you can fill 30 static controls with images; should be enough for a card game ;-)



The image viewer:

Quoteinclude \masm32\MasmBasic\MasmBasic.inc   ; download (http://www.masm32.com/board/index.php?topic=12460)

.data?
hStatic   dd ?   ; static control serves as canvas
ImgCounter   dd ?   ; Files$(0...MbGetFileCount)

   
Init         [/color]; initialise MasmBasic (http://www.masm32.com/board/index.php?topic=12460)
   mov esi, CL$()   ; get first arg of commandline
   GfNoRecurse=1   ; search only in the current folder
   .if Exist(esi)
      Let esi=Left$(esi, Rinstr(esi, "\"))+"*"+Right$(esi, 4)
      GetFiles esi   ; show files with the same extension
   .else
      GetFiles *.jpg   ; load Files$() array with
      AddFiles *.png   ; typical image files
      AddFiles *.gif
   .endif
   call WinMain
   
Exit
[/color]
WinMain proc
LOCAL msg:MSG, wcex:WNDCLASSEX
   call ClearLocVars   ; zero WNDCLASSEX
   ebxNull equ <ebx>
   xor ebx, ebx   ; ebxNull
   lea esi, wcex
   wc equ <[esi.WNDCLASSEX]>
   m2m wc.cbSize, WNDCLASSEX
   m2m wc.style, CS_HREDRAW or CS_VREDRAW
   mov wc.lpfnWndProc, offset WndProc
   m2m wc.hbrBackground, COLOR_BTNFACE+1
   mov wc.lpszClassName, Chr$("MB GUI")
   mov wc.hInstance, rv(GetModuleHandle, ebxNull)
   mov wc.hIcon, rv(LoadIcon, eax, IDI_APPLICATION)   ; eax=hInstance
   mov wc.hIconSm, eax
   mov wc.hCursor, rv(LoadCursor, ebxNull, IDC_ARROW)
   invoke RegisterClassEx, esi
   invoke CreateWindowEx, WS_EX_CLIENTEDGE,
      wc.lpszClassName, ebxNull,
      WS_CAPTION or WS_THICKFRAME or WS_CLIPCHILDREN or WS_VISIBLE,
      -127, -127, ebxNull, ebxNull,\   ; for now, outside of visible screen
      ebxNull, ebxNull, wc.hInstance, ebxNull
   invoke CreateWindowEx, ebxNull, Chr$("static"), ebxNull,
      WS_CHILD or WS_VISIBLE, ebxNull, ebxNull, ebxNull, ebxNull,
      eax, 123, wc.hInstance, ebxNull   ; eax=retval cwex main, 123=IdStatic
   mov hStatic, eax
   add esi, wc.cbSize   ; lea esi, msg but one byte shorter ;-)
   .Repeat
      invoke GetMessage, esi, ebxNull, ebxNull, ebxNull
      .Break .if !eax
         ; invoke TranslateMessage, esi
         invoke DispatchMessage, esi
   .Until 0
   ret
WinMain endp

WndProc proc uses edi esi ebx hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
LOCAL rc:RECT, pt:POINT

  SWITCH uMsg
  CASE WM_DESTROY
   invoke PostQuitMessage, NULL

  CASE WM_KEYUP
     call ArrowHandler   ; left/up=previous, right down=next image, [Ctrl] PageDown/Up, Home, End

  CASE WM_SIZE
   call CenterImage   ; resize window to fit image #1

  CASE WM_GETMINMAXINFO
     mov eax, lParam
     and [eax.MINMAXINFO.ptMinTrackSize.x], 0   ; for very small fotos, e.g. icons
     and [eax.MINMAXINFO.ptMinTrackSize.y], 0

  CASE WM_PAINT
   invoke GetClientRect, hWnd, addr rc
   invoke MoveWindow, hStatic, 0, 0, rc.right, rc.bottom, 0
   invoke InvalidateRect, hStatic, 0, 0
   mov esi, Files$(ImgCounter)
   ImgPaint hStatic, 0, esi      ; <<<< GdiPlus
GdipDrawImageRectI wrapper[/color]
      SetWin$(hWnd)="Viewing "+esi

  ENDSW
  invoke DefWindowProc, hWnd, uMsg, wParam, lParam
 
ret

CenterImage:
...
ArrowHandler:
...
   retn 0
WndProc endp

end start
Title: Re: MasmBasic
Post by: juozas on October 29, 2011, 10:31:27 AM
ok. downloaded latest version, updated files, opened masmbasic, got build errors on SkelMasmBasic...
Quote*** user-defined OPT_xx variables: ***

*** SkelMasmBasic.rc not found, will try rsrc.rc ***
OPT_Arg1: "This is a command line with spaces"
OPT_Arg2: "The second command line argument"
OPT_Out:  "SkelMasmBasic.exe"
OPT_Res:  rsrc


*** Assemble, link and run SkelMasmBasic ***

Microsoft (R) Windows (R) Resource Compiler Version 6.1.7600.16385

Copyright (C) Microsoft Corporation.  All rights reserved.


*** Assemble using \Masm32\bin\ml /nologo /c /coff  /Fl /Sn /Fo "SkelMasmBasic" ***
Assembling: tmp_file.asm
tmp_file.asm(23) : error A2008: syntax error : ,
wChr$(2): Macro Called From
  wPrint(1): Macro Called From
   tmp_file.asm(23): Main Line Code
*** Assembly Error ***

Screenshot below:

(http://www.masm32.com/board/index.php?action=dlattach;topic=12460.0;id=9881)

Jwasm gives me error too:
*** user-defined OPT_xx variables: ***

*** SkelMasmBasic.rc not found, will try rsrc.rc ***
OPT_Arg1: "This is a command line with spaces"
OPT_Arg2: "The second command line argument"
OPT_Out:  "SkelMasmBasic.exe"
OPT_Res:  rsrc


*** Assemble, link and run SkelMasmBasic ***

Microsoft (R) Windows (R) Resource Compiler Version 6.1.7600.16385

Copyright (C) Microsoft Corporation.  All rights reserved.


*** Assemble using \Masm32\bin\JWasm /nologo /c /coff  /Fl /Sn /Fo "SkelMasmBasic" ***
Tmp_File.asm(23) : Error A2227: Missing right parenthesis in expression
wChr$(1)[MasmBasic.inc]: Macro called from
  Tmp_File.asm(23): Main line code
Tmp_File.asm: 34 lines, 1 passes, 78 ms, 0 warnings, 1 errors
*** Assembly Error ***
Title: Re: MasmBasic
Post by: jj2007 on October 29, 2011, 03:08:45 PM
      Open "O", #1, "Wide.txt"
      wPrint #1, wChr$("This is Unicode", 13, 10)   ; just for fun, we write a wide string to file
      Close


Thanks for the bug report, Jouzas.

Old & buggy:
wChr$ MACRO args:VARARG
LOCAL argByte, argWide, oo
  oa = (opattr args) AND 127
  if (oa eq atImmediate) or (oa eq 0)   ; ml needs the zero


New & perfect:
wChr$ MACRO args:VARARG
LOCAL argByte, argWide, oo, arg1
  FOR arg1, <args>
   oa = opattr arg1
   EXITM
  ENDM
  if (oa eq atImmediate) or (oa eq 0)   ; ml needs the zero


The FOR arg1, <args> is a dirty hack but it works. New version 29 Oct attached on top of thread.
The reason for this bug is actually that wChr$() learnt to deal with non-immediates, e.g. wChr$(esi), so I had to check the opattr now - and it fails for more than one arg.
Title: Dave's Basic
Post by: jj2007 on November 01, 2011, 11:37:05 PM
This is a special update dedicated to DednDave :bg

Quote from: dedndave on October 28, 2011, 02:54:07 AM
the simpler method...
        mov     ebx,offset MyStruct
        mov     al,[ebx]._TEST.Member


Let's go a step further, and create a global structure with 256 bytes of Frequently Used Variables (FUV):

include \masm32\MasmBasic\MasmBasic.inc   ; download (http://www.masm32.com/board/index.php?topic=12460)

GlobalVars STRUCT   ; 64+1 members
gsA   dd ?   ; DWORD #1 of 65
gsB   dd ?
...
...
gspZ   dd ?
gspRC   RECT <>   ; any name and type allowed here
gsp4   dd ?
gsp5   dd ?   ; DWORD #64
gsp6   dd ?   ; just for fun: #65, outside -128...+127 range
GlobalVars ENDS
.data
MyRc   RECT <12, 34, 56, 78>
Before   dd 123
ggv   GlobalVars <>   ; would normally be in the .data? section
After   dd 456


The point here is that you can get a "privileged access" to 64 dwords (or a lower number of other types, e.g. RECT) by using e.g. ebx as a permanent pointer:

   Init
   gv equ <[ebx.GlobalVars-128]>
   mov ebx, offset ggv+128   ; place ebx in the middle of the structure
   mov eax, 111
   int 3   ; Olly will stop here
   mov ggv.gsA, eax   ; the "normal" addressing mode, 5 bytes
   mov gv.gsA, eax   ; relative to ebx
   mov gv.gsB, eax
   mov gv.gsp4, eax
   mov gv.gsp5, eax   ; relative to ebx
   mov gv.gsp6, eax   ; relative to ebx but gsp6 is outside of  -128...+127 range, 6 bytes
   mov ggv.gsp5, eax   ; the "normal" addressing mode, 5 bytes


Now the first good news here is that Dave's syntax allows a very convenient text equate: gv equ <[ebx.GlobalVars-128]>
The second good news is that both the Str$() and the deb macro now understand the equate, as shown below:

   debExpand=0
   deb 4, "Rect short", gv.gspRC.left, gv.gspRC.top, gv.gspRC.right, gv.gspRC.bottom
   debExpand=1
   deb 4, "Rect expanded", gv.gspRC.left, gv.gspRC.top, gv.gspRC.right, gv.gspRC.bottom
   Print Str$("\nRect=%i", gv.gspRC.left), "/", Str$(gv.gspRC.top), "/", Str$(gv.gspRC.right), "/", Str$(gv.gspRC.bottom), CrLf$, CrLf$

Output:
Rect short
gv.gspRC.left   12
gv.gspRC.top    34
gv.gspRC.right  56
gv.gspRC.bottom 78

Rect expanded
[ebx.GlobalVars-128].gspRC.left 12
[ebx.GlobalVars-128].gspRC.top  34
[ebx.GlobalVars-128].gspRC.right        56
[ebx.GlobalVars-128].gspRC.bottom       78

Rect=12/34/56/78
Title: Re: MasmBasic
Post by: dedndave on November 02, 2011, 09:55:40 AM
thanks, Jochen   :bg

i had not thought of using up the neg offsets   :U
Title: Re: MasmBasic
Post by: jj2007 on November 02, 2011, 09:51:02 PM
Quote from: dedndave on November 02, 2011, 09:55:40 AM
thanks, Jochen   :bg

i had not thought of using up the neg offsets   :U

Actually, for full performance, one should use HeapAlloc in combination with a memalign that matches the cache line size, which is 64 bytes*) according to Intel:

   PrintLine "Same approach using HeapAlloc:"
.data?
   pHeap   dd ?
   Ebx64   dd ?
.code
   invoke HeapAlloc, rv(GetProcessHeap), HEAP_ZERO_MEMORY, GlobalVars
   mov pHeap, eax
   xchg eax, ebx      ; in the interest of performance, we will align the pointer ;-)
   memalign ebx, 64    ; see Intel (http://software.intel.com/en-us/forums/showthread.php?t=65575&wapkw=%28QX6850%29): The cache line size is the same in all three cases: 64 Bytes
   sub ebx, -128      ; use the negative offsets, too
   mov Ebx64, ebx     ; keep a global copy e.g. for assigning to ebx at the top of WndProc
   mov gv.gsB, 123
   debExpand=0
   deb 4, "short", gv.gsB
   debExpand=1
   deb 4, "expanded", gv.gsB
   deb 4, "long form", [ebx.GlobalVars.gsB-128]
   PrintLine Str$("gv=%i", [ebx.GlobalVars.gsB-128]/gv.gsB)
   PrintLine Str$("gv.gsB/1.23=%i", gv.gsB/1.23)
   invoke HeapFree, rv(GetProcessHeap), 0, pHeap
   deb 4, "HeapFree returned", eax
   Inkey "ok"

Output:
Same approach using HeapAlloc:
short   gv.gsB          123
expanded        [ebx.GlobalVars-128].gsB        123
long form       [ebx.GlobalVars.gsB-128]        123
gv=1
gv.gsB/1.23=100
HeapFree returned       eax             1

*)
QuoteIntel: (http://software.intel.com/en-us/forums/showthread.php?t=70545)
You are right that on modern IA-32 hardware, the cache line size is 64.  The value 128 is a legacy of the Intel Netburst Microarchitecture
(e.g. Intel Pentium D) where 64-byte lines are paired into 128-byte sectors.   When a line in a sector is fetched, the hardware automatically
fetches the other line in the sector too.  So from a false sharing perspective, the effective line size is 128 bytes on the Netburst processors
[/b]

P.S.: I had to upload a new version because wCL$() (Unicode commandline, uses GetCommandLineW) had a minor bug. This is now valid code:

include \masm32\MasmBasic\MasmBasic.inc   ; download (http://www.masm32.com/board/index.php?topic=12460)
   Init
   xor ebx, ebx
   wPrint wChr$("Checking the commandline:")
@@:   inc ebx
   mov ecx, wCL$(ebx)
   jecxz @F
   wPrint wCrLf$, wStr$("arg %i\t", ebx), ecx
   .if wInstr_(ecx, wChr$("/"))
      wPrint wChr$(9, "valid options have a slash")
   .endif
   jmp @B
@@:   wInkey wChr$(13, 10, 10, "-- bye --")
   Exit
end start

Sample output with this batch file and a cyrillic file dragged over the bat:
@echo off
\masm32\RichMasm\CmdLineW.exe /read /write /dump %1 \and \more \args
pause

Checking the commandline:
arg 1   /read   valid options have a slash
arg 2   /write  valid options have a slash
arg 3   /dump   valid options have a slash
arg 4   D:\masm32\RichMasm\Добро пожаловать.txt
arg 5   \and
arg 6   \more
arg 7   \args
Title: IncBin for ML.EXE
Post by: jj2007 on December 06, 2011, 10:23:04 AM
Here is a little tool to embed binary data into your executable, similar to JWasm's IncBin directive. Its usage is very simple:

   drag the file to embed over CreateIncBin.exe
   insert include FileName.dat into the .data section
   use offset filename as a pointer to the embedded data

Example:
include \masm32\include\masm32rt.inc

.data
include SayHello.dat ; generated with CreateIncBin.exe
db 0 ; for displaying embedded text
.code
start: inkey offset SayHello, 13, 10, 10, 10, "Masm is fun!"
exit
end start


Source and demo attached.
Title: NanoTimer
Post by: jj2007 on January 18, 2012, 08:39:16 PM
Inspired by Edgar's fast file time thread (http://www.masm32.com/board/index.php?topic=18104.0), the next edition of MasmBasic will feature a NanoTimer macro. This is a pre-release in case you need one urgently ;-)

include \masm32\MasmBasic\MasmBasic.inc   ; download (http://www.masm32.com/board/index.php?topic=12460)
include NanoTimer.mac   ; attached

   Init
   SleepMs = 250   ; 125/250/500 yield exact results

   NanoTimer()   ; start the timer
   Delay SleepMs   ; sleep some milliseconds
   Print Str$("%i milliseconds = ",
NanoTimer(ms))
   
   NanoTimer()
   Delay SleepMs
   Print Str$("%i microseconds = ",
NanoTimer(µs))
   
   NanoTimer()
   Delay SleepMs
   Inkey Str$("%i nanoseconds",
NanoTimer())

   Exit
end start


Output:
250 milliseconds = 250000 microseconds = 250000000 nanoseconds

I hope the syntax is self-explanatory :bg

P.S. The resolution is 100 ns.
Title: Re: MasmBasic
Post by: MichaelW on January 18, 2012, 09:46:13 PM
The problem I see with this is that (in my tests under Windows 2000) the effective resolution of the interrupt time defaults to 10ms, although you can use timeBeginPeriod to set it to 1ms. With an effective resolution of a few microseconds the high-resolution performance counter would be a better choice for a precision timer.

I just got reminded of a related function:

;==============================================================================
include \masm32\include\masm32rt.inc
;==============================================================================

printf MACRO format:REQ, args:VARARG
    IFNB <args>
        invoke crt_printf, cfm$(format), args
    ELSE
        invoke crt_printf, cfm$(format)
    ENDIF
    EXITM <>
ENDM

;==============================================================================
    .data
        timeAdjustment          dd 0
        timeIncrement           dd 0
        timeAdjustmentDisabled  dd 0
    .code
;==============================================================================
start:
;==============================================================================

    invoke GetSystemTimeAdjustment, ADDR timeAdjustment,
                                    ADDR timeIncrement,
                                    ADDR timeAdjustmentDisabled

    printf("%d\n%d\n\n",timeAdjustment,timeIncrement)

    inkey "Press any key to exit..."
    exit
;==============================================================================
end start


The (somewhat strange) results running on my Windows 2000 system:

100144
100144

Title: Re: MasmBasic
Post by: jj2007 on January 19, 2012, 12:55:44 AM
Michael,
You are right - I had not yet seen this granularity, quite familiar from GetTickCount. No miracles under the sun :(
But the QPC seems to work:
100     ms delay: 98.000 s
200     ms delay: 203.00 s
300     ms delay: 312.00 s
400     ms delay: 406.00 s
500     ms delay: 500.00 s
600     ms delay: 608.00 s
700     ms delay: 703.00 s
800     ms delay: 812.00 s
900     ms delay: 906.00 s
1000    ms delay: 1000.00 s


Same syntax as before, macros attached.

include \masm32\MasmBasic\MasmBasic.inc   ; download (http://www.masm32.com/board/index.php?topic=12460)
include NanoTimer.mac

   Init
   SleepMs = 250   ; 125/250/500 yield exact results
   NanoTimer()   ; start the timer
   Delay SleepMs   ; sleep some milliseconds
   Print Str$("%3f seconds = ",
NanoTimer(s))
   
   NanoTimer()
   Delay SleepMs
   Print Str$("%i milliseconds = ",
NanoTimer(ms))
   
   NanoTimer()
   Delay SleepMs
   Inkey Str$("%i microseconds",
NanoTimer(µs))
   Exit
end start

Output: 0.241 seconds = 250 milliseconds = 249795 microseconds
Title: MasmBasic - Januar 2012 version
Post by: jj2007 on January 28, 2012, 08:55:43 PM
I haven't updated MasmBasic since 3 November, but I was working a lot with MasmBasic, and there are some by-products of this activity that I could share with you. A rough count says it has now about 140 commands, plus 28 Unicode versions :bg

The 28 Jan 2012 version is ready for download here (http://www.masm32.com/board/index.php?topic=12460). Incomplete list of changes:

- fully compatible with 1. Masm32 version 11, 2. all Masm versions starting from ML 6.15, 3. JWasm
- updated the C++ example at \masm32\MasmBasic\MB2C\CalcTest.asc
- SetClip$:
   SetClip$ "Today is the "+Date$+", and the time is "+Time$
   wSetClip$ "Today is the "+wDate$+", and the time is "+wTime$
   SetClip$ hBmp, CF_BITMAP
- Rand() improved, e.g. Rand(1, 7, MyArray(ebx))      ; put random number directly into the (byte, word, dword, qword, r4, r8) array
- crt_xxx dependencies eliminated except for QSort
- wChr$(eax) works
- NanoTimer uses QPC
- Launch (aka ShellExecute) can now passdata to consoles ->ParentData$()
  Launch "my.exe", passdata, esi [, Len(esi)]
- IncBin function here (http://www.masm32.com/board/index.php?topic=17867.msg150571#msg150571)
- solved LNK4078 warning (http://www.masm32.com/board/index.php?topic=18117.msg152837#msg152837) problem
- interface to Kip Irvine's library (http://www.masm32.com/board/index.php?topic=17846.0)
- DosBasic (http://www.masm32.com/board/index.php?topic=17991.0)
- Inkey and wInkey return Chr$/wChr$ compatible code, i.e. Windows keys (VK_LEFT...) instead of scan codes
- combining Left$ and Trim$ works now:
   Let edi="       badly_formatted_equate     EQU 123"      ; desired output: [badly_formatted_equate]
   Let edi=Trim$(Left$(edi, Instr_(edi, "equ", 5)-1))      ; Instr 5=case-insensitive, whole word
   Print "[", edi, "]"
- fixed a problem with the DLL examples (\masm32\RichMasm\Res\MbMicroDll.asc) and RichMasm

The new functions are documented, as usual, in \masm32\MasmBasic\MbGuide.rtf

Some examples are attached, including TestMasmBasic.asc, my internal testbed.
The second attachment contains the two templates (spreadsheet, FPU) that are marked in red when you click "New Masm source" in RichMasm.
Title: Re: MasmBasic
Post by: jj2007 on February 01, 2012, 06:18:25 PM
I hesitated a lot to put the 1 Feb version online, because it has some potential for abuse; however, it seems that a simple firewall would inform the user that there is a download attempt, so here it is:

include \masm32\MasmBasic\MasmBasic.inc   ; download (http://www.masm32.com/board/index.php?topic=12460)
   Init
   ; read a file from the Internet, strip all HTML tags, scripts and styles, and display it on the screen:
   Inkey NoTag$(FileRead$("http://www.masm32.com"))
   Exit
end start

I am curious if any AV would trigger an alert ::)

Output:
MASM32 Home Page
The MASM32 SDK
Index Download Installation Forum License History Myths Why
The MASM32 SDK Version 11
Description The MASM32 SDK version 11 is a working development environment for p
rogrammers who are interested in either learning or writing 32 bit Microsoft ass
embler (MASM). The installation is an automated process that installs the correc
t directory tree structure on the local drive of your choice.
...
Not for the faint of heart. If MASM is beyond you, take up server side scripting
.
Copyright (c) The MASM32 SDK 1998 - 2012 All Rights Reserved
Title: Re: MasmBasic
Post by: dedndave on February 01, 2012, 07:09:10 PM
Smith & Wesson sells guns - that doesn't make them killers - lol

reminds me of a hoax article i saw about an interview with an Aussie General...
http://www.hoax-slayer.com/cosgrove-female-interviewer.shtml

QuoteWell, Ma'am, you're equipped to be a prostitute, but you're not one, are you?
Title: Floating point comparisons
Post by: jj2007 on February 09, 2012, 01:13:01 AM
The Feb 9 2012 version of MasmBasic (http://www.masm32.com/board/index.php?topic=12460.0) features a new Fcmp (more (http://www.masm32.com/board/index.php?topic=18253.msg154377#msg154377)):

Fcmp
MyPI_hi   REAL4   3.14160
   ...
   Fcmp MyPI_hi, PI, medium
   .if FcmpLesser
      Print Str$("MyPI_hi at %f is lower than the real PI\n", MyPI_hi)
   .elseif Zero?
      Print Str$("MyPI_hi at %f is exact\n", MyPI_hi)
   .else
      Print Str$("MyPI_hi at %f is higher than the real PI\n", MyPI_hi)
   .endif
Rem   - returns Zero? and Sign? flags: Sign? means "first arg below second arg"
   - you may use FcmpGreater and FcmpLess (aka !Sign? and Sign?)
   - single arg, e.g. Fcmp xmm1, tests for zero
   - almost any number formats can be compared, including xmm registers etc

Example:
   m2m eax, 123
   movd xmm0, eax
   Print Str$("Xmm0 at %i is ", xmm0)
   Fcmp xmm0, FP10(123.1)
   .if Sign?
      PrintLine "lower"
   .elseif Zero?
      PrintLine "equal"
   .else
      PrintLine "higher"
   .endif

For Fcmp xmm0, FP10(123.1), low the result would be "equal".
Title: Re: MasmBasic
Post by: jj2007 on March 17, 2012, 12:16:47 AM
Update 17 March (attached here (http://www.masm32.com/board/index.php?topic=12460)):

- SendControlKey hWin, VK_xxx: send e.g. a paste key to Notepad
- [Set]HtmlClip$ handles the format used by Microsoft Office as well as Thunderbird and many others
- GetFiles companions: GfSize, GfDate$, GfTime$, GfAgeHours, GfAgeMinutes, GfAgeMs return file properties:

include \masm32\MasmBasic\MasmBasic.inc   ; download (http://www.masm32.com/board/index.php?topic=12460)
   Init
   GetFiles *.asm   ; get all sources in the current folder and its subfolders
   xchg eax, ecx   ; save #files
   xor edi, edi      ; counter for the filter
   For_ ebx=0 To ecx-1
      .if GfAgeHours(ebx)<=24   ; pick your latest code
         call PrintFileInfo
      .endif
   Next
   Print Str$("\n%i files younger than 24 hours\n", edi)

   GetFiles *.hlp|*.exe   ; help files or executables
   xchg eax, ecx   ; save #files
   xor edi, edi      ; counter for the filter
   For_ ebx=0 To ecx-1
      .if !Instr_(7, GfDate$(ebx), "20")   ; pre-2000 - your date format might differ
         call PrintFileInfo
      .endif
   Next
   Print Str$("\n%i files from the previous millennium", edi)
   Inkey CrLf$, "ok"
   Exit
PrintFileInfo proc
  inc edi
  mov esi, Cat$(Files$(ebx)+Space$(20))   ; we simulate LSET
  Print Str$("\n#%i ", ebx+1), GfDate$(ebx), ", ", GfTime$(ebx), Spc2$
  Print Mid$(esi, Rinstr(esi, "\")+1, 20)
  Print Str$(" age: %ih", GfAgeHours(ebx))
;  Print Str$(" = %im", GfAgeMinutes(ebx))   ; age can be expressed in
;  Print Str$(" = %ims", GfAgeMs(ebx))   ; hours, minutes, milliseconds
  Print Str$(", size=%i", edx::GfSize(ebx))
  ret
PrintFileInfo endp

end start

Enjoy :U
Title: Re: MasmBasic
Post by: jj2007 on March 17, 2012, 11:05:23 PM
Update 18 March (attached here (http://www.masm32.com/board/index.php?topic=12460)):

Just a stupid little bugfix: Fcmp whatever, MyDwordInMemory would load the dword as Real4. All other operands (reg32, xmm, qword, real4/8/10) worked already fine in the 17 March version.
Title: Re: MasmBasic
Post by: jj2007 on March 27, 2012, 10:05:00 PM
Update 28 March (attached here (http://www.masm32.com/board/index.php?topic=12460)):

- Insert and Delete accept a counter as second arg:
      Insert L$(100)   ; insert one empty string at index 100
      Let L$(100)="brandnew"
      Delete L$(1100)   ; delete the string
      mov ecx, 1000   ; just a counter
      Insert L$(0), ecx   ; insert ecx items
      Delete L$(1111), ecx   ; delete ecx at another position

- the string engine has a new feature: when accessing the n+1th element of an array, automatic expansion is triggered. Example:

include \masm32\MasmBasic\MasmBasic.inc   ; download (http://www.masm32.com/board/index.php?topic=12460)
   Init
   Dim My$(1)   ; a string array with 2 elements, 0 and 1
   ; Let My$(3)="This would trigger a runtime error"   ; no good
   For_ n=0 To 9
      Let My$(n)=Str$("This is string #%i", n)   ; but incremental assignments are OK
   Next
   For_ n=0 To 9
      PrintLine My$(n)
   Next
   Inkey "OK"
   Exit
end start
Title: Re: MasmBasic
Post by: jj2007 on April 27, 2012, 10:46:37 PM
Update 28 April (download from top of thread (http://www.masm32.com/board/index.php?topic=12460)). Major changes:

- GetFiles got a companion, SortFiles:

include \masm32\MasmBasic\MasmBasic.inc   ; download (http://www.masm32.com/board/index.php?topic=12460)
   Init
   Print "Oldest files in examples folder:", CrLf$
   GetFiles \Masm32\Examples\*.asm
   AddFiles \Masm32\Examples\*.inc
   SortFiles date, asc   ; first arg can be name, size, date; second arg asc or desc or blank=descending
   For_ ebx=0 To Min(9, eax-1)
      PrintLine Str$(GfSize(ebx)), Tb$, GfDate$(ebx), Spc2$, GfTime$(ebx), Tb$, Files$(ebx)
   Next
   Inkey
   Exit
end start

Oldest files in examples folder:
1250    20.01.1999  08:35:56    \Masm32\Examples\exampl01\minimum\minimum.asm
6560    21.01.1999  03:38:26    \Masm32\Examples\exampl01\dll\loaddll\loaddll.asm
6792    21.01.1999  03:39:02    \Masm32\Examples\exampl01\dll\calldll\calldll.asm
13798   27.01.1999  15:31:32    \Masm32\Examples\exampl01\generic\generic.asm
6561    12.04.1999  15:45:34    \Masm32\Examples\exampl01\oldstyle\oldstyle.asm
2463    30.04.1999  03:19:40    \Masm32\Examples\exampl01\dll\tstdll.asm
9806    03.05.1999  04:49:12    \Masm32\Examples\exampl01\regkey\regkey.asm
2104    17.05.1999  05:02:50    \Masm32\Examples\exampl01\mdidemo\filedlgs.asm
969     17.05.1999  05:02:50    \Masm32\Examples\exampl01\mdidemo\statusbr.asm
2065    17.05.1999  05:02:50    \Masm32\Examples\exampl01\mdidemo\tbmacros.asm


- ArraySort and ArrayMinMax can now handle QWORD and REAL8 arrays

- ArraySort has become faster, and beats Masm32 nrQsort in typical situations, see this thread (http://www.masm32.com/board/index.php?topic=18765.msg158792#msg158792) (not to mention the horribly slow CRT version of QuickSort :bg)

The ultrafast algo is inspired by MarWin alias Marty Winkler's marvelous sorting algo tool (http://www.codingcrew.de/marty/win32asm.php#saia) - compliments to Germany :U


Enjoy :thumbu
Title: Re: MasmBasic
Post by: jj2007 on April 28, 2012, 06:43:18 PM
Addendum: The ArraySort macro has no option to set the sort order at runtime, but there is a "manual" workaround, see below. I attach the updated manual, including also docu of the SortFiles macro.

   ...
   ArraySort MyR4(-:123)      ; sort descending, first 123 elements only
   lea esi, KeyArr(0)      ; load start address of an array containing keys (e.g. original position)
   ArraySort MyR4(-), esi      ; sort Real4 array descending, keep key values with Real4 values
   ArraySort MyR4(+), KeyArr(), fill      ; use key array directly, fill with original unsorted order (0, 1, 2, ... n)
Rem   - returns number of sorted elements in eax
   - use for signed DWORD, signed QWORD, REAL4 and REAL8 arrays; for strings, see QSort
   - ArraySort sorts ascending if no - is found in the first argument. In case you need to determine the order based on
     a runtime parameter, you need to use the invoke syntax as follows:
      MbArrSort PROTO :DWORD, :DWORD, :DWORD, :DWORD
      invoke MbArrSort, ptr to first element, #elementsi, ptr to key array, mode
      with mode=size (4, 8) or (32 and real) or (64 and ascending) or (1 and MinMaxOnly) or (2 and fill the key)
   - uses a very fast algo inspired by Marwin's site (http://www.codingcrew.de/marty/win32asm.php#saia), often faster than QuickSort (and much faster than the crt qsort)
   - Real4 and Dword use the same algo; the only difference is that the Real4 variant applies an extra
     pass to invert the order of negative elements. Speedwise there is no measurable difference

Little example:
include \masm32\MasmBasic\MasmBasic.inc   ; download (http://www.masm32.com/board/index.php?topic=12460)
  Init
  StringToArray Clip$(), L$()   ; get something from the clipboard, e.g. from http://www.masm32.com/board/index.php?action=stats
  dec eax
  xchg eax, ebx         ; move linecount to permanent reg32
  Dim MyDw(ebx) As DWORD
  For_ ct=0 To ebx
   mov esi, L$(ct)
   .if Rinstr(esi, Tb$)   ; get rightmost tab char
      push edx
      inc eax
      mov MyDw(ct), Val(eax)
      pop ecx
      Let L$(ct)=Trim$(Left$(esi, ecx))
   .endif
  Next
  ArrayMinMax MyDw()
  xchg eax, ecx
  xchg ecx, edx   ; ascending sort...
  Print Str$("\nRange of values is %i to ", edx), Str$(ecx)
  Dim MyKey(ebx) As DWORD
  ArraySort MyDw(), MyKey(), fill   ; sort MyDw(), set reference to MyKey
  For_ ecx=0 To ebx
   Print Str$("\n#%i\t", ecx), Str$(MyDw(ecx)), Tb$, L$(MyKey(ecx))
  Next
  Inkey
  Exit debug
end start
Title: Re: MasmBasic
Post by: jj2007 on May 10, 2012, 11:21:49 PM
Update 11 May 2012: Error handling with Try/Catch/Finally

In its simplest form, the syntax for a full console app is as follows:

Quoteinclude \masm32\MasmBasic\MasmBasic.inc   ; download (http://www.masm32.com/board/index.php?topic=12460)
   Init tc   ; install the handler
  Try         ; set the start label
   xor ecx, ecx
   inc dword ptr [ecx]   ; you should go to jail for that, but we'll be kind
  Catch         ; set the end label
   Inkey "Incrementing 0 is illegal!!"
   Exit
   TryCatchEnd   ; activate the handler - must be last instruction before "end start"
end start

A more sophisticated example, a loop that ends up dividing by zero:

Quoteinclude \masm32\MasmBasic\MasmBasic.inc   ; download (http://www.masm32.com/board/index.php?topic=12460)
   Init tc   ; install the handler
  Try         ; set the start label
     mov ecx, 4
     .Repeat
      Print Str$("44444444/%i = ", ecx)
      mov eax, 44444444
      cdq
      div ecx
      PrintLine Str$(eax)
      dec ecx
   .Until Sign?
  Catch only   ; "only" signals skip if no problems
     mov eax, 31415926   ; ... otherwise, change your results here...
     PrintLine "undefined"   ; ... or issue a warning, etc.
  Finally
   .if LastEx(code)   ; we better give some extra info
        PrintLine CrLf$, "Ouch, we had an exception at ", CrLf$, "address", Tb$,\
        Hex$(LastEx(addr)), CrLf$, "code", Tb$, Hex$(LastEx(code)), CrLf$, Err$()
   .endif
   Inkey
   Exit
   TryCatchEnd   ; activate the handler - must be last instruction before "end start"
end start

Output:
44444444/4 = 11111111
44444444/3 = 14814814
44444444/2 = 22222222
44444444/1 = 44444444
44444444/0 = undefined

Ouch, we had an exception at
address 00401064
code    C0000094


Different languages use different syntax. I have tried to stay as close as possible to "natural" wording (and i don't like "Finally", but it seems to be recognised Visual Basic jargon... feedback and opinions welcome :bg)
Title: Re: MasmBasic
Post by: jj2007 on May 14, 2012, 02:55:21 PM
Quote from: AntariyIn MbTryCatch you're using EBX and ESI, but not preserving them (there is one path with return of EXCEPTION_CONTINUE_EXECUTION).

Thanks, Alex. It's corrected today (14 May, here (http://www.masm32.com/board/index.php?topic=12460)).

I also added a "descriptive text" option to SetErrLine:

  Try         ; set the start label
     mov ecx, 4
     .Repeat
      Print Str$("44444444/%i = ", ecx)
      mov eax, 44444444
      cdq
      SetErrLine "reason\tdiv ecx"
      div ecx
      PrintLine Str$(eax)
      dec ecx
   .Until Sign?
  Catch only   ; "only" signals skip if no problems
     mov eax, 31415926   ; ... otherwise, change your results here...
     PrintLine "undefined"   ; ... or issue a warning, etc.
  Finally         ; needed after "only"
   .if LastEx(code)   ; we better give some extra info
        PrintLine CrLf$, "We had an exception at ", CrLf$, "address", Tb$,\
        Hex$(LastEx(addr)), CrLf$, "code", Tb$, Hex$(LastEx(code)), CrLf$, LastEx(info)
   .endif

We had an exception at
address 00401092
code    C0000094
reason  div ecx


Full example attached.
Title: Re: MasmBasic
Post by: Antariy on May 16, 2012, 03:01:01 AM
Quote from: jj2007 on May 14, 2012, 02:55:21 PM
Thanks, Alex.

:thumbu


Incrementing [0] is illegal

44444444/4 = 11111111
44444444/3 = 14814814
44444444/2 = 22222222
44444444/1 = 44444444
44444444/0 = undefined

Ouch, we had an exception at
address 00401092
code    C0000094
reason  div ecx

Let's try again, outside the Try/Catch block??

Exception (line 35?):
Code    C0000005
EIP     00401174
Error   inc [0] failed


It is also possible to obtain a line number from a map file, not placing it into exe.
Need to specify /Zd switch to the ML when translating and /MAP /MAPINFO:LINES for LINK when building.
The section in resulting MAP file is named "Line numbers for"... and contains the correspondencies between source lines and code offset relative to start of the section. I.e., if code section (segment) starts at 401000, then just need to add this to offset from MAP to get resulting virtual address.
Title: Re: MasmBasic
Post by: jj2007 on May 18, 2012, 10:48:58 AM
Quote from: Antariy on May 16, 2012, 03:01:01 AM
Need to specify /Zd switch to the ML when translating and /MAP /MAPINFO:LINES for LINK when building.

Alex,

You are a source of inspiration :U

See \masm32\RichMasm\Res\SkelTryCatch.asc in the 18 May version (http://www.masm32.com/board/index.php?topic=12460). Open in RichMasm, hit F6, see the exception messages; quit and see how the editor jumps to the first line that triggered an exception :bg

You need ML.exe version 6.15 or JWasm, and the standard linker coming with the Masm32 SDK - see here (http://www.masm32.com/board/index.php?topic=18874.0) for more info.

Simple example:

Quoteinclude \masm32\MasmBasic\MasmBasic.inc   ; download (http://www.masm32.com/board/index.php?topic=12460)
   Init tc   ; install the try/catch handler
   ErrLines   ; blank or on means use them, off means don't
   xor ecx, ecx   ; you should go to jail for accessing address zero, but we'll be kind
   inc dword ptr [ecx]   ; RichMasm will select this line after exiting the program
   Inkey "Can you see this text?"   ; no, you can't... we have a non-continuable exception before ;-)
   Exit
   TryCatchEnd   ; activate the handler - must be last instruction before "end start"
end start

  OPT_Assembler   JWasm         ; only ml.exe 6.15 works ok (Hex$ may not look good in JWasm, ml 8+ don't do /Zd)
  OPT_DebugA   /Zd         ; generate info for mapinfo:lines
  OPT_DebugL   /map /mapinfo:lines      ; recent ml.exe and link.exe versions can't do that
  OPT_Linker   link         ; you need the Masm32 version, i.e. the old 1998 link.exe
Title: Re: MasmBasic
Post by: guga on May 20, 2012, 01:48:20 AM
Excelent work JJ  :U


One question...how do you managed to enable the hyperlinked text in a richedit control ? ( i mean the "Hi guga (http://guga.com)", instead of http://guga.com)
Do you have some small example of this ?

I tried to make a riechedit control works this way but it keeps showing the full url
Title: Re: MasmBasic
Post by: jj2007 on May 20, 2012, 02:16:52 AM
Hi Guga,

The trick is to disable EM_AUTOURLDETECT and then roll your own via CFM_LINK. Warning, it may cost you some sleepless night :wink
Title: Re: MasmBasic
Post by: guga on May 20, 2012, 03:14:24 AM
many tks..i´ll give a try

hmm...you mean using it with EM_SETEVENTMASK, EM_GETEVENTMASK and EM_AUTOURLDETECT ?
Title: Re: MasmBasic
Post by: guga on May 20, 2012, 05:20:24 AM
I´m confused...It is not working....

is disabling autourldetect realy necessary ?

what about using CFE_HIDDEN ?
I mean, i wonder if it may work if i grab somehow the string memory (the "url" that is surrounding the string), and through EN_LINK i hide only the url string somehow.

Is this c code usefull ?
http://www.tek-tips.com/viewthread.cfm?qid=317950
Title: Re: MasmBasic
Post by: dedndave on May 20, 2012, 05:59:59 AM
this might help...
http://www.codeproject.com/Articles/9196/Links-with-arbitrary-text-in-a-RichTextBox
when i read these code project articles, i find it very helpful to browse through the discussions at the bottom   :bg
Title: Re: MasmBasic
Post by: jj2007 on May 20, 2012, 09:31:06 AM
Quote from: guga on May 20, 2012, 05:20:24 AM
I´m confused...It is not working....
What do you expect after only one sleepless night? :green

Quote
is disabling autourldetect realy necessary ?

See Dave's link, under "Caveats"

Quote
what about using CFE_HIDDEN ?

Sounds interesting, but you would still have to see the link style for a piece of text, right?

Quote
Is this c code usefull ?
http://www.tek-tips.com/viewthread.cfm?qid=317950

That was 2005 - judge yourself:
Quoteok, for my life I have no idea what the problem is. ... I'll probably post this in it's own thread pretty soon here...

By the way, RichMasm supports several types of hyperlinks:
(http://www.webalice.it/jj2006/pics/LinksInMB.png)

1. plain http (it will ask)
2. open a local file (directly)
3. jump to internal anchor ("you need resources")
4. insert a file replacing the link
5. while hovering over a MB keyword (Print, Init, Recall, ...), the mouse cursor becomes a question mark. Right-click then to see help.

Source attached - it needs the path name.