---
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
```


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
```


### XCHG
```asm
XCHG AX, BX
```
> Var1 Var2 對調
> Temp = Var1
> Var1 = Var2
> Var2 = Temp


```asm
MOV AX, 123
MOV BX, 234
XCHG AX, BX
```

### 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])


資料在資料區,所以用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


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

### Addtion instructions
Addtion instruction
+ `ADD`
+ `ADC`
+ `INC`
+ `AAA`
+ `DAA`

---
ADD
```asm
MOV AX, 1100
MOV BX, 0ABC
ADD AX, BX
```

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當作借位

---
減法的操作和加法差不多,在此就不多做著墨了: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`

> 目的地固定是AX或DX:AX
>
Logic Instructions
---
AND OR NOT XOR
> bitwise (一個一個bit運算)

```asm
MOV AL, 01010101B
AND AL, 00011111B
OR AL, 11000000B
XOR AL, 00001111B
NOT AL
```

Shift instructions
---
Logic shift & Arithmetic shift
:::info
**Logic shift v.s. Arithmetic shift**
Logic shift : 不管正負號
Arithmetic shift : 正負號
:::

> SHL和SAL的指令意義相同,但是SHR和SAR的指令意義不相同
+ SAL/SHL
```asm
MOV AX, 1234H
SHL AX, 1 ;也可以用SAL AX, 1
;左移1個bit(從右邊往左邊補0,把擠出去bit的送至CF)
;AX = 2468H
```

+ SHR
```asm
MOV AX, 1234H
MOV CL, 2
SHR AX, CL ;不等同於SAR AX, CL
;右移1個bit(從左邊往右邊補0,把擠出去bit的送至CF)
;AX = 048DH
```

+ SAR
```asm
MOV AX, 91DH
MOV CL, 2
SAR AX, CL
;AX = 0246H
;算術右移兩次
;原本的 0000100100011010
;第一次 0000010010001101 CF = 0
;第二次 0000001001000110 CF = 1
```

> SAR和SHR最大的不同是,SAR補的是sign bit,而非像SHR補0
:::success
負數移位時會經過2's complement運算。
:::
Rotate instructions
---

+ ROL
```asm
MOV AX, 1234H
ROL AX, 1
```

> 與SHL的不同是,會把擠出去的bit補到LSB同時也送至CF
+ ROR
```asm
MOV AX, 1234H
MOV CL, 4
ROR AX, CL
```

> 與SHR的不同是,會把擠出去的bit補到MSB同時也送至CF
+ RCL

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)

:::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