5. Lệnh Mul và Div
Cú pháp:
- Mul [Toán hạng nguồn]
- IMul [Toán hạng nguồn]
- Div [Toán hạng nguồn]
- IDiv [Toán hạng nguồn]
Trong đó: [Toán hạng nguồn]có thể là thanh ghi hay ô nhớ. Với các lệnh nhân: [Toán hạng đích] ngầm định là thanh ghi Al hoặc Ax. Với các lệnh chia: [Toán hạng đích] là một trong các thanh ghi đa năng Ax, Bx,...
Tác dụng:
- Lệnh Mul (Multiply): Thực hiện phép nhân trên số không dấu. Nếu [Toán hạng nguồn] là toán hạng 8 bít thì lệnh sẽ nhân nội dung của [Toán hạng nguồn] với giá trị thanh ghi AL, kết quả 16 bít chứa ở thanh ghi Ax.
Nếu [Toán hạng nguồn] là toán hạng 16 bít thì lệnh sẽ nhân nội dung của [Toán hạng nguồn] với giá trị thanh ghi Ax, kết quả 32 bít chứa ở cặp thanh ghi Dx:Ax, phần thấp ở Ax, phần cao ở Dx. Nếu phần cao của kết quả (AH hoặc DX) bằng 0 thì các cờ CF = 0 và OF = 0.
- Lệnh IMul (Interger Multiply): Tương tự lệnh Mul nhưng thực hiện phép nhân trên hai số có dấu. Kết quả cũng là một số có dấu.
- Lệnh Div (Divide): Thực hiện phép chia trên số không dấu. Nếu [Toán hạng nguồn] là toán hạng 8 bít thì lệnh sẽ lấy giá trị của thanh ghi Ax (số bị chia) chia cho [Toán hạng nguồn] (số chia), kết quả thương số chứa trong thanh ghi Al, số dư chứa trong thanh ghi Ah.
Nếu [Toán hạng nguồn] là toán hạng 16 bít thì lệnh sẽ lấy giá trị của cặp thanh ghi Dx:Ax (số bị chia) chia cho [Toán hạng nguồn] (số chia), kết quả thương số chứa trong thanh ghi Ax, số dư chứa trong thanh ghi Dx.
Nếu phép chia cho 0 xảy ra hay thương số vượt quá giới hạn của thanh ghi AL (chia 8 bít) hay Ax (chia 16 bít) thì CPU sẽ phát sinh lỗi “Divice overflow”.
- Lệnh Idiv (Integer Divide): Tương tự lệnh Div nhưng thực hiện phép chia trên hai số có dấu. Kết quả cùng là các số có dấu.
Ví dụ 1:
- Mul Bl ; Ax ßAL * Bl: số bị nhân ngầm định trong Al
- Mul Bx ; Dx:Ax ßAx * Bx: số bị nhân ngầm định trong Ax
- Idiv Bl ; Ax/Bl, thương số chứa trong Al, số dư chứa trong Ah
- Idiv Bx ; Dx:Ax/Bx, thương số chứa trong Ax, số dư trong Dx
Ví dụ 2: Dãy các lệnh dưới đây sẽ thực hiện phép gán A = 4*A – 3*B, trong đó A và B là các biến kiểu word:
Mov Ax, 4 ; số nhân phải được chứa trong Ax
IMul A ; thực hiện phép nhân
Mov Bx, Ax ; lưu tạm kết quả vào Bx
Mov Ax, 3 ; Ax = 3
Imul B ; Ax = Ax * B
Sub Bx, Ax
Mov A, Bx ; đặt kết quả cuối cùng vào A
Trong trường hợp này ta đã giả sử hiện tượng tràn đã không xảy ra và kết quả phép nhân chỉ chứa trong thanh ghi Ax.
Ví dụ 3: Các lệnh sau đây thực hiện phép: chia -123 cho 24:
Mov Ax, -123 ; đặt số bị chia vào Ax
Mov Bl, 24 ; đặt số chia vào Bl (thanh ghi 8 bít)
Idiv Bl ; chia Ax cho Bl, kết quả chứa ở Al và Ah
Ví dụ 4: Dãy lệnh dưới đây sẽ thực hiện phép gán A = N! (tính N giai thừa). A là một biến word:
Mov Ax, 1 ; chuẩn bị Ax để lưu kết quả
Mov Cx, N ; tính N!
LapNhan:
Mul Cx ; Ax ßAx * Cx
Loop LapNhan
;---------------------------
Mov A, Ax ; trả kết quả vào biến A
Trong trường hợp này chúng ta giả sử kết quả không vượt quá gới hạn 16 bít.
Chúng ta đã biết: N! = 1 nếu N = 1, N! = N*(N-1)*(N-2)*...*1 nếu N>1, điều này hoàn toàn phù hợp với sự thay đổi của thanh ghi CX trong lệnh lặp Loop. Do đó, ở đây ta có thể sử dụng CX như là N trong biểu thức tính giai thừa.
Chú ý: Hợp ngữ cung cấp lệnh AAM (Ascii Adjust for Multiple) để điều chỉnh kết quả phép nhân trên 2 số BCD dạng không dồn. Và lệnh AAD (Ascii Adjust for Division) để điều chỉnh kết quả phép chia trên 2 số BCD dạng không dồn. Ngoài ra còn có lệnh CBW (Convert Byte to Word) và lệnh CWD (Convert Word to Doubleword) để hỗ trợ cho phép chia trên các số có dấu [2 – 187-200].
Lệnh IMul của vi xử lý Intel 80286 cho phép ghi rõ [Toán hạng đích], [Toán hạng nguồn] trong câu lệnh, các lệnh này có thể có đến 3 toán hạng [1 - 541].
6. Lệnh logic: NOT – AND – OR – XOR – TEST
Trước khi tìm hiểu về các lệnh logic chúng ta xem lại kết quả thực hiện các phép tính logic trên 2 bít nhị phân A và B thông qua bảng sau đây:
A
|
B
|
A And B
|
A Or B
|
A Xor B
|
NotA
|
0
|
0
|
0
|
0
|
0
|
1
|
0
|
1
|
0
|
1
|
1
|
1
|
1
|
0
|
0
|
1
|
1
|
0
|
1
|
1
|
1
|
1
|
0
|
0
|
Bảng trên cho thấy: Với phép And: kết quả = 1 chỉ khi cả hai bít = 1; Với phép Or: kết quả = 0 chỉ khi cả hai bít = 0; Với phép Xor: kết quả = 0 khi hai bít giống nhau, kết quả = 1 khi hai bít khác nhau. Với phép Not: 0 thành 1, 1 thành 0.
Cú pháp:
- Not [Toán hạng đích]
- And [Toán hạng đích], [Toán hạng nguồn]
- Or [Toán hạng đích], [Toán hạng nguồn]
- Xor [Toán hạng đích], [Toán hạng nguồn]
- Test [Toán hạng đích], [Toán hạng nguồn]
Trong đó: [Toán hạng đích], [Toán hạng nguồn] có thể là hằng số (trực hằng), biến, thanh ghi hay địa chỉ ô nhớ. [Toán hạng đích] không thể là hằng số.
Tác dụng: Mỗi lệnh logic thực hiện phép tính logic tương ứng trên các bít (tương ứng về vị trí) của [Toán hạng đích] và [Toán hạng nguồn], kết quả được ghi vào lại [Toán hạng đích]. Riêng lệnh Not, thực hiện phép đảo bít ngay trên các bít của [Toán hạng đích]. Hầu hết các lệnh logic đều ảnh hưởng đến các cờ CF, OF, ZF,...
- Lệnh Not (Logical Not): Thực hiện việc đảo ngược từng bít trong nội dung của [Toán hạng đích]. Lệnh này không làm ảnh hưởng đến các cờ.
Lệnh Not thường được sử dụng để tạo dạng bù 1 của [Toán hạng đích].
- Lệnh And (Logical And): Thực hiện phép tính logic And trên từng cặp bít (tương ứng về vị trí) của [Toán hạng nguồn] với [Toán hạng đích], kết quả lưu vào [Toán hạng đích].
Lệnh And thường được sử dụng để xóa (= 0) một hoặc nhiều bít xác định nào đó trong một thanh ghi.
- Lệnh Or (Logical Inclusive Or):Thực hiện phép tính logic Or trên từng cặp bít (tương ứng về vị trí) của [Toán hạng nguồn] với [Toán hạng đích], kết quả lưu vào [Toán hạng đích].
Lệnh Or thường dùng để thiết lập (= 1) một hoặc nhiều bít xác định nào đó trong một thanh ghi.
- Lệnh Xor (eXclusive OR):Thực hiện phép tính logic Xor trên từng cặp bít (tương ứng về vị trí) của [Toán hạng nguồn] với [Toán hạng đích], kết quả lưu vào [Toán hạng đích].
Lệnh Xor thường dùng để so sánh (bằng nhau hay khác nhau) giá trị của hai toán hạng, nó cũng giúp phát hiện ra các bít khác nhau giữa hai toán hạng này.
- Lệnh Test: Tương tự như lệnh And nhưng không ghi kết quả vào lại [Toán hạng đích], nó chỉ ảnh hưởng đến các cờ CF, OF, ZF,...
Ví dụ 1:
Mov Al,0 ; Al ß0
Not Al ; Al = Not Al. Tức là Al = 0FFh
Ví dụ 2: Cho AL = (10010011)2, BL = (11001100)2.
- And Al, Bl ; Al ß 10010011 And 11001100. Al =
- And Al, 0 ; Al ß 10010011 And 0. Al =
- Or Bl, Al ; Bl ß 11001100 Or 10010011. Al =
- Or Bl, 4 ; Bl ß 11001100 Or 100. Al =
- Xor Al, Bl ; Al ß 10010011 Xor 11001100. Al =
- Xor Bl, Bl ; Bl ß 11001100 Xor 11001100. Bl = 00000000
Ví dụ 3: Để xóa nội dung thanh ghi nào đó, trong hợp ngữ ta có thể sử dụng một trong các lệnh sau đây:
- Mov Ax, 0
- Sub Ax, Ax
- Xor Ax, Ax ; các cặp bít giống nhau thì đều = 0
Ví dụ 5: Lệnh sau đây sẽ xóa (= 0) các bít 3 và 6 của thanh ghi AL, các bít khác giữ nguyên giá trị:
- And AL, 10110111b ; AL ßAL And 10110111
Trong trường hợp này: dãy bít 10110111 được gọi là dãy bít mặt nạ, các bít 3 (= 0) và 6 (= 0) được gọi là các bít mặt nạ. Như vậy muốn làm cho bít nào = 0 ta cho bít mặt nạ tương ứng với nó = 0, các bít còn lại trong dãy bít mặt nạ đều = 1.
Ví dụ 6: Lệnh sau đây sẽ thiết lập (= 1) các bít 3 và 6 của thanh ghi AL, các bít khác giữ nguyên giá trị:
- Or AL, 01001000b ; AL ßAL Or 01001000
Trong trường hợp này: dãy bít 01001000 được gọi là dãy bít mặt nạ, các bít 3 (= 1) và 6 (= 1) được gọi là các bít mặt nạ. Như vậy muốn làm cho bít nào = 1 ta cho bít mặt nạ tương ứng với nó = 1, các bít còn lại trong dãy bít mặt nạ đều = 0.
Ví dụ 7: Lệnh sau đây sẽ kiểm tra bít 12 của thanh ghi AX là = 0 hay = 1:
- And AX, 0001000000000000b ; AX ßAX And 0001000000000000
Với dãy bít mặt nạ như trên, nếu bít 12 của Ax = 0 thì kết quả: Ax = 0, nếu bít 12 của Ax = 1 thì kết quả: Ax <> 0.
Cách dùng lệnh And như trên để kiểm tra bít ít được sử dụng, vì nó làm thay đổi giá trị của thanh ghi cần kiểm tra (điều này có thể khắc phục bằng lệnh Test) và phải thêm bước kiểm tra giá trị của Ax (= 0 hay <> 0) mới biết được kết quả kiểm tra. Ngoài ra, nó cũng chỉ kiểm tra được 1 bít.
Trong thực tế người ta thường sử dụng kết hợp giữa các lệnh dịch bít, lệnh quay bít, lệnh nhảy,... để kiểm tra các bít trong một thanh ghi.
7. Lệnh chuyển dữ liệu qua cổng: IN và OUT
Cú pháp:
- IN AL, <Địa chỉ cổng>
- OUT <Địa chỉ cổng>, AL
Trong đó:<Địa chỉ cổng> chính là số hiệu cổng (port) mà lệnh nhận nhiệm vụ trao đổi dữ liệu qua nó. Địa chỉ cổng có thể được ghi trực tiếp dưới dạng một hằng số hoặc được ghi thông qua thanh ghi Dx.
Tác dụng:
- LênhIn (Input): Đọc một lượng dữ liệu 8 bít từ cổng được chỉ ra ở <Địa chỉ cổng> đưa vào lưu trữ trong thanh ghi AL.
Nếu địa chỉ cổng nằm trong giới hạn từ 0 đến FF (hệ thập lục phân) thì có thể viết trực tiếp trong câu lệnh, nếu địa chỉ cổng lớn hơn FF thì ta phải dùng thanh ghi Dx để chỉ định địa chỉ cổng.
- LệnhOut (Output): Gởi một lượng dữ liệu 8 bít từ thanh ghi AL ra cổng được chỉ ra ở <Địa chỉ cổng>. Tương tự lệnh In, địa chỉ cổng có thể được viết trực tiếp trong câu lệnh hoặc thông qua thanh ghi Dx.
Ví dụ 1:
- In Al, 40h ;
- Mov Dx, 3B0h ;
In Al, Dx ;
Ví dụ 2:
- Out 40h, Al ;
- Mov Dx, 3B0h ;
Out Dx, Al ;
Ví dụ 3:
Các khai báo hằng:
DAT EQU 13h ;
POR EQU 7Ch ;
Các lệnh:
Mov Al, POR ;
Mov Bl, DAT ;
Out Bl, Al ;
0 Comment:
Đăng nhận xét
Thank you for your comments!