The MASM Forum

General => The Campus => Topic started by: luciddreamer on January 25, 2021, 07:15:25 PM

Title: Hello World Question
Post by: luciddreamer on January 25, 2021, 07:15:25 PM
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") ?
Title: Re: Hello World Question
Post by: Vortex on January 25, 2021, 07:22:55 PM
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.
Title: Re: Hello World Question
Post by: luciddreamer on January 25, 2021, 07:28:03 PM
 :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?
Title: Re: Hello World Question
Post by: 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
Title: Re: Hello World Question
Post by: 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:
Title: Re: Hello World Question
Post by: daydreamer on January 25, 2021, 08:37:16 PM
Welcome luciddreamer
.386 is max cpu ,can be replaced with
.686
.XMM
to be able to use more modern mnemonics/opcodes
Title: Re: Hello World Question
Post by: luciddreamer on January 25, 2021, 09:30:19 PM
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?
Title: Re: Hello World Question
Post by: luciddreamer on January 25, 2021, 09:35:56 PM
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 :)
Title: Re: Hello World Question
Post by: luciddreamer on January 25, 2021, 09:40:04 PM
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?
Title: Re: Hello World Question
Post by: TimoVJL on January 25, 2021, 10:32:42 PM
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.
Title: Re: Hello World Question
Post by: Vortex on January 25, 2021, 10:36:14 PM
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

Title: Re: Hello World Question
Post by: luciddreamer on January 25, 2021, 11:46:01 PM
Played around with Assembly, what does ADDR operator do?
Title: Re: Hello World Question
Post by: TimoVJL on January 25, 2021, 11:54:39 PM
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
Title: Re: Hello World Question
Post by: jj2007 on January 26, 2021, 01:15:49 AM
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
Title: Re: Hello World Question
Post by: luciddreamer on January 26, 2021, 01:53:29 AM
I use Ghidra and IDA PRO to dissemble binaries, Pseudo C code gives me some idea how everything works in higher level.
Title: Re: Hello World Question
Post by: luciddreamer on January 26, 2021, 02:00:10 AM
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
Title: Re: Hello World Question
Post by: 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
Title: Re: Hello World Question
Post by: luciddreamer on January 26, 2021, 02:16:52 AM
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.
Title: Re: Hello World Question
Post by: Dan-TheStarman on February 12, 2021, 09:48:53 AM
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
Title: Re: Hello World Question
Post by: hutch-- on February 12, 2021, 10:17:00 AM
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