News:

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

Main Menu

Understanding The Shortest Valid x86 MASM Assembly Program

Started by greatbigfoot, January 27, 2020, 01:58:54 PM

Previous topic - Next topic

greatbigfoot

Hi,
I'm just starting to learn assembly (not school related, I just want to learn it) and I thought it best to start with the shortest possible program that didn't produce an error.

.model flat, stdcall
ExitProcess PROTO, dwExitCode: DWORD

.code
main:
  ; write your assembly code here

  INVOKE ExitProcess, 0
end main
I want to make sure I understand this properly, and this seems like the best place to get feedback on if I do. Thanks in advance!

.model flat, stdcall

.model
.model is a directive that allows the programmer to select one of 7 memory segmentation models, and the Calling Convention the assembler should use to interact with other programs.

flat
flat is one of the seven memory segmentation models supported by x86 processors. All seven memory segmentation models are: TINY, SMALL, COMPACT, MEDIUM, LARGE, HUGE and FLAT
However, FLAT is the only model used when writing 32 and 64 bit programs. The other models are only there now to provide backwards compatibility with 16 bit programs.
FLAT models store all of a programs segments (data, code, etc.) in a single section of memory. While the other options sub-divide the programs segments across multiple sections of memory.

stdcall
stdcall tells the assembler, that the programmer will be using Microsoft's WIN32 standard calling conventions for interacting with other programs, such as the operating system.

ExitProcess PROTO, dwExitCode: DWORD

ExitProcess
Is the label which will represent a function declaration in memory
Will instruct the assembler to call the WIN32 procedure _ExitProcess@4

PROTO
Is a directive telling the assembler that this line represents a function declaration

dwExitCode:
Is the name of the parameter variable that the function accepts

DWORD
Tells the assembler that any value passed to the function will be allocated 4 bytes (a word) of memory

Quote.code
.code is a directive, that tells the assembler that this section of the text file will store the actual code the CPU will execute

main:
main: is a label, that represents the starting location of the procedure called main in memory

; write your assembly code here
This is a comment

INVOKE ExitProcess, 0
INVOKE
Is a directive that tells the assembler to call a procedure
ExitProcess
Is a symbol representing the address of the start of the procedure being called in memory
0
Is a numeric literal, and will be used to tell the operating system to end the program, and that no errors were encountered
This whole line is translated by the Assembler into:
push        0 
call        _ExitProcess@4 (01041007h)
Which pushes 0 to the program's stack, and calls a windows function that end the program and all of its activities

end main
end
Is a masm directive, and tells the assembler that this marks the end of a module
main
is a label representing the module being ended

felipe

Quote from: greatbigfoot on January 27, 2020, 01:58:54 PM
However, FLAT is the only model used when writing 32 and 64 bit programs.

When writing 64 bits programs, you don't use the flat directive. Also you will need ml64 for 64 bits programs.  :icon_idea:


vitsoft

Quote from: greatbigfoot on January 27, 2020, 01:58:54 PM
I thought it best to start with the shortest possible program that didn't produce an error.

The shortes possible formally valid x86 program is only 1 byte long and it contains instruction RET only (0xC3). Of course it doesn't do anything useful and it just gracefully terminates itself. 

File containing 0xC3 is interpreted by CP/M, DOS, NTVDM in 32bit Windows or by DosBox in 64bit Windows as 16bit TINY COM program, if it has file extension .COM. When you launch such program, DOS will allocate some memory, create 256 bytes long Program Segment Prefix, loads the *.COM file  from disk right after PSP (at offset 256), sets CS=DS=ES=SS to point at PSP and finally sets SP=-2 and IP=256. Processor performs our instruction RET at CS:IP, i.e. it loads IP from SS:SP, where it finds a word 0 (the stack is clear). Hence the next performed instruction is found at CS:0, i.e. at the start of PSP. The first two bytes in PSP always contain 0xCD20, which is interpreted as INT 0x20 - system service ExitProcess.

