Home

Masm(Microsoft assembly)

Comments

; Single line comments
comment !
	Multi line comments
	Can use any matching pair of symbols
!

Literals/Immediate

Examples Number System
11 or 11d Decimal
00001011b Binary
11h Hex
‘H’ or “H” Character(1 byte)
2. or 2.1 or 40.2E5 Float

Symbols

varName = 10
constName equ 10
constString equ <"String", 0>

Endianess

Example: 0x1429FD2E

Little endian(Intel) - Opposite to arrays. Useful for aligning. | Address | Value | |———|——-| | 0 | 2E | | 1 | FD | | 2 | 29 | | 3 | 14 |

Big endian(Arm) - Same as arrays. Not as useful for aligning. | Address | Value | |———|——-| | 0 | 14 | | 1 | 29 | | 2 | FD | | 3 | 2E |

Registers

General Purpose Registers


| eax | <- 4 bytes | ax | <- 2 bytes | ah | al | <- 1 byte not for esi, edi, ebp, or esp

Names Description
eax Usually used for accumulating
ebx  
ecx Usually used for counting
edx  
esi  
edi  
ebp Base pointer
esp Stack pointer

Unaccessible registers

Names Description
eip Instruction pointer
eflags Flags register
ds Data segment
ss Stack segment
cs Code segment
hs Heap segment

Flags

Name Symbol Description
OF Overflow flag Signed integer overflow
CF Carry flag Unsigned integer overflow
SF Sign flag Is the result negative
ZF Zero flag Is the result 0
PF Parity flag Even number of 1s in the least significant byte
AC Auxiliary cary flag Used for BCD. Is there a carry between the 3rd and 4th bit

.data

Data Type Bytes Bits Description
byte 1 8 Int
word 2 16 Int
dword 4 32 Int
qword 8 64 Int
tbyte 10 80 Binary coded decimal
real4 4 32 Float
real8 8 64 Float
real10 10 80 Float

Binary coded decimals(BCD)

.data
	num1 tbyte 34120000000000000000h ; 1234 decimal
	num1 tbyte 34120000000000000080h ; -1234 decimal

Arrays and Directives

Directive Name Description
type Size of the elements
lengthof Number of elements
sizeof Number of bytes. type * lengthof
align # Adds that many bytes in .data. Used for aligning.
varname label dataType Takes up no storage. Like union in C
.data
	arr byte 0, 1, 2, 3
	    byte 4, 5, 6, 7

Pointers

.data
	var1 dword 12345678h
.code
	mov byte ptr [var1 + 3], 21  ; var1 is 21345678h. Little endian so index 0 is LSB.

Direct addressing - Using an index

.data
	arr1 word 0, 1, 2, 3, 4
.code
	mov ax, arr1[2 * type arr1] ; Moves index 2 into ax

Indirect addressing - Using a memory location

.data
	arr1 word 0, 1, 2, 3, 4
.code
	mov eax, offset arr1
	add eax, type arr1 * 2   ; eax holds the offset of arr1 from .data
	mov bx, [eax]            ; Moves 2 into bx

.code

Modifying flags

Command Description
test des, 0 Set Zero flag
or des, 1 Clear Zero flag
or most significant bit with 1 Set Sign flag
and most significant bit with 0 Clear Sign flag
stc Set Carry flag
clc Clear Carry flag
Add positive nums that produce neg Set Overflow flag
or des, 0 Clear Overflow flag
test reg, reg Check the flags without changing

Arithmetic

Addition and Subtraction

Multiplying

Multiplicand Multiplier Product
al reg8/mem8 ah:al(ax)
ax reg16/mem16 dx:ax
eax reg32/mem32 edx:eax

Ex: 16 * 16 or 10h * 10h

mov al, 10h
mov bl, 10h
mul bl         ; ah = 01h and al = 00h

Dividing

Dividend Divisor Remainder Quotient
ah:al(ax) reg8/mem8 ah al
dx:ax reg16/mem16 dx ax
edx:eax reg32/mem32 edx eax

Ex: 16 / 16 or 10h / 10h

mov al, 10h
mov ah, 0
mov bl, 10h
div bl         ; ah = 00h and al = 01h

Bitwise

Ex: Converting to upper case

mov eax, 61h    ; 'a'
and eax, NOT 32 ; 'A'

Shifting and Rotating

Ex: Sign extend a register

mov ax, -128     ; eax = ????FF80h
shl eax, 16      ; eax = FF800000h
sar eax, 16      ; eax = FFFFFF80h

Ex: 13 * 10 using shifting 13 * 10 = 13 * (2^3 + 2^1) = 13 * 2^3 + 13 * 2^1

mov al, 13
shl al, 3     ; 13 * 2^3
mov bl, 13
shl bl, 1     ; 13 * 2^1
add al, bl    ; 13 * 2^3 + 13 * 2^3 = 13 * 10

Loops

Ex: Loop through an array

.data
	arr1 word 0, 1, 2, 3
.code
	mov eax, 0               ; Accumulator
	mov esi, 0               ; Index
	mov ecx, lengthof arr1   ; Count
