# 組合語言 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> ![ROR_img](https://i.stack.imgur.com/pFTAH.png) </br> ![RCR_img](https://i.stack.imgur.com/A4NyR.png) ## 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