1

I learned the concepts of Assembly language programming through "MIPS Assembly". I wrote a couple of programs like fibonacci, stack related stuff and so on. Now I want to get to the next level, 32bit Windows assembly for the .386 instruction set.

This is what I already have.

.386
.model flat, stdcall
.stack 4096
ExitProcess PROTO, deExitCode:DWORD

.data
msg db "Hello, World!", 0

.code

main PROC


    INVOKE ExitProcess, 0
main ENDP
END main

But how can I call a system function like print_string? I am really overwhelmed. I tried a couple of related SO answers but they use NASM and so it did not work for me.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
John Doe
  • 415
  • 1
  • 4
  • 15
  • 1
    SO has a [tag:masm] tag; try searching that. Or google search something like `site:stackoverflow.com masm hello world`. Or there's a MASM answer on [How to write hello world in assembler under Windows?](https://stackoverflow.com/a/1032422) – Peter Cordes Nov 04 '20 at 00:01

2 Answers2

1

This is a basic WIN32 console mode HelloWorld! ASM program, to be compiled with MASM 615, and runs on my Win10,64-bit system. You can consult the author's website for any changes (if there's any) to make it compile with VS2019 etc.

; 32-Bit Intel Protected Mode Programming
; KIP IRVINE Assembly Language for x86 / Intel-Based Computers. 
;

.386
.model flat,stdcall
.stack 4096

; DEFINE/DECLARE necessary WIN32 constants, functions etc.
;------------------------------------------------------------
; Win32 Console handles
STD_OUTPUT_HANDLE EQU -11       ; predefined Win API constant


; ALIAS  : The following Win32 API functions have an
; extra "A" at the end of their name, 
; so they are redefined here with text macros:
WriteConsole EQU <WriteConsoleA>


;                   FUNCTION PROTOTYPES
; -------------------------------------------------------------
ExitProcess PROTO,          ; exit program
    dwExitCode:DWORD        ; return code


GetStdHandle PROTO,         ; get standard handle
    nStdHandle:DWORD        ; type of console handle


WriteConsole PROTO,                 ; write a buffer to the console
    handle:DWORD,                   ; output handle
    lpBuffer:PTR BYTE,              ; pointer to buffer
    nNumberOfBytesToWrite:DWORD,    ; size of buffer
    lpNumberOfBytesWritten:PTR DWORD,   ; num bytes written
    lpReserved:DWORD                    ; (not used)

; User Defined Data Section
; ---------------------------------------------------------------
.data
mesg1               BYTE    "Hello world!",0dh,0ah,0
sizeMesg1           = ($-mesg1)-1       ; ex-cluding the sign bit
BytesWritten        DWORD   0
ConsoleOutHandle    DWORD   0

.code
main proc
    
    ; Get Standart Output Handle
    INVOKE GetStdHandle, STD_OUTPUT_HANDLE  ; Get a handle to console SCREEN.
    mov ConsoleOutHandle, eax
    
    ; Write Message to the Handle => CONSOLE
    INVOKE WriteConsole, ConsoleOutHandle, ADDR mesg1, (LENGTHOF mesg1)-1, ADDR BytesWritten, 0
    
    
    invoke ExitProcess,0
main endp
;-------------------------------------------------------------------

end main
Fat32
  • 136
  • 3
1

Example masm code that enables instruction and calls printf with a pointer to the string. The legacy library is specified because starting with Visual Studio 2015, printf and scanf are now inlined when compiling a C source file, while assembly will need to use the legacy library. If a program consists of both C and assembly source files, the legacy library is not needed.

A custom build step will probably be needed. Create an empty Windows Console project, add the assembly source file, right click on the assembly source file name, then properties, set excluded from build to no, then set custom build step parameters:

For debug build:

command line: ml /c /Zi /Fo$(OutDir)\example.obj example.asm
output file:  $(OutDir)\example.obj

For release build the Zi is not needed:

command line: ml /c /Fo$(OutDir)\example.obj example.asm
output file:  $(OutDir)\example.obj

Example source code:

        .686p                   ;enable instructions
        .xmm                    ;enable instructions
        .model flat,c           ;use C naming convention (stdcall is default)

;       include C libraries
        includelib      msvcrtd
        includelib      oldnames
        includelib      legacy_stdio_definitions.lib    ;for scanf, printf, ...

        .data                   ;initialized data
pfstr   db      "Hello world!",0dh,0ah,0
        .data?                  ;uinitialized data
        .stack  4096            ;stack (optional, linker will default)

        .code                   ;code 
        extrn   printf:near
        public  main

main    proc

        push    offset pfstr
        call    printf
        add     sp,4 

        xor     eax,eax
        ret
main    endp

        end

For 64 bit builds, use ml64.exe instead of ml.exe.

rcgldr
  • 27,407
  • 3
  • 36
  • 61