Hello masm32, I am Stefan or call me with the username luciddreamer, I registered here for learning Assembly, as a kid born in 2000, I wasnt exposed to Assembly so here I am expanding my knowledge :)
My question was just also a verification that I am not a bot.
so I copy-pasted this code and ran it everything went fine until I ran the exe:
.386
.model flat, stdcall
option casemap :none
include \masm32\include\kernel32.inc
include \masm32\include\masm32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib
.data
message db "FOX", 0
.code
main:
invoke StdOut, addr message
invoke ExitProcess, 0
end main
How do I call system("pause") ?
Hello luciddreamer,
Here is an example for you :
.386
.model flat, stdcall
option casemap :none
include \masm32\include\kernel32.inc
include \masm32\include\masm32.inc
include \masm32\include\msvcrt.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\msvcrt.lib
.data
message db "FOX",0
func db "pause",0
.code
main:
invoke StdOut,ADDR message
invoke crt_system,ADDR func
invoke ExitProcess,0
END main
The fuınction named system is exported by msvcrt.dll. All the functions from msvcrt are prepended with the prefix crt_ to avoid naming clashes with some reserved Masm keywords.
:greenclp: worked!! what about new lines, I tried \n like in C/C++ but that didn't work, is there a macro for new line?
Hello,
You can try this one, the ASCII codes of CR and LF :
message db "FOX",13,10,0
Hi luciddreamer,
Erol alias Vortex showed you the crt way, here is another option - the Masm32 SDK macros:
include \masm32\include\masm32rt.inc
.code
start:
inkey "Hello Stefan"
exit
end start
The include line covers the most common libraries, including the crt. Open the file in Notepad to study what it does. You may also see here (https://www.jj2007.eu/Masm32_Tips_Tricks_and_Traps.htm) some tips for starters. Welcome to the Forum :thup:
Welcome luciddreamer
.386 is max cpu ,can be replaced with
.686
.XMM
to be able to use more modern mnemonics/opcodes
Quote from: Vortex on January 25, 2021, 07:43:15 PM
Hello,
You can try this one, the ASCII codes of CR and LF :
message db "FOX",13,10,0
Import names for msvcrt.dll
.rdata:00402064 ;
.rdata:00402064 off_402064 dd rva word_402088 ; DATA XREF: .rdata:__IMPORT_DESCRIPTOR_msvcrt↑o
.rdata:00402068 dd 0
.rdata:0040206C word_40206C dw 9Bh ; DATA XREF: .rdata:0040205C↑o
.rdata:0040206E db 'ExitProcess',0
.rdata:0040207A aKernel32Dll db 'kernel32.dll',0 ; DATA XREF: .rdata:00402024↑o
.rdata:00402087 align 4
.rdata:00402088 word_402088 dw 2B0h ; DATA XREF: .rdata:off_402064↑o
.rdata:0040208A db 'system',0
.rdata:00402091 align 2
.rdata:00402092 aMsvcrtDll db 'msvcrt.dll',0 ; DATA XREF: .rdata:00402038↑o
.rdata:0040209D align 2
.rdata:0040209E word_40209E dw 16Ah ; DATA XREF: .rdata:00402058↑o
.rdata:004020A0 db 'GetStdHandle',0
.rdata:004020AD align 2
.rdata:004020AE word_4020AE dw 2F7h ; DATA XREF: .rdata:off_402054↑o
.rdata:004020B0 db 'WriteFile',0
.rdata:004020BA align 1000h
.rdata:004020BA _rdata ends
Why does it use writefile?
Quote from: jj2007 on January 25, 2021, 08:14:37 PM
Hi luciddreamer,
Erol alias Vortex showed you the crt way, here is another option - the Masm32 SDK macros:
include \masm32\include\masm32rt.inc
.code
start:
inkey "Hello Stefan"
exit
end start
The include line covers the most common libraries, including the crt. Open the file in Notepad to study what it does. You may also see here (https://www.jj2007.eu/Masm32_Tips_Tricks_and_Traps.htm) some tips for starters. Welcome to the Forum :thup:
Thank you :)
Quote from: jj2007 on January 25, 2021, 08:14:37 PM
Hi luciddreamer,
Erol alias Vortex showed you the crt way, here is another option - the Masm32 SDK macros:
include \masm32\include\masm32rt.inc
.code
start:
inkey "Hello Stefan"
exit
end start
The include line covers the most common libraries, including the crt. Open the file in Notepad to study what it does. You may also see here (https://www.jj2007.eu/Masm32_Tips_Tricks_and_Traps.htm) some tips for starters. Welcome to the Forum :thup:
I ran the code and disassemble it to see how does it gets compiled
Using masm macros I get Pseudo C structure like this:
void __stdcall __noreturn start(int a1)
{
sub_401020(aHelloStefan);
sub_401060();
sub_401020(asc_40300D);
ExitProcess(0);
}
With the crt way I get this:
void __noreturn start()
{
sub_401028(aHelloStefan);
system(Command);
ExitProcess(0);
}
Why are there extra functions?
Quote from: luciddreamer on January 25, 2021, 09:30:19 PM
Why does it use writefile?
WriteFile and WriteConsole are Windows API functions.
You can use puts or printf from msvcrt.dll for printing too.
Hi luciddreamer,
Reading \masm32\macros\macros.asm :
;; ------------------------------------------------------
;; display user defined text, default text or none if
;; NULL is specified and wait for a keystroke to continue
;; ------------------------------------------------------
inkey MACRO user_text:VARARG
IFDIF <user_text>,<NULL> ;; if user text not "NULL"
IFNB <user_text> ;; if user text not blank
print user_text ;; print user defined text
ELSE ;; else
print "Press any key to continue ..." ;; print default text
ENDIF
ENDIF
call wait_key
print chr$(13,10)
ENDM
;; ---------------------------------------------------
;; wait for a keystroke and return its scancode in EAX
;; ---------------------------------------------------
getkey MACRO
call ret_key
ENDM
Played around with Assembly, what does ADDR operator do?
Quote from: luciddreamer on January 25, 2021, 11:46:01 PM
Played around with Assembly, what does ADDR operator do?
gives ADDRESS of variable, not value
Quote from: luciddreamer on January 25, 2021, 09:40:04 PMI ran the code and disassemble it to see how does it gets compiled
Using masm macros I get Pseudo C structure like this:
...
Why are there extra functions?
How did you get these "pseudo C structures"? They don't resemble Assembly. Here is what you get using OllyDbg (http://www.ollydbg.de/version2.html):
Address Hex dump Command Comments
<ModuleEntryPo Ú$ 68 00304000 push offset ??0019 ; ÚArg1 = ASCII "Hello Stefan"
00401005 ³. E8 16000000 call StdOut ; ÀNewMasm32.StdOut
0040100A ³. E8 51000000 call wait_key
0040100F ³. 68 0D304000 push offset ??001F ; ÚArg1 = ASCII CR,LF <<<<<<< why???
00401014 ³. E8 07000000 call StdOut ; ÀNewMasm32.StdOut
00401019 ³. 6A 00 push 0 ; ÚExitCode = 0
0040101B À. E8 E2000000 call ExitProcess ; ÀKERNEL32.ExitProcess
StdOut Ú$ 55 push ebp ; NewMasm32.StdOut(guessed Arg1)
00401021 ³. 8BEC mov ebp, esp
00401023 ³. 83C4 F4 add esp, -0C
00401026 ³. 6A F5 push -0B ; ÚStdHandle = STD_OUTPUT_HANDLE
00401028 ³. E8 DB000000 call GetStdHandle ; ÀKERNEL32.GetStdHandle
0040102D ³. 8945 FC mov [ebp-4], eax
00401030 ³. FF75 08 push dword ptr [ebp+8] ; ÚArg1 => [Arg1]
00401033 ³. E8 58000000 call StrLen ; ÀNewMasm32.StrLen
00401038 ³. 8945 F4 mov [ebp-0C], eax
0040103B ³. 6A 00 push 0 ; ÚpOverlapped = NULL
0040103D ³. 8D45 F8 lea eax, [ebp-8] ; ³
00401040 ³. 50 push eax ; ³pBytesWritten => offset LOCAL.2
00401041 ³. FF75 F4 push dword ptr [ebp-0C] ; ³Size => [LOCAL.3]
00401044 ³. FF75 08 push dword ptr [ebp+8] ; ³Buffer => [Arg1]
00401047 ³. FF75 FC push dword ptr [ebp-4] ; ³hFile => [LOCAL.1]
0040104A ³. E8 BF000000 call WriteFile ; ÀKERNEL32.WriteFile
0040104F ³. 8B45 F8 mov eax, [ebp-8]
00401052 ³. C9 leave
00401053 À. C2 0400 retn 4
wait_key $ 6A F6 push -0A ; ÚStdHandle = STD_INPUT_HANDLE
00401062 . E8 A1000000 call GetStdHandle ; ÀKERNEL32.GetStdHandle
00401067 . 50 push eax ; ÚhConsole
00401068 . E8 A7000000 call FlushConsoleInputBuffer ; ÀKERNEL32.FlushConsoleInputBuffer
0040106D > 6A 01 push 1 ; ÚTime = 1 ms
0040106F . E8 A6000000 call Sleep ; ÀKERNEL32.Sleep
00401074 . FF15 88304000 call near [<&msvcrt._kbhit>] ; [MSVCRT._kbhit
0040107A . 85C0 test eax, eax
0040107C . 74 EF je short 0040106D
0040107E . FF15 8C304000 call near [<&msvcrt._getch>] ; [MSVCRT._getch
00401084 . C3 retn
StdOut, wait_key and StrLen are functions of the Masm32 library, e.g. in \Masm32\m32lib\strlen.asm
print, inkey and exit are defined in \Masm32\macros\macros.asm
I use Ghidra and IDA PRO to dissemble binaries, Pseudo C code gives me some idea how everything works in higher level.
Example:
.386
option casemap :none
include \masm32\include\masm32rt.inc
.data
message db "Hello World",13,10,0
func db "pause",0
.code
main:
invoke StdOut,ADDR message
invoke crt_system,ADDR func
invoke ExitProcess,0
END main
PSEUDO C OUTPUT:
void __noreturn start()
{
sub_401020(aHelloWorld);
system(Command);
ExitProcess(0);
}
//sub_401020 code probably func to StdOut
DWORD __stdcall sub_401020(LPCVOID lpBuffer)
{
DWORD nNumberOfBytesToWrite; // [esp+0h] [ebp-Ch]
DWORD NumberOfBytesWritten; // [esp+4h] [ebp-8h] BYREF
HANDLE hFile; // [esp+8h] [ebp-4h]
hFile = GetStdHandle(0xFFFFFFF5);
nNumberOfBytesToWrite = sub_401060(lpBuffer);
WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, &NumberOfBytesWritten, 0);
return NumberOfBytesWritten;
}
Dissasembled Assembly
.text:00401000 public start
.text:00401000 start proc near
.text:00401000 push offset aHelloWorld ; "Hello World\r\n"
.text:00401005 call sub_401020
.text:0040100A push offset Command ; "pause"
.text:0040100F call ds:system
.text:00401015 add esp, 4
.text:00401018 push 0 ; uExitCode
.text:0040101A call ExitProcess
.text:0040101A start endp
Hi luciddreamer,
I would suggest you Agner Fog's objconv tool, it's a very good disassembler :
https://github.com/gitGNU/objconv
Quote from: Vortex on January 26, 2021, 02:09:17 AM
Hi luciddreamer,
I would suggest you Agner Fog's objconv tool, it's a very good disassembler :
https://github.com/gitGNU/objconv
Thank you, I will try it out now.
Quote from: luciddreamer on January 25, 2021, 11:46:01 PM
Played around with Assembly, what does ADDR operator do?
Hi luciddreamer,
I know I'm a bit late here, but with your background this may have been more helpful:
ADDR is essentially what you'd think of as
PTR; a POINTER to where some data can be found, or an "lp<name>" parameter in VS Windows code. I didn't realize that when I first started working with masm32 quite recently.
Apart from using "inkey" in console code, I wanted to say that it's pretty easy in masm32 (unlike Windows C++ etc. code) to just go ahead and use "MessageBox" or "MessageBoxA" functions that wait for someone to click on "OK" to close them! It's what the average Windows users expect these days anyway instead of a Command Prompt window. They'll be impressed, and you'll be like: It was so easy!
MB_OK button = "0"; same thing with an INFO icon = "40h". I did a very extensive "Hello" program in VS2019 using 64-bit Assembly code (the free Community edition requires you to use the C++ code that Viorel-1 supplied; here's URL:
https://docs.microsoft.com/en-us/answers/questions/169851/error-lnk2001-unresolved-external-symbol-winmaincr.html#answer-170564 (https://docs.microsoft.com/en-us/answers/questions/169851/error-lnk2001-unresolved-external-symbol-winmaincr.html#answer-170564)), but here's what the main section from there would become in masm32 (32-bit runs just fine under Windows 10 latest versions):
; Set up the parameters for calling the "MessageBoxA" Function (see:
; https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-messageboxa
; for more information on all the available parameters you could use):
invoke MessageBoxA, 0, addr winTxt, addr winCapt, INFOI
invoke ExitProcess, 0 ; Exit Code = "0".
With an "INFOI EQU 40h" earlier in program; or use "MB_OK" or "0" for just an "OK" button. You could also use a different exit code, or alternatively set it up for changing depending upon the code in a previous invoke (function call). The spaces are optional, "addr" makes it a pointer to the messages, and the most important thing of all: You don't need to keep track of any specific registers or what order they need to be in: You use the SAME ORDER they occur in the Microsoft API documentation; like you would for C++, etc.
Dan, TheStarman
There is another way to get the swing of the ADDR operator, you can directly code this in mnemonics (instructions).
LOCAL MyVar :DWORD ; the variable
LOCAL pVar :DWORD ; a pointer to it
lea eax, MyVar ; load the address of the memory operand into eax
mov pVar, eax ; store the address into a DWORD sized pointer