jj2007

Here is an application that is 8 bytes long and does something useful - it prints what was passed in the commandline:

.model tiny
.code
  org 100h
start:
  mov ah, 09h          ; write string to STDOUT
  mov dx, 82h          ; get command line
  int 21h              ; show it... ;-)
  ret                  ; an extract of Ralf Brown's list of DOS interrupts is available here
end start

FORTRANS

Hi,

Quote from: jj2007 on February 03, 2020, 12:06:56 AM
  mov ah, 09h          ; write string to STDOUT

   Note that it is a $ terminated string.  So you
will usually get some garbage following the
command line string.  Unless you add a $ at
the string end, of course.

Cheers,

Steve

hutch--


Mikl__

Hi, greatbigfoot!
It is my tiny PE win64 in FASM-dialect. Workable 64-bits program with MessageBox function. Exe-size is 278 bytes
format binary as "exe"
include "d:\fasm\include\win64a.inc"
struc dbs [data]
{
  common
  . db data
  .size = $ - .
}

IMAGE_DOS_SIGNATURE             equ 5A4Dh
IMAGE_NT_SIGNATURE              equ 00004550h
PROCESSOR_AMD_X8664             equ 8664h
IMAGE_SCN_CNT_CODE              equ 00000020h
IMAGE_SCN_MEM_WRITE             equ 80000000h
IMAGE_SCN_MEM_READ              equ 40000000h
IMAGE_SCN_CNT_INITIALIZED_DATA  equ 00000040h
IMAGE_SUBSYSTEM_WINDOWS_GUI     equ 2
IMAGE_NT_OPTIONAL_HDR64_MAGIC   equ 20Bh
IMAGE_FILE_RELOCS_STRIPPED      equ 1
IMAGE_FILE_EXECUTABLE_IMAGE     equ 2
IMAGE_BASE                      equ 400000h
align1                          equ 4
use64
org 0
;--------DOS-stub-------------------------------
Signature               dw IMAGE_DOS_SIGNATURE,0
;-------PE-header--------------------------------------------------
ntHeader                dd IMAGE_NT_SIGNATURE
;----COFF File Header (Object and Image)----
Machine                 dw PROCESSOR_AMD_X8664
Count_of_section        dw 0
TimeStump               dd 0
Symbol_table_offset     dd 0
Symbol_table_count      dd 0
Size_of_optional_header dw begin-optional_header
Characteristics         dw IMAGE_FILE_RELOCS_STRIPPED or IMAGE_FILE_EXECUTABLE_IMAGE
;-------Optional Header (Image Only)------------------
optional_header:
Magic_optional_header   dw IMAGE_NT_OPTIONAL_HDR64_MAGIC
Linker_version_major_and_minor db 14,11
Size_of_code            dd Import_Table-begin
Size_of_init_data       dd 70h
Size_of_uninit_data     dd 0
entry_point             dd start
base_of_code            dd begin
;-----------------------------------------------------
image_base              dq IMAGE_BASE
section_alignment       dd align1
file_alignment          dd ntHeader
OS_version_major_minor  dw 6,0
image_version_major_minor dd 0
subsystem_version_major_minor dw 6,0
Win32_version           dd 0
size_of_image           dd end_import
size_of_header          dd begin
checksum                dd 0
subsystem               dw IMAGE_SUBSYSTEM_WINDOWS_GUI
DLL_flag                dw 8100h
Stack_allocation        dq 100000h
Stack_commit            dq 1000h
Heap_allocation         dq 100000h
Heap_commit             dq 1000h
loader_flag             dd 0
number_of_dirs          dd 2
export_RVA_size         dq 0
import_RVA_size         dd _import,3Ch
;--------data and code-----------------------------------------
begin:         
MsgBoxText      dbs "Win64 Assembly is Great!",0
MsgCaption      db "Uncle Remus tales",0;
start:         
        push rbp                     
        mov edx,MsgBoxText+IMAGE_BASE
        lea r8d,[rdx+MsgBoxText.size]
        xor ecx,ecx                 
        xor r9d,r9d                 
        call [MessageBox]           
        pop rbp                     
        retn                         
