; Single line comments
comment !
Multi line comments
Can use any matching pair of symbols
!
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 |
0dh, 0ah
for new lines in strings.varName = 10
constName equ 10
constString equ <"String", 0>
$
gets the current address. Ex: arrLength equ ($ - arr) / 4Example: 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 |
| 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 |
Names | Description |
---|---|
eip | Instruction pointer |
eflags | Flags register |
ds | Data segment |
ss | Stack segment |
cs | Code segment |
hs | Heap segment |
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 |
varName dataType literal
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 |
s
in front for sign(sbyte), but asm doesn’t have any concept of sign.?
for unutilized. Ex: var1 byte ?
.data
num1 tbyte 34120000000000000000h ; 1234 decimal
num1 tbyte 34120000000000000080h ; -1234 decimal
arrName dataType ele1, ele2
or arrName dataType size dup(defaultValues)
str byte 5 dup('_'), 0
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 |
type
can also be used for variables..data
arr byte 0, 1, 2, 3
byte 4, 5, 6, 7
type ptr dataName
.data
var1 dword 12345678h
.code
mov byte ptr [var1 + 3], 21 ; var1 is 21345678h. Little endian so index 0 is LSB.
arr[index * type arr]
.data
arr1 word 0, 1, 2, 3, 4
.code
mov ax, arr1[2 * type arr1] ; Moves index 2 into ax
[arr + index * type arr]
offset arr
stores the offset from .data segment.
.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
nop
- 1 byte of program storage and does nothing.mov des, src
- Moves src to des without changing bits. Des and src have to be the same size.movzx des, src
- Des has to be larger than src and fills in the upper bits with 0s.movsx des, src
- Des has to be larger than src and fills in the upper bits with the sign of src.xchg des1, des2
- Swaps des1 and des2. They have to be the same size.
mov eax, var1
, xchg eax, var2
, mov var1, eax
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 |
lahf
- Load the low byte of eflags into ah. This includes the sign, zero, auxiliary carry, parity, and carry flags.sahf
- Store ah into eflags.neg des
- Reverse the sign by using 2s compliment
sub 0, eax
add des, src
sub des, src
des = des - src
inc des
- Increments des. Faster than add des, 1
dec des
- Decrements des. Faster than sub des, 1
adc des, src
- Add with carry. des = des + src + CFsbb des, src
- Subtract with borrow. des = des - src - CFMultiplicand | Multiplier | Product |
---|---|---|
al | reg8/mem8 | ah:al(ax) |
ax | reg16/mem16 | dx:ax |
eax | reg32/mem32 | edx:eax |
mul des
- Unsigned multiplication.
imul des
- Signed multiplication.
imul reg16, reg16/mem16/imm8/imm16
imul reg32, reg32/mem32/imm8/imm32
imul reg16, reg16/mem16, imm8/16
Ex: 16 * 16 or 10h * 10h
mov al, 10h
mov bl, 10h
mul bl ; ah = 01h and al = 00h
Dividend | Divisor | Remainder | Quotient |
---|---|---|---|
ah:al(ax) | reg8/mem8 | ah | al |
dx:ax | reg16/mem16 | dx | ax |
edx:eax | reg32/mem32 | edx | eax |
div des
- Unsigned division
idiv des
- Signed division.
cbw
- Sign extends al to ah. Convert byte to word.cwd
- Sign extends ax to dx. Convert word to dword.cdq
- Sign extends eax to edx. Convert dword to qword.Ex: 16 / 16 or 10h / 10h
mov al, 10h
mov ah, 0
mov bl, 10h
div bl ; ah = 00h and al = 01h
or des, src
and des, src
not des
xor des, src
nand des, src
nor des, src
temp |= 0x4
- Sets to 1temp &= ~0x4
- Sets to 0temp ^= 0x4
- Toggles bitEx: Converting to upper case
mov eax, 61h ; 'a'
and eax, NOT 32 ; 'A'
shl des, imm8/cl
/sal des, imm8/cl
- Shift left.
shr des, imm8/cl
- Logical shift right.
sar des, imm8/cl
- Arithmetic shift right.
shld reg16/mem16/reg32/mem32, reg16/reg32, imm8/cl
- Shift left into des1
shrd reg16/mem16/reg32/mem32, reg16/reg32, imm8/cl
- Shift right into des1
rol des, imm8/src
- Rotate leftror des, imm8/src
- Rotate rightrcl des, imm8/src
- Rotate left through the Carry Flagrcr des, imm8/src
- Rotate right through the Carry FlagEx: 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
loop label
- Decrements ecx, and then jumps to label if ecx isn’t 0.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.
ebp
(Base pointer) - Holds the address of the base of the procedure.
eip
(Instruction pointer) - Address of the next instruction.esp
(Stack point) - Points to the top of the stack, the last pushed stack value.
push src
pop des
call procedure
- Same as push eip
ret
or ret #
- Same as pop eip
#
of bytes to pop from stack. Used to remove arguments.enter
- push ebp
, then mov ebp, esp
leave
- mov esp, ebp
and pop ebp
pushfd
/popfd
pusha
/pushad
and popa
/popad
label::
.Add proc uses esi ecx
- The uses operator pushes the listed register at the start of the procedure and then pops them at the end of the procedure.
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
lea des, src
- Load effective address. Returns the address of an indirect operand.
lea eax, [ebp - 4]
does the same thing as mov eax, ebp
and sub eax, 4
, but only takes one operation.OFFSET
only works for addresses know at compiler time, while lea
works at run time.LOCAL label1:type, label2:type, etc
LOCAL var1:byte
, LOCAL pArray:ptr word
, or LOCAL TempArray[10]:dword
INVOKE procedureName, arg1, arg2, etc
ADDR data
procedureName PROC uses registers, paramName:type, etc
procedureName PROTO
mov eax, [array]
vs
mov eax, array
mov eax, dword ptr [array]
jmp label
- Jumps the code to that labelcmp des, src
- Subtracts to set the flags register, but doesn’t change the des.test des, src
- ANDing to set the flags register, but doesn’t change the des.
bool isSet = var1 & 0x4
jz label
/je label
- Jump if equal/zero flagjnz label, jne label
- Jump if not equal/zero flagjs label
- Jump if sign flagjns label
- Jump if not sign flagjc
- Jump if carry flagjnc
- Jump if not carry flagjo
- Jump if overflow flagjno
- Jump if not overflow flagjcxz label
- Jump if CX = 0jecxz label
- Jump if ECX = 0jrcxz label
- Jump if RCX = 0 (64-bit mode)jb label
/jnae label
- Jump below.
ja label
/jnbe label
- Jump above.
jae label
/jnb label
- Jump above or equal.jbe label
/jna label
- Jump below or equal.jl label
/jnge label
- Jump less.
jg label
/jnle label
- Jump greater.
jle label
/jng label
- Jump less or equal.jge label
/jnl label
- Jump greater or equal.loopz label
/loope label
- Decrement ecx, loops if ecx isn’t 0, or loop if zero/equal flag is set.loopnz label
/loopne label
- Decrement ecx, loops if ecx isn’t 0, or loop if zero/equal flag is clear.&&
||
If_Body_
, Else_
, Else_If_1_
, Else_If_2_
, End_If_
Or
, Or_2
While
, While_Body
, End_While
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:
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 |
CARRY?
OVERFLOW?
PARITY?
SIGN?
ZERO?
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 |
// 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;
}
cld
- Clear direction flag. std
- Sets direction flagmovsb
- For bytesmovsw
- For wordsmovsd
- For dwordsMove 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.
cmpsb
cmpsw
cmpsd
repe
/repz
- Repeat if equal/zero flag.repne
/repnz
- Repeat if not equal/not zero flag..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.
scasb
scasw
scasd
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.
stosb
stosw
stosd
.data
arr1 dword 20 DUP(?)
.code
mov eax, 40h
mov edi, offset arr1
mov ecx, LENGTHOF arr1
cld
rep stosd
lodsb
lodsw
lodsd
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;
}