News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Console Hello world prog link error !

Started by AssemblyBeginner, March 10, 2015, 07:09:37 AM

Previous topic - Next topic

AssemblyBeginner

Hi all,

I have obtained the following code from this forum :

include \masm32\include\masm32rt.inc

.data
HelloWorld db "Hello World!",13,10,0
.code
start:
invoke StdOut, addr HelloWorld
inkey "Press a key to continue ..."


invoke ExitProcess, 0
end start



When I BuildAll with qeditor I get the following link error message :

LINK : fatal error LNK1104: cannot open file "stdOut.exe"

Is this due to a MASM32 installation problem ?

hutch--

See if the libraries built correctly. If something in you OS settings or AV scanner interferes, you may not have a valid library that contains StdOut. Go to the m32lib directory and run MAKE.BAT and watch if there are any errors, there should be none. If you are getting build errors, then something in your OS or AV settings is stopping the build from working.

GoneFishing

More details , please :
Where's stdOut.asm located? How do you open it ?.. maybe by drag'n'drop?
Try Console build

dedndave

Quote from: AssemblyBeginner on March 10, 2015, 07:09:37 AM
LINK : fatal error LNK1104: cannot open file "stdOut.exe"

it appears that you have an instance of the EXE already running
windows prevents alteration of exe files during program execution

use the task manager to make sure all previous instances of the program have been terminated
then, try assembling it again

AssemblyBeginner

Thanks everyone ?

StdOut is the name I gave to the asm file ... I gues, I should have given it a different name to avoid confusion

As kindly, suggested by Vertogra, 'Console build' soved the problem :)

Again, thank you for your help

AssemblyBeginner

As a side note , what is the role of 13, 10  in the following code line ?
HelloWorld db "Hello World!",13,10,0

I thought a byte string declaration in asm was only followed by a Null (0) character

hutch--

t places a CRLF after the string so that the console cursor finished on the next line.

AssemblyBeginner

Quote from: hutch-- on March 10, 2015, 10:20:10 AM
t places a CRLF after the string so that the console cursor finished on the next line.
Thank you hutch

AssemblyBeginner

In the previous code , I used : 'invoke StdOut, addr HelloWorld' instead of using offset as in the following working snippet .. however the two versions (ie: addr and offset) seem to work in the same way.

include \masm32\include\masm32rt.inc

.data
HelloWorld db "Hello World!",13,10,0
.code
start:
invoke StdOut, offset HelloWorld
inkey "Press a key to continue ..."


invoke ExitProcess, 0
end start


I am curious to know he difference between the two if any

Regards.

dedndave

for global data (data or data? section), i would use OFFSET

ADDR was intended for use with INVOKE on local variables
if you use ADDR and the assembler needs OFFSET, it will substitute

using the intended specifier makes code a little easier to read, though

hutch--

Its a very useful distinction to understand, an OFFSET is an absolute address from the start of an executable and this is generally why its used in both initialised data (data with content) and uninitialised data (allocated space). The ADDR notation is a bit more generalised in that it means an ADDRESS which can be either in the data sections OR a stack address, the stack address being dynamic where the data sections are static.

As Dave mentioned you use ADDR with the INVOKE notation as it makes your code easier for you to read. If you are loading a data section address into a register for example you would use the following.

mov eax, OFFSET mydata

Where "mydata" is the address of the data you want from either of the data sections. If you have a look at a disassembly of the code you will find that the mov eax you wrote has a direct offset as the source which is the location of the data in the respective data section.

dedndave

neither Hutch nor i gave really good explanations of what goes on with ADDR

consider the following example:

    INCLUDE     \masm32\include\masm32rt.inc

;###########################################################################

SomeFunc PROTO :HWND,:DWORD

;###########################################################################

        .DATA

;initialized data goes here

;***************************************************************************

        .DATA?

;uninitialized data goes here

;###########################################################################

        .CODE

;***************************************************************************

main    PROC

    INVOKE  SomeFunc,0,1

    inkey
    exit

main    ENDP

;***************************************************************************

SomeFunc PROC USES EBX ESI EDI hWnd:HWND,dwArg2:DWORD

;---------------------------

    LOCAL   dwLocal1      :DWORD
    LOCAL   rcLocal2      :RECT
    LOCAL   abLocal3[24]  :BYTE

;---------------------------

;some code here

    INVOKE  GetClientRect,hWnd,addr rcLocal2

;some more code here

    lea     edx,abLocal3

;some more code here

    mov     eax,dwArg2
    imul    eax,5
    mov     dwLocal1,eax

;some more code here

    ret

SomeFunc ENDP

;###########################################################################

    END     main


this is a disection of the code that is actually generated by the assembler....

;this is the code that is generated for the "INVOKE SomeFunc,0,1" line

00401000:  push    1                                   ;second argument passed in INVOKE
00401002:  push    0                                   ;first argument passed in INVOKE
00401004:  call    00401029                            ;address of SomeFunc

;some code here generated for the "inkey" macro expansion (not shown for simplicity)

;this is the code generated for the "exit" macro expansion