;----import--------------------------------------------
Import_Table:
user32_table:
MessageBox  dq _MessageBox
_import:
dd 0,0,0,user32_dll,user32_table,0
user32_dll db "user32"
dd 0
_MessageBox             db 0,0,"MessageBoxA",0
end_import:
for Win32 XP or Seven I wrote a program that creates MessageBox with size equal to 97 bytes.686P
.model flat
include windows.inc
includelib user32.lib
includelib kernel32.lib
extern _imp__MessageBoxA@16:dword
extern _imp__WriteFile@20:dword
extern _imp__CreateFileA@28:dword
extern _imp__CloseHandle@4:dword
extern _imp__LoadLibraryA@4:dword
.code
start:  xor ebx,ebx
        push MB_ICONINFORMATION OR MB_SYSTEMMODAL;1040h
        push offset szInfoCap
        push offset namefile
        push ebx
    call _imp__MessageBoxA@16
    mov eax,_imp__LoadLibraryA@4
    sub eax,offset _LoadLibraryA-buffer+ImageBase+size _LoadLibraryA;400023h
    mov _LoadLibraryA,eax
    mov eax,_imp__MessageBoxA@16
    sub eax,offset _MessageBoxA-buffer+ImageBase+size _MessageBoxA;400035h
    mov _MessageBoxA,eax
    push ebx    ;NULL   
    push FILE_ATTRIBUTE_ARCHIVE
    push CREATE_ALWAYS
    push ebx
    push FILE_SHARE_READ or FILE_SHARE_WRITE
    push GENERIC_READ or GENERIC_WRITE
    push offset namefile
    call _imp__CreateFileA@28
    push eax    ;hFile 4;O CloseHandle
    push ebx        ;lpOverlapped
        push offset SizeReadWrite   ;lpNumberOfBytesToWrite
    push sizeof_image;a4-buffer ;nNumberOfBytesToWrite=97
    push offset buffer  ;lpBuffer
    push eax    ;hFile 4;O WriteFile
    call _imp__WriteFile@20
    call _imp__CloseHandle@4
QUIT:   retn
ImageBase equ 400000h
buffer  dd 'ZM','EP'
    dw 14Ch ;Machine (Intel 386)
    dw 0    ;NumberOfSection
EntryPoint: xor ebx,ebx ; ebx = 0
    mov edi,offset namedll-buffer+ImageBase
    push edi        ;push offset user32
    jmp short @f
    db 0,0  ;       UNUSED
    dw a4-optheader ;SizeOfOptionalHeader
    dw 103h ;Characteristics (no relocations, executable, 32 bit)
optheader:
    dw 10Bh ;Magic PE32
@@:
    db 0E8h         ;call LoadLibraryA
_LoadLibraryA dd 0
    push ebx        ;push 0
    push edi        ;push offset user32
    push edi        ;push offset user32
    push ebx        ;push 0
    jmp short @f
    db 0,0,0
    dd EntryPoint-buffer
@@:
    db 0E8h         ;call MessageBoxA
_MessageBoxA dd 0
    retn
    dw 0    ;           UNUSED
    dd ImageBase    ;ImageBase
    dd 4    ;SectionAligment
    dd 4    ;FileAligment
namedll db 'user32',0,0 ;       UNUSED
    dd 4    ;MinorSubsystemVersion  UNUSED
    dd 0    ;Win32VersionValue  UNUSED
    dd 68h  ;SizeOfimage
    dd sizeof_image;64h ;SizeOfHeader
    dd 0    ;CheckSum       UNUSED
    db 2    ;Subsystem (Win32 GUI)
