Projects > MasmBasic & the RichMasm IDE
Dual 64- and 32-bit Assembly
jj2007:
Attached the installer of the JBasic library. JBasic sources assemble either in 64- or in 32-bit, depending on the OPT_64 setting:
--- Code: ---include \Masm32\MasmBasic\Res\JBasic.inc ; ## builds in 32- or 64-bit mode with UAsm, ML, AsmC ##
Init ; OPT_64 0 ; put 0 for 32 bit, 1 for 64 bit assembly
PrintLine Chr$("This program was assembled with ", @AsmUsed$(1), " in ", jbit$, "-bit format.")
EndOfCode
--- End code ---
With different OPT_64 settings and assemblers:
--- Code: ---This program was assembled with UAsm64 in 64-bit format.
This program was assembled with ml64 in 64-bit format.
This program was assembled with ml in 32-bit format.
This program was assembled with AsmC in 32-bit format.
This program was assembled with AsmC in 64-bit format.
This program was assembled with UAsm64 in 32-bit format.
--- End code ---
Currently, about 70 macros are available, as a subset of the almost 500 MasmBasic macros (e.g. Open, Print, FileRead$(), Chr$, Hex$, Str$, Len...). Inter alia, the deb macro can be used in 64-bit code.
System requirements:
- a 64-bit flavour of Windows
- the Masm32 SDK
- UAsm64
To use AsmC instead of UAsm64, change the *.bat files accordingly.
It is possible (but not recommended) to use ML64. High level syntax such as .if ... .else ... .endif will not work with the 64-bit version of MASM.
Please report any installation or usage problems below this post.
jj2007:
A simple program that writes some strings to a file, then opens the file for input and prints the content to the console. Afterwards, the first 1000 bytes of \Masm32\include\Windows.inc are shown in a MessageBox:
--- Code: ---include \Masm32\MasmBasic\Res\JBasic.inc ; ## builds in 32- or 64-bit mode with UAsm, ML, AsmC ##
Init ; OPT_64 1 ; 0 for 32 bit, 1 for 64 bit assembly
PrintLine Chr$("This program was assembled with ", @AsmUsed$(1), " in ", jbit$, "-bit format.")
Open "O", #1, "TestO.txt"
Print "Hello world", CrLf$, "take it easy", Str$(" \nThe file handle is %i\n\n", rax)
Print #1, "hello world", CrLf$, "written to a file", Str$(" \nThe value of rax is %i", rax)
Close #1
PrintLine "The content of the file: ", CrLf$, "[", FileRead$("TestO.txt"), "]"
Kill "TestO.txt" ; cleanup
mov rsi, FileRead$("\Masm32\include\Windows.inc")
mov byte ptr [rsi+1000], 0 ; don't overload the MessageBox ;-)
MsgBox 0, rsi, "Hi", MB_OK
EndOfCode
--- End code ---
Output (without MsgBox):
--- Code: ---This program was assembled with UAsm64 in 64-bit format.
Hello world
take it easy
The file handle is 60
The content of the file:
[hello world
written to a file
The value of rax is 1]
--- End code ---
Source and executables attached.
jj2007:
A variant of the previous example, with a Mid$() macro:
--- Code: ---include \Masm32\MasmBasic\Res\JBasic.inc
Mid$ MACRO pString, mStart, mBytes
mov rdx, repargA(pString)
mov rax, mStart
add rax, rdx
mov rdx, mBytes
and byte ptr [rax+rdx], 0
EXITM <rax>
ENDM
Init ; OPT_64 1 ; 0 for 32 bit, 1 for 64 bit assembly
PrintLine Chr$("This program was assembled with ", @AsmUsed$(1), " in ", jbit$, "-bit format.")
Open "A", #1, "TestO.txt" ; append to existing file
Print "Hello world", CrLf$, "take it easy", Str$(" \nThe file handle is %i\n\n", rax)
Print #1, "Strings", CrLf$, "written to a file:", CrLf$, "the entry point is at ", Hex$(offset start), CrLf$
Close #1
PrintLine "The content of the file: ", CrLf$, "[", FileRead$("TestO.txt"), "]"
MsgBox 0, Mid$(FileRead$("\Masm32\include\Windows.inc"), 92, 1036), "Hi", MB_OK
EndOfCode
--- End code ---
Source and executables attached. You may note that the 64-bit executable is somewhat larger (4096 bytes) than the 32-bit exe (2560 bytes).
LiaoMi:
Hi jj2007,
what are the differences from MasmBasic, without taking into account the x64 support :icon_idea:
jj2007:
--- Quote from: LiaoMi on March 30, 2021, 07:33:14 PM ---Hi jj2007,
what are the differences from MasmBasic, without taking into account the x64 support :icon_idea:
--- End quote ---
MasmBasic has over 700 macros, of which 488 are documented. Inter alia, it has strong support for string and numeric arrays (see Recall, Insert & Delete, QSort, etc). Mainly because of the array and string engines, a "Hello World" in MasmBasic is 27.5kBytes, far too much for the taste of the average assembly programmer ;-)
In contrast, JBasic just offers some basic services, such as reading a file into memory, printing, input, etc.; the executables are tiny - for example, 4608 bytes for a full-fledged 64-bit Gui application with a menu and an edit control, see below. However, it does have the deb macro, which I consider essential for any coding, and which IMHO can speed up the learning of a novice.
And it comes with a simple 100kB installer that gives you jinvoke access to 13,000+ WinAPI calls... isn't that cute? :tongue:
Btw jinvoke does count and check arguments, so a n00b fighting with CreateWindowEx may see forced error: ## too many arguments for CreateWindowEx ## or forced error: ## not enough arguments for CreateWindowEx ## (I strongly believe in holding the hot little hands of n00bs; google site:masm32.com "hot little" in case you don't get the joke)
This is the Gui demo (see ?:\Masm32\MasmBasic\Res\SkelDualGUI.asm). It assembles fine with UAsm, AsmC and ML64:
--- Code: ---include \Masm32\MasmBasic\Res\JBasic.inc ; hit F6 to build this program
wcx WNDCLASSEX <WNDCLASSEX, CS_HREDRAW or CS_VREDRAW or CS_OWNDC, WndProc, 0, 0, 1, 2, 3, COLOR_BTNFACE+1, 0, txClass, SIZE_P>
txClass db "JBasicGUI", 0 ; class name, will be registered below
lastMenu DWORD ? ; OPT_64 1 ; 0=32-bit, 1=64-bit assembly
hEdit SIZE_P ? ; the handle to the edit control is a pointer, 32 or 64 bits wide
Init
WinMain proc
LOCAL msg:MSG
wc equ [rbx.WNDCLASSEX] ; we use an equate for better readability
lea rbx, wcx
mov wc.hInstance, rv(GetModuleHandle, 0)
mov wc.hIcon, rv(LoadIcon, rax, IDI_APPLICATION) ; click on the first Rsrc bookmark to change the icon
mov wc.hIconSm, rax ; the rv macro returns results in rax
mov wc.hCursor, rv(LoadCursor, NULL, IDC_ARROW) ; get a cursor
jinvoke RegisterClassEx, rbx ; the window class needs to be registered
wsStyle=WS_OVERLAPPEDWINDOW or WS_VISIBLE or WS_CLIPCHILDREN
jinvoke CreateWindowEx, 0, wc.lpszClassName, Chr$("Hello World"), wsStyle, 300+320*@64, 127, 300, 200, NULL, rv(LoadMenu, wc.hInstance, 100), wc.hInstance, NULL
msgLoop: jinvoke TranslateMessage, addr msg ; translates virtual-key messages into character messages
jinvoke DispatchMessage, addr msg ; dispatches a message to a window procedure
jinvoke GetMessage, addr msg, 0, 0, 0 ; retrieve a message from the queue, and return a BOOL
mcs inc eax : shr eax, 1 : jne msgLoop ; quit if GetMessage returned 0 (exit OK) or -1 (error)
jinvoke ExitProcess, msg.wParam
WinMain endp
WndProc proc <cb cs> uses rsi rdi rbx hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
LOCAL ps:PAINTSTRUCT, MyR4:REAL4
Switch_ uMsg
Case_ WM_CREATE
reStyle=WS_VISIBLE or WS_CHILD or ES_MULTILINE or WS_VSCROLL or WS_HSCROLL or ES_AUTOHSCROLL or ES_AUTOVSCROLL or ES_NOHIDESEL
jinvoke LoadLibrary, Chr$("RichEd20") ; we want to add a RichEdit control
ID_EDIT=111
jinvoke CreateWindowEx, WS_EX_CLIENTEDGE, Chr$("RichEdit20A"), NULL, reStyle, 0, 0, 1, 1, hWnd, ID_EDIT, wcx.hInstance, NULL
mov hEdit, rax ; you may need this global variable for further processing
xchg rax, rbx ; use a persistent register for the handle
and MyR4, 0 ; just for fun:
jinvoke SendMessage, rbx, WM_SETTEXT, 0, MyR4 ; ** Warning, line 35: passing a REAL4 may not work **
jinvoke SendMessage, rbx, EM_SETTARGETDEVICE, 0, 0 ; word wrap on
jinvoke SendMessage, rbx, EM_EXLIMITTEXT, 0, -1 ; no limit
jinvoke SendMessage, rbx, WM_SETFONT, rv(GetStockObject, ANSI_FIXED_FONT), 0
jinvoke SetWindowText, rbx, Str$(Chr$("This template was built with", 13, 10, @AsmUsed$(1), " in %i-bit mode", 13, 10), jBits)
Case_ WM_KEYDOWN
cmp wParam, VK_ESCAPE
jne @F
forceClose: jinvoke SendMessage, hWnd, WM_CLOSE, 0, 0
@@:
Case_ WM_COMMAND
movsx eax, word ptr wParam
mov lastMenu, eax
jinvoke InvalidateRect, hWnd, 0, 1
cmp word ptr wParam, 106
je forceClose
Case_ WM_PAINT
jinvoke BeginPaint, hWnd, addr ps
xchg rax, rsi
PtDC equ rsi
jinvoke SetTextColor, PtDC, RgbCol(160, 0, 0)
cmp lastMenu, 107
jne @F
jinvoke SetBkColor, PtDC, RgbCol(255, 255, 240)
jinvoke TextOut, PtDC, 7, 2, Str$(Chr$("Assembled with ", @AsmUsed$(1), " in %i-bit mode", 13, 10), jBits), s$Len
jmp EndPt
@@: jinvoke SetBkColor, PtDC, RgbCol(204, 255, 240)
jinvoke TextOut, PtDC, 7, 2, Str$("Command or menu clicked: %i", lastMenu), s$Len ; Str$() and Hex$() return a special length variable s$Len
EndPt: jinvoke EndPaint, hWnd, addr ps
Case_ WM_SIZE ; adjust shape of edit control to main window
movzx eax, word ptr lParam ; width of client area
movzx edx, word ptr lParam+2 ; height
sub eax, 17 ; these 32-bit instructions sign-extend the upper 32 bits
sub edx, 37 ; of the 64-bit registers and are one byte shorter
jinvoke MoveWindow, hEdit, 7, 30, rax, rdx, 1
Case_ WM_DESTROY
jinvoke PostQuitMessage, NULL ; quit after WM_CLOSE
Endsw_
jinvoke DefWindowProc, hWnd, uMsg, wParam, lParam ; default processing
ret
WndProc endp
EndOfCode
--- End code ---
Current JBasic macros:
Chr$
FP4
FP8
FP10
CodeSize
wMsgBox
RgbCol
MsgBox
Hex$
Str$
Input$
Len
wLen
Val
PrintLine
Inkey
Print
Open
Close
Kill
FileRead$
@AsmUsed$
ComCtl32$
nops
mPush
jinvoke
void
Err$
deb
Init
j@end
Cls
SetProto
_Regs
Switch_
Case_
Default_
Endsw_
CL$
Oword16
PushX
PopX
mcs
Switch_
Case_
Default_
Endsw_
Link$
Rand64
Rand
GuidFromString
Navigation
[0] Message Index
[#] Next page
Go to full version