# 組合語言 Assembly Language (CSIE-2)
###### tags: `courses meow` `CSIE-2` `Assembly Language` `2020 Autumn`
:::success
:::spoiler Click for open TOC
[TOC]
:::
# Lab
- [lab1](/vexdJAG1TeKbM8uTtizxxA)
## Integer Sotrege SIzes
- byte: 8 bit
- word: 2 Byte
- dword: 4 Byte
## python caculator
```python=
int("binary string", 2) # decimal <- binary
int("hex string", 16) # decimal <- hex
hex(decimal) # hex <- decimal
```
## x86 arch
- clock
- sync cpu, BUS
## execution cycle
- operation order
- fetch
- decode
- fetch operands
- exec
- store output
- Memory
- segment
- CODE
- DATA
- BUS
- data bus
- Address bus
- decoder
- decode operands
##
- reak-address mode
- protected Mode
- mulititasking
- address table => address remapping
## General-Purpose Register
- CPU
- system bus (connect CPU and ALU)
- ALU
- register
- General-Purpose
- EAX 32bit
- AX 16bit (parts of EAX)
- AH 8bit (high pos, parts of AX)
- AL 8bit (low pos, parts of AX)
- EAX, ECX, ESP, ESI, EDI, EBP
- Segment
- CS DS SS
- EIP instruction pointer
- EFLAGS
---
> 092
## variables
### declare
```asm
;[variableName] [type] [val]
myVar btye 11011b
myVar2 dword 0A5h
; list
list BTYE 1, 2, 3, 4
; string
str BYTE "a string", 0
; mulity line string
bigStr BYTE "Enter your name: ", 0Dh, 0Ah
BTYE "next line~~", 0
;DUP
var1 BYTE 20 DUP(1) ; 20 bytes, all equal to 1
```
### type
- `d` => decimal(default)
- `h` => hex
- `b` => binary
- e.g.
- `0A5H`
### identifiers
- ==NOT== case senstive
## Directives
- NOt a command.
## insturection
### content
- label
- Mnemonic
- operanf
- comment
### example
```asm
; finalval = val1 + val2
mov eax, val1
add wax, val2
mov finalval, eax
```
### Labls
- data
## Comment
> Comments are good!
## Suggested Coding Standards
- some approacjes to capitalzation
- other suggestions
## Inreinstic Data Types
- BTYE, SBYTE
## Memory
### Little Endian Order
> intel standar
```
val DWORD 12345678h
```
```
memory
0000: 78
0001: 56
0002: 34
0004: 12
```
## bit operate
- SHL
- SHR
- SAL
- SAR
### Shift to Right
- Logic shift (**SHR**)
- 補0
```
[1][0][1][1] -> cf[]
[0][1][0][1]-> cf[1]
```
- Methmatic shift (**SAR**)
- 補自己
- 維持正負號
```
[1][0][1][1] -> cf[]
[1][1][0][1]-> cf[1]
```
### Shift to Left
43210
01001 => 9
10010 => -14
01110
### fast mulitpy
- shift to left
- num *= 2
- shift to right
- num /= 2
## Operand Types
- immediate
- Register
- Memory
### Direct Memory Operands
- mov
- 兩個 operand 需要等價
- 例外 **Zero Extension**
- destination > source
- CS, EIP, IP 不能是 destination
- dest 與 source 不能同時是 memory
- memory <- reg
- reg <- memory
```
MOV destination, source ; des.size == source.size
MOVSX ax, bl ; 補source第一位
MOVZX ax, bl ; 補0
```
### direct-offset operands
```
.data
array WORD 0000h 0002h
.code
mov al, arrayB+1 ; al = 0001h (arr[1])
mov al, [arrayB+1] ; al = 0001h (arr[0]+1)
```
```
; little edian
array dword 1000h 2000h
[00] array
[10]
[00] array + 2
[20]
```
### INC & DEC
```
mov ax, 00FFh
inc ax ; ax = 0100h
mov ax, 00FFh
inc al ; {al=FF -> al=00}
; ax = 0000h
```
### ADD & SUB
```
ADD destination, source
; destination += source
SUB destination, source
; destination -= source
```
### NEG
```
NDG target
; target *= -1
```
### FLAG
#### Zero Flag (ZF)
```
mov cx, 0 ; cx = 0, ZF = 1
inc cx, 1 ; cx = 1, ZF = 0
```
- a flag is set when it is equal to 1
- a flag is clear when it is equal to 0
#### Sign Flag (SF)
```
mov al, 0
sub al, 1 ; al = 11111111, SF = 1
add al, 2 ; al = 00000001, SF = 0
```
#### Carry Flag (CF)
```
mov al, 0FFh ; al = 01111111
add al, 1 ; CF = 1, al = 00000000
mov al, 0 ; al = 0000 0000
sub al, 1 ; CF = 1, al = 1111 1111
```
- [carry][al][al][al][al][al][al][al][al]
- when ADD
- CF = (carry out of the MSB)
- when SUB
- CF = invers(carry out of the MSB)
- CF = 1 when unsigned overflowed
#### Overflow Flag (OF)
```
; example 1
mov al, +127
add al, 1 ; OF = 1, al = ???
; Example 2
mov al, 7Fh ; al = 0111 1111
add al, 1 ; OF = 1, al = 1000 000
```
- `Overflow_flag = 1` if "overflow"
- OF = (carry out of the MSB) XOR (carry into the MSB)
#### CF & OF
:::success
see `var` as a `signed` number, then if it perfrom non-sense result after signed operation, OF=1
see `var` as a `unsinged` number, ..., CF = 1
:::info
Example:
```
num1 byte 11111111b ; num1 = -1
add num, 1 ; num = 0
; CF = 1, OF = 1
```
num1 = 11111111 -> 0000000
- see it **`unsigned`**
- -1 + 1 = 0 :heavy_check_mark: OK => **OF=0**
- see it **`signed`**
- 255 + 1 = 0 :x: overflowed => **CF=1**
:::
:::
#### hardware view
### OFFSET examples
```
.data
bVal BYTE ? ;1
wVal WORD ? ;2
.code
mov esi, OFFSET bVal
```
### Pointer operator
### Type Operator
```
.data
var1 BTYE ?
var2 WORD ?
.code
mov al, type var1 ;
```
### LENGTHOF Operator
how many element of array
```
mov eax, LENGTHOF myArray
```
### SizeOf operator
how many bytes of target
### Value oper
```
.data
myArray DWORD 1, 2, 3, 4, 5
.code
mov esi, OFFSET myArray
mov dword ptr esi, 0 ; *esi_ptr = 10
```
## LOOP Instruction
- implete by `jump`
- change `EIP`
- `EIP` is a pointer pointing the next command which cpu should exec
### Loop example
### Indirect Operands
## Stack
- ESP (Stack pointer)
- point to the top of the stack
- ESP -= 4 ; when push
- ESP += 4 ; when pop
### push & pop
```
push eax
pop eax
```
### Nested Loop
```asm
mov ecx, 100 ; loop1 for 100
Loop1:
push ecx ; store ecx in stack
mov ecx, 10 ; loop2 for 10
Loop2:
;
loop loop2
pop ecx ; get the val of stack
loop1
```
## Creating Procedures
- call
- `call mySub`
- impelte
- `push eip`
- `mov eip, &mySub`
- ret
- `ret`
- implete
- `pop eip`
### Call-Retrun Example
#### segments
- code seg
- data seg
- stack seg
### USES Operator
```
ArraySum PROC USES esi ecx
; this declare that the ArraySum produce will
; not make effct to esi ecx in main
```
```
; when using the keyword:`USES`
; the MASM will auto generate the code:
ArraySum PROC
push esi
push ecx
...
...
pop esi
push ecx
ArraySum ENDP
```
## Booleam Operation
- AND
```
AND destination, source
; dest = dest & source
```
- kind of "mask"
- application
- to capital
- OR
```
OR dest, source
; dest = dest | source
```
- application
- number to char(ASCii)
- XOR
```
XOR dest, source
; dest = dest ^ source
```
- application
- encyping a string
- output = secret ^ key
- secret = output ^ key
- NOT
```
NOT dest
; reverse dest
```
## CMP, TEST, JMP
- CMP
- compare a and b
```
cmp a, b ; flag = a - b
```
- TEST
- Assert a and b is eq
```
test a, b ; flag = a & b
```
:::warning
`a` and `b` must both be register
:::
- JMP
- Advence
- JZ, JNZ, JC, JE...
- Basic
- unsigned
- JE - jump if eq
- JNE - jump if not eq
- JA - jump if left > right
- JB - jump if left < rigt
- JAE
- JAN
- JNA
- JNB
- signed
- JG
- JL
## Rotate
### ROL (**Ro**tate to **L**eft)
- 最左跑到最右
- carry 作為 temp 紀錄最左邊一位
```
[1][0][1][0]
[0][1][0][1]
cf = 1ss
```
### RCL (**R**otate to **L**eft with **C**arry flag)
- 多帶著 `carry flag` 往左 Rotate
```
clc ; clear carry flag
mov bl, 88h
rcl bl
```
```
cf[1] bl[1][0][0][0][1][0][0][0]
RCL
cf[1] bl[0][0][0][1][0][0][0][1]
```
### ROR (**Ro**tate to **R**ight)
- cf 會作為暫存
```
rotate 2
[1][0][1][0] -> cf[0]
[0][1][0][1] -> cf[1]
[1][0][1][0] -> cf[1]
```
### RCR (**R**otate to **R**ight with **C**array flag)
### Compare
</br>