a4:
;---------------------------------------------------------------------------
sizeof_image=$-buffer
.data
szInfoCap db "Creator tiny MessageBox",0
namefile db 'tiny97.exe',0
SizeReadWrite dd 0
end start

daydreamer

Quote from: Mikl__ on February 03, 2020, 09:55:48 PM
Hi, greatbigfoot!
It is my tiny PE win64 in FASM-dialect. Workable 64-bits program with MessageBox function. Exe-size is 278 bytes
format binary as "exe"
include "d:\fasm\include\win64a.inc"
struc dbs [data]
{
  common
  . db data
  .size = $ - .
}

IMAGE_DOS_SIGNATURE             equ 5A4Dh
IMAGE_NT_SIGNATURE              equ 00004550h
PROCESSOR_AMD_X8664             equ 8664h
IMAGE_SCN_CNT_CODE              equ 00000020h
IMAGE_SCN_MEM_WRITE             equ 80000000h
IMAGE_SCN_MEM_READ              equ 40000000h
IMAGE_SCN_CNT_INITIALIZED_DATA  equ 00000040h
IMAGE_SUBSYSTEM_WINDOWS_GUI     equ 2
IMAGE_NT_OPTIONAL_HDR64_MAGIC   equ 20Bh
IMAGE_FILE_RELOCS_STRIPPED      equ 1
IMAGE_FILE_EXECUTABLE_IMAGE     equ 2
IMAGE_BASE                      equ 400000h
align1                          equ 4
use64
org 0
;--------DOS-stub-------------------------------
Signature               dw IMAGE_DOS_SIGNATURE,0
;-------PE-header--------------------------------------------------
ntHeader                dd IMAGE_NT_SIGNATURE
;----COFF File Header (Object and Image)----
Machine                 dw PROCESSOR_AMD_X8664
Count_of_section        dw 0
TimeStump               dd 0
Symbol_table_offset     dd 0
Symbol_table_count      dd 0
Size_of_optional_header dw begin-optional_header
Characteristics         dw IMAGE_FILE_RELOCS_STRIPPED or IMAGE_FILE_EXECUTABLE_IMAGE
;-------Optional Header (Image Only)------------------
optional_header:
Magic_optional_header   dw IMAGE_NT_OPTIONAL_HDR64_MAGIC
Linker_version_major_and_minor db 14,11
Size_of_code            dd Import_Table-begin
Size_of_init_data       dd 70h
Size_of_uninit_data     dd 0
entry_point             dd start
base_of_code            dd begin
;-----------------------------------------------------
image_base              dq IMAGE_BASE
section_alignment       dd align1
file_alignment          dd ntHeader
OS_version_major_minor  dw 6,0
image_version_major_minor dd 0
subsystem_version_major_minor dw 6,0
Win32_version           dd 0
size_of_image           dd end_import
size_of_header          dd begin
checksum                dd 0
subsystem               dw IMAGE_SUBSYSTEM_WINDOWS_GUI
DLL_flag                dw 8100h
Stack_allocation        dq 100000h
Stack_commit            dq 1000h
Heap_allocation         dq 100000h
Heap_commit             dq 1000h
loader_flag             dd 0
number_of_dirs          dd 2
export_RVA_size         dq 0
import_RVA_size         dd _import,3Ch
;--------data and code-----------------------------------------
begin:         
MsgBoxText      dbs "Win64 Assembly is Great!",0
MsgCaption      db "Uncle Remus tales",0;
start:         
        push rbp                     
        mov edx,MsgBoxText+IMAGE_BASE
        lea r8d,[rdx+MsgBoxText.size]
        xor ecx,ecx                 
        xor r9d,r9d                 
        call [MessageBox]           
        pop rbp                     
        retn                         