:00401022  push    0                                   ;exit code
:00401024  call    kernel32.ExitProcess                ;ExitProcess API function

=========

;this is the code generated for the "SomeFunc" PROC

;-----------------------------------------------------------------------------

;stack frame initialization
;this is called the PROC "prologue" code, automatically generated by the assembler
;the PROC line has "USES EBX ESI EDI", as well as 2 DWORD arguments
;then, we allocate 44 bytes for local variables

;SomeFunc PROC USES EBX ESI EDI hWnd:HWND,dwArg2:DWORD

;    LOCAL   dwLocal1      :DWORD
;    LOCAL   rcLocal2      :RECT
;    LOCAL   abLocal3[24]  :BYTE

00401029:  push    ebp                              ;preserve EBP contents
0040102A:  mov     ebp,esp                          ;EBP = stack frame base pointer
0040102C:  add     esp,-44                          ;make room for our local variables (44 bytes total)
0040102F:  push    ebx                              ;preserve EBX contents
00401030:  push    esi                              ;preserve ESI contents
00401031:  push    edi                              ;preserve EDI contents

;so, our stack frame looks like this

;[EBP+12]    dwArg2
;[EBP+8]     hWnd
;[EBP+4]     RETurn address
;[EBP]       saved EBP contents
;[EBP-4]     dwLocal1, a DWORD
;[EBP-20]    rcLocal2, RECT structure (4 DWORD's)
;[EBP-44]    abLocal3, 24 byte array

;when you PUSH or POP during the course of your function code, the ESP register changes to point to the current "top of stack"
;however, the EBP register does not change - it always points to the same address on the stack

;-----------------------------------------------------------------------------

;this is the code generated for the "INVOKE GetClientRect,hWnd,addr rcLocal2" line of code
;notice that ADDR causes the assembler to generate an LEA instruction

00401032:  lea     eax,[ebp-20]                     ;EAX = ADDR rcLocal2
00401035:  push    eax
00401036:  push dword ptr [ebp+8]                   ;hWnd argument
00401039:  call    user32.GetClientRect             ;GetClientRect API function

;-----------------------------------------------------------------------------

;this is the code generated for the "lea edx,abLocal3" line of code

0040103E:  lea     edx,[ebp-44]                     ;EDX = ADDR abLocal3

;-----------------------------------------------------------------------------

;some example code to familiarize you with local variables

00401041:  mov     eax,[ebp+12]                     ;"mov eax,dwArg2"
00401044:  imul    eax,5                            ;"imul eax,5"
00401047:  mov     [ebp-4],eax                      ;"mov dwLocal1,eax"

;-----------------------------------------------------------------------------

;this is called the PROC "epilogue" code, automatically generated by the assembler whenever RET occurs

0040104A:  pop     edi                              ;restore EDI contents
0040104B:  pop     esi                              ;restore ESI contents
0040104C:  pop     ebx                              ;restore EBX contents
0040104D:  leave                                    ;same as, "MOV ESP,EBP", followed by, "POP EBP"
0040104E:  ret     8                                ;RETurn, and discard 2 DWORD arguments from the stack

AssemblyBeginner

Thanks for the answers provided regarding addr vs offset .. dedndave's answer is a bit difficult for me to disgest at this stage as I am an absolute beginner with asm but I'll study it nonetheless ... and I am sure it will come in handy at some point in my learning process

jj2007

Here is another minimalistic example:
include \masm32\include\masm32rt.inc

.code
MyTest proc title$
LOCAL msg$[100]:BYTE ; a local buffer
  int 3
  invoke lstrcpy, addr msg$, chr$("Hello")
  MsgBox 0, addr msg$, title$, MB_OK
  ret
MyTest endp

start: invoke MyTest, chr$("My title")
exit

end start


Under the hood:
00401000          Ú$  55                      push ebp                               ; NewWin32.00401000(guessed Arg1)
00401001          ³.  8BEC                    mov ebp, esp
00401003          ³.  83EC 64                 sub esp, 64
00401006          ³.  CC                      int3
00401007          ³.  68 00204000             push offset 00402000                   ; ÚSrc = "Hello"
0040100C          ³.  8D45 9C                 lea eax, [ebp-64]                      ; ³
0040100F          ³.  50                      push eax                               ; ³Dest
00401010          ³.  E8 2D000000             call <jmp.&kernel32.lstrcpyA>          ; ÀKERNEL32.lstrcpy
00401015          ³.  6A 00                   push 0                                 ; ÚType = MB_OK|MB_DEFBUTTON1|MB_APPLMODAL
00401017          ³.  FF75 08                 push dword ptr [ebp+8]                 ; ³Caption
0040101A          ³.  8D45 9C                 lea eax, [ebp-64]                      ; ³
0040101D          ³.  50                      push eax                               ; ³Text
0040101E          ³.  6A 00                   push 0                                 ; ³hOwner = NULL
00401020          ³.  E8 17000000             call <jmp.&user32.MessageBoxA>         ; ÀUSER32.MessageBoxA
00401025          ³.  8BE5                    mov esp, ebp
00401027          ³.  5D                      pop ebp
00401028          À.  C2 0400                 retn 4