</br>

## Calcultae
### mul
- use `ax` as Arch
| source | mulifyer | destination |
| ------ | -------- | ----------- |
| bl | al | ax |
| bx | ax | dx:ax |
| ebx | eax | edx:eax |
```
mul {source}
```
```
mul bl ; ax = al * bl
; if [ah != 0];
; then cf =1
; else cf = 0
mul bx ; dx:ax = ax * bx
; if [dx != 0]
; then cf = 1
; else cf = 0
```
### div
dx -> extra dividend
ax -> dividend
dx -> remained
ax -> q
| divisor | dividend | qu | remain |
| ------- | -------- | --- |:------ |
| cl | ax | al | ah |
| cx | dx:ax | ax | dx |
| ecx | edx:eax | eax | edx |
```
div {divisor}
```
```
mov dx,0 ; dividend high
mov ax, 8003h ; dividend low
mov cx, 100h ; divisor
div cx ; ax = 0080h, dx = 3
; ax = (dx:ax) / cx
; dx = (dx:ax) % cx
```
### MACRO
- something like a inline function
```asm
microName MICRO [parma1, param2]
statment-list
ENDM
```
- e.g.
```asm
mPutchar MICRO char
push eax
mov al, char
call WtiteChar
pop eac
ENDM
.code
mPutchar "A" ; invoke
```
- what actually happend
- copy the code to the invoke line
- replace the param with input
#### Checking for missing Arguments
- IFB
- IFB: If Blank
- EXITM: exit Macro
```asm
IFB <row>
EXITM
ENDIF
```
```asm
mWriteChar MICRO str
IFB str
ECHO "str is blank!!"
ECHO "QUITE!!!"
ECITM
ENDIF
EDNM
```
## advence proc
- stack param
- `abel proc paramList`
```asm
label PROC,
param1: type1
param2: type2
```
```asm
invoke procName [ param1, param2, param3]
# same as
push param3
push param2
push param1
call procName
```
### PROTO Deirective
- creats a procedure prototype
```
label PROTO paramList
```
example:
```
MySub PROTO ; proc pototype
.code
invoke MySub ; call proc
MySub PROC ; definition of proc
ENDPROC
```
### stack Frame
- aka "activation record"
- "caller", "callee"
- Steps:
- 1. push arguments, then call the procedure
- 2. push EBP
- 3. if need local var, `ESP--`, make a room for them
### Stack parameters
```
val1
val2
return addr (old EIP)
EBP(old) <- EBP
```
example
```
### stack ###
----- proc2 -----
0x00 0x44 (local variable of proc2)
0x04 0x048 (old EIP od proc1)
0x08 0x08 (old EBP of proc1)
----- proc2 -----
----- proc1 ------
0x0c 0x33 (local vaiable in proc1)
0x10 0x22 (local variable in proc1)
0x14 0x030 (return addr (old EIP in proc0))
0x18 0x00 (old EBP of proc0)
----- proc1 -----
...
### code ###
----- proc1 ---
0x040 xor eax, eax
0x044 call proc2 <-- call proc2
0x048 mov eax, [ebp-8] <-- mov local variable in proc1
0x04c ret
--------------
----- proc2 ---
0x60 xor ecx, ecx
0x68 xor ecx, [ebp-8] <-- mov local variable in proc2
0x6c ret
--------------
```
```
val1 -> [ebp - 8]
val2 -> [ebp - 12]
```
### RET Instruction
## local variable
```
MySub PROC
push ebp
mov ebp, esp
sub esp, 8 ; creat 8 byte space
mov [ebp-4], 10 ; localVar1 = 10
mov [ebp-8], 20 ; localVar2 = 20
```
### LEA Instruction
when a address is offered in runtime, `OFFSET` is invailed
```
CopyString PROC, count:DWORD
LOCAL temp[20]:BTYE ; declare a variable name
mov edi, OFFSET temp ; invailed expression :not_good:
lea edi, count ; :good:
lea esi, temp
```
### ENTER Instruction
```
MtSub PROC
enter 8, 0
; ## as same as
MySub PROC
push ebp
mov ebp, esp
sub esp, 8
```
### LEAVE Instruction
```
leave
; # as same as
mov esp, ebp
pop ebp
```
### LOCAL Dritive
```
MySub PROC,
LOCAL var1:DWORD, var:DWORD
...
ret
```
same as
```
MySub PROC
enter 8, 0
leave
...
ret
```
### INVOKE and ADDR
```
```
## include
.inc
blablabla
==TODO: complete this==
## ep9 Strings and Arrays
### MOVSB
- command:
- MOVSB -> inc/descrements by 1 Byte
- MOVSW -> by 1 word (2)
- MOVSD -> by 4 word
- desctipt
- mov *esi_ptr to *edi_ptr
- then increase/decrease esi and edi
- **Direction Flag**
- DF = clear(0) increse ESI and EDI
- DF = set(1) decrese ESI and EDI
```
cld ; clear DF
mov ecx, LENFTHOF source
mov esi, OFFSET source
mov edi, OFFSET target
rep movsd ; repeat {ECX} times
; result: all of the element in source is moved to target
```
### Compare a pair of dword
- command
- CMPSB
- CMPSW
- CMPSD
- description
- compare two *ptr (esi - edi)
- increase/decrease esi, edi
```
mov esi, source
mov edi ,taerget
cmpsd ; compare double word
```
### SCASB (scan)
- command
- SCASB
- SCASW
- SCASW
- description
- comapre a value in AL/AX/EAX to EDI
- increase/decrease EDI
```
repe command ; repeat while equal
repne command ; repeat while not equal
```
```
mov edi, OFFSET myArray
mov al, 'F'
mov ecx, LENGTHOF myArray
cld ; clear Drection Flag
repne scasb ; repeat while not qual or ecx == 0
jnz quite ; if equal
dec dei
```
### STOSB (store)
- command
- STOSB
- STOSW
- STOSD
- descript
- store [edi] to AL/AX/EAX
- increase/decrease ESI
### LODSB (load)
- command
- LODSB
- LODSW
- LODSD
- descript
- load a byte/word/dword from [ESI] into AL/AX/EAX
- increase/decrease ESI
## Structure
### Using a structure
```asm
name STRUCT
field-declarations
name ENDS
```
#### e.g.: COORD Struture
- used by MS-Windows progeaming liabrary
- the menber in the structure is continuouse in memory
```
COORD STRUCT
x WORD ? ; offset 00
y WORD ? ; offset 02
COORD ENDS
.data
setOfCorrdinates COORD 10 DUP(<>) ; 尖括弧是 constructor,間括號裡為空即不給它初始值(<>)
mov ebx, OFFSET setCoordinates
mov esi, 2
mov eax, 0
mov ecx, LENGTHOF setcoordinates
L1 :
mov ax, [ebx+esi]
call WriteDec
add ebx, SIZEOF COORD ; === Type setOfCorrdinates
loop L1
; OFFSET coord === coord.x
; OFFSET coord +4 === coord.y
```
### another example: Employee Structure
- A structure for combining field of different types
```asm
Employee STRUCT
IdNum BYTE "00000000"
LastName BYTE 30 DUP(0)
ALIGN DWORD ; add 2 Byte to ALIGN
SalaryHistory DWORD 0,0,0,0
Employee ENDS
```
### Data Aligment
- discript:
- align the data above the command
- command:
- `ALIGN WORD`
- `ALIGN DWORD`
### Referencing Structure Variable
- use "."
```asm...
mov dx,worker.Years
mov worker.Salary,20000
movworkerHistory + 4,30000
mov edx,OFFSET worker.LastName
mov esi,OFFSET worker
mov eax,(Employee PTR [esi]).Years
mov ax, [esi].Years ; :x: invaild operand (ambiguous)
```
### Looping Through an Array of Points
```asm
.data
NumPoints = 3
AllPoints COORD NumPoints DUP(<0,0>)
.code
mov edi,0
mov ecx,NumPoints
mov ax,1
L1 :
mov (COORD PTR AllPoints[edi]).X,ax
mov (COORD PTR ALLPoints[edi]).Y,ax
add edi,Type COORD
inc ax
Loop L1
```
### GuideNode
```asm
Employee STRUCT
IdNum Byte "000000000" ; 9 Byte
LastName Byte 30 Dup() ; 30 Byte
ALIGN WORD ; 1 Byte ; total: 40
Years WORD 0 ; 1 Byte
ALIGN DWORD ; 2 Byte ; total:2
YSalaryHistory DWORD 0,0,0,0,0 ; 20 Byte
Employee ENDS
; size of Employee: 64
.data
worker Employee <>
RD_Dept Employee 10 DUP(<>)
;Whats value return
Type Employee
Type RD_Dept
SIZEOF Employee
SIZEIF worker
SIZEOF RD_Dept
LENGTHOF RD_Dept
Type Employee.SalaryHistory
LENGTHOF Employee.SalaryHistory
SIZEOF Employee.SalaryHistory
Type Employee.Years
Type worker,IdNum
```
### structure example: Displaying the System time
```
.data
sysTime SYSEMTIME <>
XYPos COORD <10, 5>
consoleHandle Dword ?
.code
INVOKE GetStdHandle, STD_OUTPUT_HANDLE
mov consoleHandle, eax
INVOKE setConsleCursorPosistion, consoleHangle, XYPos
INVOKE GetLocalTime, ADDR sysTime
mov edx, OFFSET TheTimeis ; TheTimeis = string "the time is"
call WriteString
movzx eax, sysTeim.wHiur
call WriteDec
mov edx, offset colonStr ; ":"
call WriteString
movzx eax, sysTime.wMintue
call WriteDec
mov edx, offset colonStr
call WriteString
mozx eax, sysTine.wSecond
call WriteDec
```
### Nested Structures
- Define a structure that contains other structures
- Used nested braces(or brackets) to initialize
## Unions
- descript
- all member share the same OFFSET memory
- can only regist one member at a time
```
unionName UNION
menber
unionName ENDS
```
### examples
```
Integer UNION
D DWORD 0
W WROD 0
B BYTE 0
Integer ENDS
```
### Checking for Missing Argument
```asm
IFB<row>
EXITM //Exit the macro
ENDIF
```
## Some Content that i missed
## Expansion(%) at beginning of the line
### EQU
### TEXTEQU
- something like `#define` in C++
```
rowSize=5
count TEXTEQU %(rowSize*2)
move TEXTEQU <mov>
```
### Special Operators: literal-Character(!)
```
; the expression is ambiguous :not_ok:
BadValue TEXTEQU Warning: <Y-coordinate is > 24>
```
```
; use special operators :ok:
BadValue TEXTEQU Warning: <Y-coordinate is !> 24>
```
### FOR Directive
```
FOR parameter, <arg1, arg2>
statment
ENDM
```
like for each
```
for elements in list<a, b, c, d>
//do something to element
```
example:
```
Window STRUCT
FOR color, <fram, titlebar, background, foreground>
color DWORD ?
ENDM
Window ENDS
```
### FORC
- description: for each char in string
- command:
```
FORC code, <ABCDEFG>
Group_&code WORD ?
ENDM
; it will generate code
Group_A WORD ?
Group_B WORD ?
Group_C WORD ?
...
...
```
## MS-Windows Programming
- API & SDK
- Miscrosoft Win32 Application Programming interface
- API: a collection of types, constants, ...
- Miscrosoft Platform Software Development Kit
- SDK: a collection of tools, libs, somaple code...
### standard Console Handles
- a handle is a 32-bit integer
- STD_INPUT_HANDLE
- STD_OUTPUT_HANDLE
- STD_ERROR_HANDLE
#### GetStdHandle
- Prototype:
```
; return value: at EAX
GetStdHandle PROTO,
nStdHandle: DWORD ;handle type
```
### Console Window Am
### Screen Biffer and Console Window
### SetConsoleTitle
examples:
```
.data
titleStr Byte "a example title", 0
.code
INVOKE SetConsoleTitle addr titleStr
```
### GetConsoleScreenBufferInfo
```
.data
outHandle DWORD ?
consoleInfo CONSOLE_SCREEN_BUFFER_INFO <>
.code
INVOKE GetHandle, ; get handle
nStdHandle
mov outHandle, eax
INVOKE GetConsoleScreenBufferInfo, ; get buffer
outHandle, ; the handle
ADDR consoleInfo ; the retun value will saved in `consoleInfo`
```
### CONSOLE_SCREEN_BUFFER_INFO
```
CONSOLE_SCREEN_BUFFER_INFO STRUCT
dwSize COORD<>
dwCursorPos COORD<>
wArribute DWROD ?
```
```
```
# NULL
:::danger
:::
## FLoting number
### FPU Instructino Set
#### operands
- zero one, or two
- no immediate operands
- no general-purpose register (EAX, EBX)
- integers must be loaded from memory onto the `stack` and convert to `float` type
- no Memory to memory
### Loading Constants
- FLD1 1
- FLD2T = $log_2 10$
### Store
- FST
- copies floating point operand from the top of the FPU stack into memory
- FST m32fp
- FST m64fp
- FSTP
- pops the stack after copying
### Arithmetic Instructions
- `FCHS`: ChangeSign
- `FADD`
- `FSUB`
- `FMUL`
- `FDIV`
### Compare
- FCOM === `Compare ST(0) to ST(1)`
- FCOM m32fp === `Compare ST(0) to m32fp`
- FCOM m64fp === `Compare ST(0) to m64fp`
#### Condition codes set by FPU
- descript: similiar to CPU flags
- `C3` === zero flag
- `C2` ===
- `C1` === carry flag