masm sample with C++






cat test01.cpp
#include <cstdio>
#include <cstring>
// C4514 unreferenced inline function has been removed
#pragma warning(disable : 4514) 

extern "C" unsigned int __stdcall TestProc(unsigned int dwValue);
extern "C" unsigned int __stdcall MoveProc(char * buf);
extern "C" unsigned int __stdcall ParamProc(int x, short y, char z);
extern "C" unsigned int __stdcall PushPopProc(void);
extern "C" unsigned int __stdcall PPesiedi(void);
extern "C" unsigned int __stdcall LoopTest1(void);
extern "C" unsigned int __stdcall IncDecTest(void);
extern "C" unsigned int __stdcall AddSubTest(int x, int y);
extern "C" unsigned int __stdcall MulDivTest(int x, short y);
extern "C" unsigned int __stdcall LogicalFunction(void);
extern "C" unsigned int __stdcall ShiftFunction(void);
extern "C" unsigned int __stdcall CmpFunction(void);
extern "C" unsigned int __stdcall LoopFunction(void);
extern "C" unsigned int __stdcall IfMacroTest(void);
extern "C" unsigned int __stdcall RepeatMacroTest(void);
extern "C" unsigned int __stdcall InvokeTest(void);
extern "C" unsigned int __stdcall LocalMemTest(void);

int main(int argc, char ** argv)
{
	unsigned int dwValue = 100;
	unsigned int dwReturn = TestProc(dwValue);

	printf("%d\n", dwReturn);
	printf(">");
	getchar();

	char buf[100];
	strcpy_s(buf,"ABCDEFGHIJKLMNOPQRSTUVWXYZ\0");

	MoveProc(buf);

	printf("%s\n",buf);

	ParamProc(10,2,1);
	PushPopProc();
	PPesiedi();
	LoopTest1();
	IncDecTest();
	dwReturn = AddSubTest(2,3);
	printf("2+2-3=%d\n", dwReturn);
	dwReturn=MulDivTest(10,3);
	printf("10*10/3=%d\n", dwReturn);
	LogicalFunction();
	ShiftFunction();
	CmpFunction();
	LoopFunction();
	IfMacroTest();
	RepeatMacroTest();
	dwReturn=InvokeTest();
	printf("100+100=%d\n", dwReturn);
	LocalMemTest();
	return 0;
}

cat test.asm
.486
.model flat, stdcall
option casemap :none

.code

TestProc proc dwValue:DWORD

	mov eax, dwValue
	add eax, 100
	ret

TestProc endp

MoveProc proc buf_ptr:DWORD
	mov eax, 100
	mov al, bl      ; move the lower byte of ebx into the lower byte of eax
	mov al, 0ffh    ; move 0xFF into the lower byte of eax
	mov ah, 0ffh    ; move 0xFF into the high byte of the low word (2-bytes) of eax
	mov ax, 0ffffh  ; move 0xFFFF into the low word of eax
	mov eax, 0ffffh ; move 0xFFFF into eax
	mov eax,buf_ptr

	push esi
	push edi
	mov esi,eax
	mov edi,eax
	mov al, [esi]   ; move the byte contained in the memory address
					; in register esi into the lower byte of eax
	mov bl,al
	inc al
	mov bl,al
	mov [edi], bl   ; move the byte value in the lowest byte of ebx
				 	; into the memory address in register edi
	inc esi
	inc edi
	mov cx, [esi]   ; move the word (2-byte) value contained in the
					; memory address of register esi into the lower word of ecx
	add cx,0101h
	mov edx,44444444h
	mov dx,cx
	mov [edi], edx  ; move the dword (4-byte) value contained in edx
					; into the memory address contained in register edi
	mov al, [esi + 3]    ; move the byte contained in the memory address
					; in register esi + 3 into the lower byte of eax
	add dx,0101h
	mov [edi + 2], dx    ; move the lower word (2-bytes) contained in
					; edx into the memory address contained in the
					; register edi + 2
	pop edi
	pop esi
	ret
MoveProc endp 

ParamProc proc dwValue1:DWORD, wValue2:WORD, bValue3:BYTE
   ret
ParamProc endp



PushPopProc proc
	mov eax, 100
	push eax    ; Stack now contains { 100 }

	mov eax, 200
	push eax    ; Stack now contains { 200, 100 }

	mov eax, 300
	push eax    ; Stack now contains ( 300, 200, 100 }

	pop eax     ; eax = 300, stack = { 200, 100 }
	pop eax     ; eax = 200, stack = { 100 }
	pop eax     ; eax = 100, stack = { }

	ret
