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.
flatflat 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.
stdcallstdcall 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
ExitProcessIs the label which will represent a function declaration in memory
Will instruct the assembler to call the WIN32 procedure _ExitProcess@4
PROTOIs a directive telling the assembler that this line represents a function declaration
dwExitCode:Is the name of the parameter variable that the function accepts
DWORDTells 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
ExitProcessIs a symbol representing the address of the start of the procedure being called in memory
0Is 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
endIs a masm directive, and tells the assembler that this marks the end of a module
mainis a label representing the module being ended
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:
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 (https://en.wikipedia.org/wiki/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.
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 (http://spike.scu.edu.au/~barry/interrupts.html)
end start
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
Do an int 19h in hex and save it as a COM file. :biggrin:
Hi, greatbigfoot!
It is my tiny PE win64 in FASM-dialect. Workable 64-bits program with MessageBox function. Exe-size is 278 bytes (https://wasm.in/styles/smiles_s/mosking.gif)
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
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 (https://wasm.in/styles/smiles_s/mosking.gif)
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: