--- tags : 微算機與組合語言 --- ###### 國立臺北大學資工系江宥旻 8088/8086 programming - Integer instructions and computations === Data transfer instructions --- + MOV + Copy value from source operand to destination operand + XCHG + Exchange the data of two operands + XLAT + For lookup-table operation + LEA, LDA, LES + LEA:load register with effective address + LDS:load register and data segment register + 找.DATA在哪(找資料區在哪) + LES:load register and extra segment register ### MOV ```asm MOV DX, CS ``` ![mov-inst](https://i.imgur.com/M7XOQRX.png =300x) ![mov-mem](https://i.imgur.com/EZ5GeJu.jpg) Memory reference MOV instructions ```asm MOV [SUM], AX ``` Destination address PA + DS * 16 + SUM > For example DS = 0200h, SUM = 1212h, PA = 200h*16 + 1212h= 3212h + (AL) -> (memory location 03212h) + (AH) -> (memory location 03213h) > little endian ```asm .data SUM DW ;資料區宣告變數 ``` + DB:define byte + DW:define word (2Bytes) + DD:define double word (4Bytes) ```asm MOV AX, 310 MOV BX, 420 MOV CX, AX MOV DH, AH MOV DL, BH MOV DX, AX ``` ![m1](https://i.imgur.com/aq9KSF0.png =200x)![m2](https://i.imgur.com/D7ld9jc.png =200x)![m3](https://i.imgur.com/6AQoPNB.png =200x) ![m4](https://i.imgur.com/dLoiPI9.png =200x)![m5](https://i.imgur.com/RFEfynF.png =200x)![m6](https://i.imgur.com/oULbQ1D.png =200x) ### XCHG ```asm XCHG AX, BX ``` > Var1 Var2 對調 > Temp = Var1 > Var1 = Var2 > Var2 = Temp ![xchg-inst](https://i.imgur.com/bC5wiqh.jpg =400x) ![xchg-mem](https://i.imgur.com/42S8QH1.jpg) ```asm MOV AX, 123 MOV BX, 234 XCHG AX, BX ``` ![xc1](https://i.imgur.com/uqb9O3z.png =200x)![xc2](https://i.imgur.com/a2LPKDP.png =200x)![xc3](https://i.imgur.com/IJAII6h.png =200x) ### XLAT 查表轉換,類似從陣列中找尋資料。 + `BX` represent the offset of the `starting address` of the lookup table from the beginning of the current data segment + `AL` represent the offset of the `element to be accessed from the beginning` of the lookup table + XLAT:AL<-(DS*16 + BX + AL),AL一開始是index,經過XLAT轉換成arr[index]的值。 > BX代表陣列的起始位址(arr[0]),利用AL去遍歷(arr[index]) ![xlat-inst](https://i.imgur.com/ztCMWOz.jpg =500x) ![xlat-mem](https://i.imgur.com/p0eaerW.jpg =400x) 資料在資料區,所以用DS:BX去找到陣列起始的實體位址,DS * 16 + BX + AL去找我們要的資料。 ```asm MOV AL, 8 MOV BX, 0100 XLAT ``` ### LEA, LDS, LES Loading a segment and a general purpose register with an address directly from memory ![lll](https://i.imgur.com/lk9m7AQ.jpg =400x) ![lll-mem1](https://i.imgur.com/EIpNcFn.jpg =300x)![lll-mem2](https://i.imgur.com/9SyYd9z.jpg =300x) Arithmetic instructions --- > [8086/8088指令](https://www.796t.com/content/1548365764.html) + Operations + Addition + Subtraction + Multiplication + Division + Operands format + Signed & Unsigned + Byte, word + Packed & Unpacked + Decimal bytes + ASCII numbers ![op](https://i.imgur.com/KiVbgx3.jpg =300x) ### Addtion instructions Addtion instruction + `ADD` + `ADC` + `INC` + `AAA` + `DAA` ![adi](https://i.imgur.com/VHPaHiu.jpg =500x) --- ADD ```asm MOV AX, 1100 MOV BX, 0ABC ADD AX, BX ``` ![add](https://i.imgur.com/vtQvhGx.jpg) ADC + Add with carry + S + D + CF -> D INC + Increment (++) + INC AH + AH + 1 -> AH ```asm MOV AL, 0E1H ;E1H被視為符號,則前面要加一個0才會被視為數字 MOV BL, 0A3H ADD AL, BL ADC AL, 1 ;AL + 1 + CF -> AL INC AL ``` :::info BCD碼:用四個二進制位表示一個十進制數字,最常用的是8421 BCD碼 **壓縮型BCD碼 v.s. 非壓縮型BCD碼** 壓縮型BCD碼:一個位元組(1 Byte)可存放一個`兩位`十進制數,其中高四位元存放十位數字,低四位存放個位數字。如:56的壓縮型8421 BCD碼是0101 0110 非壓縮型BCD碼:一個位元組(1 Byte)只可存放一個`一位`十進制數,其中高字節為0,低字節的低四位元存放個位。如:5的非壓縮型BCD碼是0000 0101,必須存放在一個位元組中,56的非壓縮型BCD碼是00000101 00000110,必須存放在兩個位元組中。 ::: AAA + 非壓縮型BCD + `ASCII adjust for addition` + Should be executed immediately after the ADD instruction that adds ASCII data + 如果AL最低4個bits大於9或AF=1,則AH = AH + 01H,AL = AL + 06H,把AF和CF設置為1,且把AL的最高4個bits設為0。 + 若不滿足,則將高四位、AF和CF設置為0。 + 使用AAA指令時,通常先執行ADD/ADC指令,以AL為目的運算元,將兩個非壓縮BCD碼(與AH無關)相加,然後使用AAA將AL調整為非壓縮BCD碼格式,且AL高4位元等於0,同時,將調整產生的進位加到AH中。 ```asm MOV AL, 38H MOV BL, 39H ADD AL, BL ;AL = 77H AAA ;AX = 0107H, AH = 01H, AL = 07H ``` DAA + 壓縮型BCD + `Decimal adjust for addition` + Addition of packed `BCD` numbers + 如果AL的最低4個bits大於9或AF = 1,則AL + 06H,並將AF設置為1 + 如果AL的最高4個bits大於9或CF = 1,則AL + 60H,並將CF設置為1 + 若都不滿足,則將AF和CF設置為0 + 使用DAA指令時,通常先執行ADD/ADC指令,將兩個壓縮BCD碼相加,結果存放在AL中,然後使用該指令將AL調整為壓縮BCD碼格式。 ```asm ;低位元大於9 MOV AL, 1CH MOV BL, 36H ADD AL, BL ;1CH + 36H = 52H DAA ;BCD = 58H ;高位元大於9 MOV AL, 50H MOV BL, 54H ADD AL, BL ;50H + 54H = A4H DAA ;BCD = 04H ;高低位元大於9 MOV AL, 62H MOV BL, 88H ADD AL, BL ;62H + 88H = EAH DAA ;BCD = 50H ``` ### Subtraction instructions Subtraction instruction + `SUB` + `SBB` + `DEC` + `AAS` + `DAS` + `NEG` `取2補數` > 把CF當作借位 ![subi](https://i.imgur.com/lIfkKsZ.jpg =500x) --- 減法的操作和加法差不多,在此就不多做著墨了:stuck_out_tongue_winking_eye:。 NEG ```asm MOV AX, 72H NEG AX ;AX = FF8E ;用0去減,CF = 1,實際上已經做了1's complement然後再加1 ``` ### Multiplcation and Division instructions Multiplcation and Division instruction + `MUL` + $8bits * 8bits \leq 16bits$ + $16bits * 16bits \leq 32bits$ + **如果result超過32bits的話,就會用DX:AX表示** + `DIV` + $32bits \div 16bits$ + $16bits \div 8bits$ + `IMUL (integer)` + `IDIV (integer)` + `AAM` + `AAD` + `CBW` + 為了讓加減乘除的bits數相同 + 資料轉移 + 把符號位元(SF)`擴展到DX` + `CWD` + 為了讓加減乘除的bits數相同 + 資料轉移 + 把符號位元(SF)`擴展到DX` ![mdi](https://i.imgur.com/zRYKtQg.png) > 目的地固定是AX或DX:AX > Logic Instructions --- AND OR NOT XOR > bitwise (一個一個bit運算) ![logic](https://i.imgur.com/neHSQWz.png =500x) ```asm MOV AL, 01010101B AND AL, 00011111B OR AL, 11000000B XOR AL, 00001111B NOT AL ``` ![res](https://i.imgur.com/xShwmGS.png =300x) Shift instructions --- Logic shift & Arithmetic shift :::info **Logic shift v.s. Arithmetic shift** Logic shift : 不管正負號 Arithmetic shift : 正負號 ::: ![shi](https://i.imgur.com/eHrmnua.png) > SHL和SAL的指令意義相同,但是SHR和SAR的指令意義不相同 + SAL/SHL ```asm MOV AX, 1234H SHL AX, 1 ;也可以用SAL AX, 1 ;左移1個bit(從右邊往左邊補0,把擠出去bit的送至CF) ;AX = 2468H ``` ![shiex1](https://i.imgur.com/BfNxnU0.png) + SHR ```asm MOV AX, 1234H MOV CL, 2 SHR AX, CL ;不等同於SAR AX, CL ;右移1個bit(從左邊往右邊補0,把擠出去bit的送至CF) ;AX = 048DH ``` ![shiex2](https://i.imgur.com/Ug2lJ3D.png) + SAR ```asm MOV AX, 91DH MOV CL, 2 SAR AX, CL ;AX = 0246H ;算術右移兩次 ;原本的 0000100100011010 ;第一次 0000010010001101 CF = 0 ;第二次 0000001001000110 CF = 1 ``` ![shiex3](https://i.imgur.com/n2WVBgy.png) > SAR和SHR最大的不同是,SAR補的是sign bit,而非像SHR補0 :::success 負數移位時會經過2's complement運算。 ::: Rotate instructions --- ![ri](https://i.imgur.com/bg0fwGh.png =500x) + ROL ```asm MOV AX, 1234H ROL AX, 1 ``` ![riex1](https://i.imgur.com/JDqsKsX.png) > 與SHL的不同是,會把擠出去的bit補到LSB同時也送至CF + ROR ```asm MOV AX, 1234H MOV CL, 4 ROR AX, CL ``` ![riex2](https://i.imgur.com/cVIH63Q.png) > 與SHR的不同是,會把擠出去的bit補到MSB同時也送至CF + RCL ![riex3](https://i.imgur.com/0JAQtU4.png) 1. CF初始值為0 2. 往左移時,擠出去的bit送至CF,並把原CF的值補至LSB > 與ROL的不同是,可以把CF想像成新的MSB,且CF的初始值為0 + RCR 1. CF初始值為0 2. 往右移時,擠出去的bit送至CF,並把原CF的值補至MSB > 與ROR的不同是,可以把CF想像成新的LSB,且CF的初始值為0 小補充 --- ```asm ; output:com org 100h ;程式啟始位址為100H .data ;宣告資料區 msg db "Hello, World", 0dh, 0ah, 24h ;db(define byte), od, oa代表換行, 24h為字串的結尾 .code ;宣告程式區 mov ax, @data mov ds, ax mov dx, offset msg mov ah, 9 int 21h ;作業系統呼叫印出一字串 .exit ``` [INT 21H 指令說明及使用方法](https://www.796t.com/content/1548310330.html) ![example](https://i.imgur.com/sLlvGGD.png =200x) :::info Q:假設100h是程式起始的位址,那麼000h~100h是用來幹嘛的呢? A:是用來存放環境變數及輸入的參數。 ::: exercise ```c int a = 9; int b = 5; a += b; printf("%d", a); ``` ```asm ; this example shows the use of aaa instruction (ascii adjust after addition). ; it is used to add huge bcd numbers. name "bcd_aaa" org 100h ; first number '9': mov ah, 09h ; second number '5': mov al, 05h ; al = al + ah = ; = 09h + 05h = 0eh add al, ah ; clear tens byte of bcd ; result: xor ah, ah ; adjust result to bcd form, ; ah = 1, al = 4 -> '14' aaa ; print the result: ; store contents of ; ax register: mov dx, ax ; print first digit: mov ah, 0eh ; convert to ascii: or dh, 30h mov al, dh int 10h ; print second digit: ; convert to ascii: or dl, 30h mov al, dl int 10h ; wait for any key press: mov ah, 0 int 16h ret ; return control to operating system. ``` 參考資料 + Barry B. Bery, “The Intel Microprocessors,” 8th Edition, 2009, Prentice Hall. + Walter A. Triebel, Avtar Singh, “The 8088 and 8086 Microprocessors – Programming, Interfacing, Software, Hardware, and Applications,” 4th Edition, 2003, Prentice Hall. + 國立臺北大學資工系張玉山教授ppt