;----import--------------------------------------------
Import_Table:
user32_table:
MessageBox  dq _MessageBox
_import:
dd 0,0,0,user32_dll,user32_table,0
user32_dll db "user32"
dd 0
_MessageBox             db 0,0,"MessageBoxA",0
end_import:
for Win32 XP or Seven I wrote a program that creates MessageBox with size equal to 97 bytes.686P
.model flat
include windows.inc
includelib user32.lib
includelib kernel32.lib
extern _imp__MessageBoxA@16:dword
extern _imp__WriteFile@20:dword
extern _imp__CreateFileA@28:dword
extern _imp__CloseHandle@4:dword
extern _imp__LoadLibraryA@4:dword
.code
start:  xor ebx,ebx
        push MB_ICONINFORMATION OR MB_SYSTEMMODAL;1040h
        push offset szInfoCap
        push offset namefile
        push ebx
    call _imp__MessageBoxA@16
    mov eax,_imp__LoadLibraryA@4
    sub eax,offset _LoadLibraryA-buffer+ImageBase+size _LoadLibraryA;400023h
    mov _LoadLibraryA,eax
    mov eax,_imp__MessageBoxA@16
    sub eax,offset _MessageBoxA-buffer+ImageBase+size _MessageBoxA;400035h
    mov _MessageBoxA,eax
    push ebx    ;NULL   
    push FILE_ATTRIBUTE_ARCHIVE
    push CREATE_ALWAYS
    push ebx
    push FILE_SHARE_READ or FILE_SHARE_WRITE
    push GENERIC_READ or GENERIC_WRITE
    push offset namefile
    call _imp__CreateFileA@28
    push eax    ;hFile 4;O CloseHandle
    push ebx        ;lpOverlapped
        push offset SizeReadWrite   ;lpNumberOfBytesToWrite
    push sizeof_image;a4-buffer ;nNumberOfBytesToWrite=97
    push offset buffer  ;lpBuffer
    push eax    ;hFile 4;O WriteFile
    call _imp__WriteFile@20
    call _imp__CloseHandle@4
QUIT:   retn
ImageBase equ 400000h
buffer  dd 'ZM','EP'
    dw 14Ch ;Machine (Intel 386)
    dw 0    ;NumberOfSection
EntryPoint: xor ebx,ebx ; ebx = 0
    mov edi,offset namedll-buffer+ImageBase
    push edi        ;push offset user32
    jmp short @f
    db 0,0  ;       UNUSED
    dw a4-optheader ;SizeOfOptionalHeader
    dw 103h ;Characteristics (no relocations, executable, 32 bit)
optheader:
    dw 10Bh ;Magic PE32
@@:
    db 0E8h         ;call LoadLibraryA
_LoadLibraryA dd 0
    push ebx        ;push 0
    push edi        ;push offset user32
    push edi        ;push offset user32
    push ebx        ;push 0
    jmp short @f
    db 0,0,0
    dd EntryPoint-buffer
@@:
    db 0E8h         ;call MessageBoxA
_MessageBoxA dd 0
    retn
    dw 0    ;           UNUSED
    dd ImageBase    ;ImageBase
    dd 4    ;SectionAligment
    dd 4    ;FileAligment
namedll db 'user32',0,0 ;       UNUSED
    dd 4    ;MinorSubsystemVersion  UNUSED
    dd 0    ;Win32VersionValue  UNUSED
    dd 68h  ;SizeOfimage
    dd sizeof_image;64h ;SizeOfHeader
    dd 0    ;CheckSum       UNUSED
    db 2    ;Subsystem (Win32 GUI)
a4:
;---------------------------------------------------------------------------
sizeof_image=$-buffer
.data
szInfoCap db "Creator tiny MessageBox",0
namefile db 'tiny97.exe',0
SizeReadWrite dd 0
end start

cool
:thumbsup:
my none asm creations
https://masm32.com/board/index.php?topic=6937.msg74303#msg74303
I am an Invoker
"An Invoker is a mage who specializes in the manipulation of raw and elemental energies."
Like SIMD coding