L1:
	mov ebx, arr1[esi * type arr1]   ; Move arr1[index] into temp(ebx). This isn't necessary, just an example.
	add eax, ebx                     ; Add temp(ebx) to accumulator
	inc esi                          ; Increment index
	loop L1                          ; Decrements ecx, and exits if ecx is 0.

Procedures and the Stack

int add(int x, int y) {
	int c;
	int d;
	c = 16;
	d = x;
	return x + y;
}

int main() {
	int c = add(10, 15);
}
main proc
	; Push arguments in reverse order
		push 15
		push 10
	call add    ; push eip to save the return address
	; Remove arguments
		add esp, 8
main endp

add proc
	; Stack formation
		enter 0, 0
			; or
		push ebp                    ; Save the parent procedure's base pointer
		mov ebp, esp                ; Create this procedure's stack frame
	; Inside the procedure
		sub esp, 8                  ; Creates uninitialized c and d(4 bytes each) variables
		mov [ebp - 4], 16           ; c = 16
		mov [ebp - 8], [ebp + 8]    ; d = x(+4 for eip and +4 to get to top of x)
		mov eax, [ebp + 8]
		add eax, [ebp + 12]
	; Return preparation
		leave
			; or
		mov esp, ebp                ; Remove local vars
		pop ebp                     ; Restore calling procedure's base pointer
	; Returning
		ret
			; or
		ret #                       ; # of bytes of arguments
add endp

Calling conventions

mov eax, [array]
vs
mov eax, array
mov eax, dword ptr [array]

Jumps and Conditions

Ex: C If-Else to asm

int a = 15;
int b = 10;

int main() {
	if (a == 1 && b > 1) {
		// Code block 1
	} else if (a <= 1 || b >= 1) {
		// Code block 2
	} else {
		// Code block 3
	}
}
.data
	a sdword 15
	b sdword 10
.code
	; if (a == 1 && b > 1)
	cmp a, 1
	jne Else_If_1
	cmp b, 1
	jng Else_If_1
If_Body:
	; Code block 1
	jmp End_If
Else_If_1: ; (a <= 1 || b >= 1)
	cmp a, 1
	jle Else_If_1_Body
	cmp b, 1
	jl Else_
Else_If_1_Body:
		; Code block 2
		jmp End_If
Else_:
	; Code block 3
	jmp End_If ; Not necessary
End_If:

Ex: While loop example

.data
	a sbyte 10
.code
While: ; (a >= 10)
	cmp a, 10
	jl End_While
	; Code body
	jmp While
End_While:

Conditional directives

Directive Description
.IF condition  
.REPEAT Repeats code until .UNTIL condition is met.
.UNTIL condition Placed at the end of .REPEAT
.UNTILCXZ Until CX equals zero
.WHILE condition  
.ELSE  
.ELSEIF condition  
.ENDIF  
.ENDW Placed at the end of a .WHILE
.BREAK Terminates a .WHILE or .REPEAT
.CONTINUE Jumps to top of .WHILE or .REPEAT

System calls

Non-standard system calls: | Name | Description | |——————-|—————————————————| | call WriteBin | Prints out what’s in eax to the console in binary | | call WriteDec | Prints out unsigned int in eax | | call WriteInt | Prints out signed int in eax | | call WriteChar | Prints out ascii char in eax | | call crlf | Prints out new line to the console. 0dh, 0ah | | call WriteString | Prints array until 0. mov edx, offset str | | call SetTextColor | Allows you to set the text color | | call ClrScr | Clears the screen |

Recursion

// Recursive
int fact(int n) {
	if (n == 1) return 1
	return n * fact(n - 1);
}
// Iterative
int fact(int n) {
	int value = 1;
	for (int i = 1; i <= n; i++) {
		value *= i;
	}
	return value;
}

Special array commands

Move all the elements in arr1 into arr2

.data
	arr1 dword 20 DUP(?)
	arr2 dword 20 DUP(?)

.code
	cld    ; Forward direction
	mov esi, OFFSET arr1
	mov edi, OFFSET arr2
	mov ecx, LENGTHOF arr1
	rep movsd             ; Repeats for the amount in ecx. Decrements ecx each time.
.code
	mov esi, OFFSET arr1
	mov edi, OFFSET arr2
	mov ecx, LENGTHOF arr1
	repe cmpsd                ; Still increments/decrements even if it doesn't repeat.
	sub esi, 4                ; Therefore you need to decrement.
	mov dword prt [esi], 100  ; Moves 100 into the position that didn't match the other array.
mov edi, OFFSET str
mov al, 'F'
mov ecx, LENGTHOF str
cld
repne scasb
jnz quit               ; Didn't find anything
dec edi                ; Need to decrement to get the address of the F because repne still increments even if it didn't find anything.
.data
	arr1 dword 20 DUP(?)
.code
	mov eax, 40h
	mov edi, offset arr1
	mov ecx, LENGTHOF arr1
	cld
	rep stosd

Caching

int aLen = 2^14 / 4;
int a[aLen];
int bLen = aLen + 1;
int b[bLen];

for (int i = 0; i < aLen; i++) {
	a[i] = 10;
}

// This will cache miss the last index.
for (int i = 0; i < bLen; i++) {
	b[i] = 10;
}