PushPopProc endp

PPesiedi proc

	push ebx
	push esi
	push edi

	; code goes in here

	pop edi
	pop esi
	pop ebx
	ret

PPesiedi endp

LoopTest1 proc

	xor eax, eax    ; efficient way of saying eax = 0
	mov ecx, 5      ; ecx is the register generally used for counters

LoopStart:		    ; this is a label, used for labelling code positions
	inc eax
	dec ecx
	jnz LoopStart

	; eax now equals 5

	ret

LoopTest1 endp

IncDecTest proc

	mov ecx, 10
	xor eax, eax    ; efficient way of saying eax=0

LoopStart:
	inc eax
	dec ecx
	jnz LoopStart

	; eax now equals 10

	ret

IncDecTest endp

AddSubTest proc dwValue1:DWORD, dwValue2:DWORD

	mov eax, dwValue1
	add eax, dwValue1
	sub eax, dwValue2
	ret

AddSubTest endp

MulDivTest proc dwValue1:DWORD, wValue2:WORD

	mov eax, 10
	xor edx, edx    ; set edx to zero

	mul dwValue1
	div wValue2

	ret

MulDivTest endp

LogicalFunction proc

	xor eax, eax    ; the efficient way of saying eax=0

	mov ax, 100
	mov bx, 5
	and ax, 1
	or ax, bx
	ret

LogicalFunction endp

ShiftFunction proc

	mov eax, 1
	shl eax, 2    ; shift eaxs bits left 2 times :  i.e. eax *= 4
	shr eax, 2    ; shift eaxs bits right 2 times : i.e. eax /= 4

	ret

ShiftFunction endp

CmpFunction proc

	mov eax, 100
	cmp eax, 100

	; jump if equals
	je Equals

	; not equal
	mov eax, 2
	jmp lbl1

Equals:
	mov eax, 1

lbl1:
	ret

CmpFunction endp
LoopFunction proc

	xor eax, eax
	mov ecx, 10

	LoopStart:
	inc eax
	loop LoopStart

	ret

LoopFunction endp

IfMacroTest proc

	mov eax, 100
	mov ecx, 200

	.if eax == ecx
		; do something
	.else
		; do something else
	.endif

	ret

IfMacroTest endp

RepeatMacroTest proc

	xor eax, eax
	mov ecx, 100

	.repeat

		inc eax

	.untilcxz

	mov al,3
	.repeat
		dec al
	.until zero?   ; if zero flag set

	xor eax, eax
	mov ecx, 100

	.repeat

		push ecx
		mov ecx, 100

		.repeat

			inc eax

		.untilcxz

		pop ecx

	.untilcxz

	ret

RepeatMacroTest endp

Function1 proc dwValue:DWORD

	add eax, 100
	ret

Function1 endp

InvokeTest proc

	mov eax, 100

	invoke Function1, eax

	; eax now = 200, i.e. eax += 100
	ret

InvokeTest endp

LocalMemTest proc

	LOCAL dwValue:DWORD    ; allocates 4 bytes and labels it dwValue
	LOCAL wValue:WORD      ; allocates 2 bytes and labels it wValue
	LOCAL bValue:BYTE      ; allocates 1 byte  and labels it bValue

	xor eax, eax

	mov dwValue, eax
	mov wValue, ax
	mov bValue, al

	ret

LocalMemTest endp


end

cat makefile
.SUFFIXES: .exe .obj .asm
.PHONY: all clean mmm test

TARGET=test01
all: $(TARGET).exe

OBJS=$(TARGET).obj  test.obj

$(TARGET).exe: $(OBJS)
	link $^
	@echo

$(TARGET).obj: $(TARGET).cpp

test.obj: test.asm

.cpp.obj:
	cl -c -Wall -Od $<
	@echo

.asm.obj:
	ml -c -coff -Fo$@ $<
	@echo

test: $(TARGET).exe
	./$(TARGET).exe 

clean:
	@-rm $(TARGET).exe *.obj *~ 1>/dev/null 2>&1

mmm: 
	cat $(TARGET).cpp
	@echo 
	cat test.asm
	@echo 
	cat makefile

html:
	cat /dev/clipboard | code2html.exe | unix2dos