ASSEMBLER 2
Chia sẻ bởi Đỗ Quang Huy |
Ngày 19/03/2024 |
8
Chia sẻ tài liệu: ASSEMBLER 2 thuộc Công nghệ thông tin
Nội dung tài liệu:
Assembler
Bài 2
1. Số có dấu
Bit đầu tiên bên trái được sử dụng làm bit dấu.
0 là dương, 1 là âm.
VD:
11110110: -10
00001010: +10
NX: -10 và +10 không hẳn là giống nhau. Đó là do các số âm được lưu trữ theo dạng thức bù hai.
Để tìm bù hai của 1 số, ta đảo trạng thái các bit và + thêm 1.
VD:
+10 được lưu trữ là 00001010
Đảo trạng thái: 11110101
Cộng thêm 1: 11110101 + 1 = 11110110
Đây là ký hiệu bù 2 của –10.
Do bit cao nhất được dùng làm bit dấu, do đó tầm lớn của số sẽ giảm ½
Bộ xử lý thực hiện phép tính không quan tâm đến dấu của các con số, do đó LTV phải nhớ toán hạng có dấu hay không dấu.
VD:
Mov ax, +16 ;00010000
Add ax, -23 ;11101001
Kết quả là 11111001, cái này là –7, cũng có thể là 249.
2. Lưu trữ ký tự
Máy tính lưu trữ bằng số nhị phân.
Các ký tự được lưu trữ dưới dạng lược đồ mã hoá ký tự, phổ dụng nhất là ASCII (American Standard Code for Information Interchange).
Một chuỗi các ký tự được biểu thị trong bộ nhớ dưới dạng 1 dãy liên tiếp các byte chứa con số.
VD:
“ABC123” là 41h, 42h, 43h, 30h, 31h, 32h
3. Hằng và biểu thức
Nguyên dạng số: là tổ hợp các chữ số và các phần tuỳ chọn: một dấu, một dấu chấm thập phân, và một số mũ.
VD:
5
5.5
-5.5
26.E+05
Các hằng nguyên kết thúc bằng 1 ký hiệu định danh cơ số, nếu không có ký hiệu định danh, ngầm định sẽ là số thập phân.
H: thập lục phân
Q (hoặc o): bát phân
D: thập phân
B: nhị phân
VD:
thập phân: 26, 34d, 34D
thập lục phân: 0F6h, 2BH, 1Ah
Bát phân: 36q, 72Q
Nhị phân: 10101b
Khi một hằng thập lục phân bắt đầu bằng một một mẫu tự, nó phải chứa một số 0 dẫn đầu.
Một biểu thức hằng gồm tổ hợp các nguyên dạng số, các toán tử, các hằng ký hiệu đã được định nghĩa.
Giá trị của biểu thức phải xác định được vào thời gian hợp dịch, và giá trị của nó không thể thay đổi vào thời gian thực hiện (runtime).
VD: các biểu thức liên quan đến nguyên dạng số:
25.3
4 * 20
-3 * 4 / 6
2.301E+04
Một hằng ký hiệu được tạo bằng cách gán một biểu thức theo tên hằng.
VD:
Rows = 5
Columns = 10
tablePos = rows * columns
Các lệnh trên chỉ được đánh giá vào thời gian hợp dịch.
Hằng chuỗi hoặc ký tự: Một hằng có thể biểu diễn cho 1 chuỗi các ký tự, được bao trong các dấu nháy đơn hoặc kép.
Có thể dùng dấu nháy nhúng
VD:
‘ABC’
‘X’
“This is a test”
‘4096’ ; chứa 4 byte, mỗi byte là 1 mã ASCII
“This isn’t a test”
‘Say “hello” to Bill.’
4. Các điều lệnh
Lệnh hợp ngữ gồm: tên, từ gợi nhớ chỉ lệnh, các toán hạng và một chú giải.
Gồm 2 lớp:
Chỉ lệnh: các lệnh thi hành
Chỉ thị: các lệnh cung cấp thông tin để báo cho trình hợp dịch cách phát sinh mã thi hành.
Dạng thức chung: [tên] [từ gợi nhớ] [các toán hạng] [;chú giải]
Một điều lệnh phải viết trên cùng 1 dòng, không vượt quá cột 128. Có thể tiếp tục 1 dòng trên dòng kế tiếp, nếu ký tự cuối của dòng đầu tiên là
VD:
longArray dw 1000h, 1020h, 1030h
1040h, 1050h, 1060h, 1070h, 1080h
Chỉ lệnh: là lệnh được thi hành bởi bộ xử lý theo thời gian thực hiện. Gồm các kiểu: chuyển giao điều khiển, chuyển giao dữ liệu, số học, logic và nhập xuất.
Các chỉ lệnh được trình hợp dịch phiên dịch trực tiếp thành mã máy.
VD:
call MySub ;chuyển giao điều khiển
mov ax, 5 ;chuyển giao dữ liệu
add ax, 20 ;số học
jz next1 ;logic (nhảy nếu ấn định cờ Zero)
in al,20 ;nhập/xuất (đọc từ cổng phần cứng)
Chỉ thị là lệnh ảnh hưởng đên bảng kê chương trình hoặc cách phát sinh mã máy.
VD:
chỉ thị db báo cho trình hợp dịch tạo kho lưu trữ cho 1 biến byte tên count và khởi tạo nó theo 50:
count db 50
chỉ thị stack báo cho trình hợp dịch dành riêng 4096 byte không gian ngăn xếp.
.stack 4096
5. Tên
Tên định danh một nhãn, biến, ký hiệu hoặc từ khoá. Nó có thể chứa các ký tự:
A … Z, a … z : Các mẫu tự
0 … 9 : Các chữ số
? : Dấu hỏi
_ : Dấu gạch dưới
@ : Dấu @
$ : Dấu $
. : Dấu chấm
Quy tắc đặt tên:
Tối đa 247 ký tự (trong MASM)
Không phân biệt chữ hoa, chữ thường.
Ký tự đầu tiên có thể là một mẫu tự, @, _ hoặc $. Tránh dùng @ làm ký tự đầu tiên, vì nó thường được dùng tại đầu của nhiều tên ký hiệu được định nghĩa sẵn.
Tên không trùng với từ dành riêng của trình hợp dịch.
Biến: một vị trí trong vùng dữ liệu của chương trình đã được gán tên.
VD:
count1 db 60 ; biến count1
Nhãn: nếu 1 tên xuất hiện trong vùng mã chương trình, nó được gọi là 1 nhãn.
Nhãn được sử dụng như các dấu giữ cho khi một chương trình cần nhảy hoặc lặp vòng từ vị trí này sang vị trí khác
Nhãn nằm trên một dòng trắng hoặc nằm chung với chỉ lệnh.
VD:
Label1: mov ax, 0
mov bx, 0
…
Label2:
jmp Label1 ; nhảy đến Label1
Từ khoá: là chỉ lệnh hoặc chỉ thị của trình hợp dịch: MOV, ADD, PROC, TITLE, AX, END.
Từ khoá không thể được dùng ngoài ngữ cảnh hoặc dưới dạng các dấu định danh.
VD:
add: mov ax,10
6. Hợp dịch và kết nối
7. Các chỉ thị phân bổ dữ liệu
Biến là ký hiệu dành cho một vị trí trong bộ nhớ nơi lưu trữ một số dữ liệu.
Độ dịch vị(offset) của một biến là khoảng cách từ đầu phân đoạn đến biến đó.
Tên biến sẽ tự động kết hợp với độ dịch vị
VD: khai báo mảng chứa 4 ký tự aList thì aList sẽ chỉ định danh độ dịch vị của ký tự đầu tiên (A).
.data
aList db “ABCD”
Độ dịch vị
Offset của aList = 0
Ta sử dụng chỉ thị phân bổ dữ liệu để phân bổ kho lưu trữ, dựa trên một số kiểu được định nghĩa sẵn.
a) Định nghĩa byte(DB)
Phân bổ cho một hoặc nhiều giá trị 8-bit
[name] DB initval [,initval]…
name: tuỳ chọn
initval: dấu khởi tạo. Có thể là một biểu thức hằng chứa các nguyên dạng số, các ký hiệu được định nghĩa, ký tự, các chuỗi có dấu nháy. Ít nhất phải có 1, nhiều hơn 1 thì sử dụng dâu ‘,’ để phân tách.
Có thể để ở dạng không xác định bằng cách dùng dấu ? thay cho dấu khởi tạo.
VD:
Char1 db ‘A’ ; ký tự ASCII
char2 db ‘A’-10 ; biểu thức
signed1 db –128 ;giá trị có dấu nhỏ nhất
signed2 db +127 ; giá trị có dấu lớn nhất
unsigned db 255 ; giá trị không dấu lớn nhất
myval db ? ; không xác định
Nhiều dấu khởi tạo:
list db 10,20,30,40
Các ký tự và số nguyên là như nhau đối với trình hợp dịch. Các biến dưới đây chỉ tới cùng 1 giá trị.
char db ‘A’ ; ký tự (ASCII 41h)
hex db 41h ; thập lục phân
dec db 65 ; thập phân
bin db 01000001b ; nhị phân
oct db 101q ; bát phân
Có thể tự do pha trộn các hằng số, ký tự và chuỗi.
Có thể sử dụng cơ số khác khi định nghĩa danh sách các mục
Khi có một số thập lục phân bắt đầu bằng A-F, bổ xung thêm số zero để ngăn cấm trình hợp dịch diễn dịch nó thành nhãn. Trong vd dưới, list1 và list2 có cùng nội dung.
VD:
list1 db 10, 32, 42h, 00100010b
list2 db 0Ah, 20h, ‘A’, 22h
Cách biểu thị chuỗi
Một chuỗi được định danh bởi 1 biến, đánh dấu độ dịch vị của đầu chuỗi.
VD: một chuỗi kết thúc rỗng, tên Cstring và chuỗi Pstring có chiều dài đã mã hoá trong byte đầu tiên
Cstring db “Good afternoon”,0
Pstring db 14, “Good afternoon”
Chuỗi có thể tiếp tục trên nhiều dòng.
VD:
LongString db “This is a long string, that “
db “clearly is going to take “
db “serveral lines to store”,0
Trình hợp dịch tự động tính kho lưu trữ được sử dụng bằng cách trừ độ dịch vị khởi đầu của nó với độ dịch vị kết tiếp theo sau biến. Toán tử $ sẽ trả về bộ đếm vị trí hiện hành:
VD:
(offset)
0000 mystring db “This is a string”
0010 mystring_len = ($ - mystring)
Trong vd trên, mystring_len = 10h.
Toán tử DUP
Xuất hiện sau 1 chỉ phị phân bổ bộ nhớ, như DB, DW.
Sử dụng để lặp lại 1 hoặc nhiều giá trị khi phân bổ bộ nhớ.
VD:
db 20 dup(0) ; 20 bytes, tất cả = 0
db 20 dup(?) ; 20 bytes, không khởi tạo
db 4 dup(“ABC”) ; 12 bytes” “ABCABCABCABC”
db 4096 dup(0) ; vùng đêm 4096 byte, tất cả = 0
Có thể lồng ghép DUP.
Vd: lệnh đầu tiên tạo bộ nhớ chứa 000XX000XX000XX000XX. Lệnh thứ hai tạo 1 bảng từ 2 chiều gồm 3 hàng, 4 cột.
aTable db 4 dup( 3 dup(0), 2 dup(‘X’) )
aMatrix dw 3 dup( 4 dup(0) )
b) Định nghĩa từ (DW)
Tạo kho lưu trữ cho 1 hoặc nhiều giá trị 16-bit. Cú pháp:
[name] DW initval [,initval]…
Mỗi dấu khởi tạo tương đương 1 số nguyên không dấu 0~65535(FFFFh). Nếu có dấu –32768(8000h)~+32767(7FFFh).
Một hằng ký tự có thể lưu trong nửa dưới của từ.
VD:
dw 0,65535 ; các giá trị ko dấu nhỏ/lớn nhất
dw –32768,+32767
dw 256 * 2 ; biểu thức tính toán (512)
dw 1000h, 4096, ‘AB’,0 ; nhiều giá trị khởi tạo
dw ? ; chưa khởi tạo
dw 5 dup(1000h) ; 5 từ, mỗi từ = 1000h
dw 5 dup(?) ; 5 từ, chưa được khởi tạo
Biến trỏ: Độ dịch vị của 1 biến hoặc chương trình con có thể được lưu trong 1 biến khác, có tên là biến trỏ (pointer).
Vd: khởi tạo P theo độ dịch vị của list
list dw 256, 257, 258, 259 ; định nghĩa 4 từ
P dw list ; P trỏ đến list
Lưu trữ đảo ngược: Trình hợp dịch đảo ngược các byte trong 1 giá trị từ khi lưu trữ nó trong bộ nhớ. Byte thấp nhất xảy ra tại địa chỉ thấp nhất.
Khi biến dừoi đến 1 thanh ghi 16-bit, CPU tái đảo ngược byte.
VD: 1234h được lưu trữ trong bộ nhớ như sau:
Độ dịch vị: 00 01
Giá trị 34 12
c) Định nghĩa từ kép (DD)
Chỉ thị DD phân bỏ bộ nhớ cho 1 hoặc nhiều giá trị 32-bit:
[name] DD initval [, initval]…
Mỗi dấu tương đương 0 ~ BFFFFFFFFh
VD:
signed_val dd 0, 0BCDA1234h, -2147483648
đ 100h dup(?) ;256 từ kép (1024 byte)
Lưu trữ đảo ngược:
Độ dịch vị: 00 01 02 03
Giá trị: 78 56 34 12
Một từ kép có thể lưu địa chỉ đoạn dịch vị 32-bit của 1 biến hay thủ tục.
VD: tạo pointer1 lưu địa chỉ của subroutine1
pointer1 dd subroutine1
8. Hằng ký hiệu
Các lệnh lập phương trình cho phép gán các tên ký hiệu cho các hằng và các nguyên dạng số.
Một hằng có thể định nghĩa tại đầu chương trình, và trong 1 số trường hợp có thể định nghĩa lại về sau.
a) Dấu bằng
Được xem như một phép lập phương trình định nghĩa lại được, nó tạo 1 ký hiệu tuyệt đối bằng cách gán giá trị của một biểu thức số cho một tên. Cú pháp:
name = expression
Khác với DB và DW, lệnh = không phân bổ bộ nhớ. Khi được hợp dịch, tất cả name sẽ được thay thế bằng expression.
Biểu thức phải có khả năng diễn tả số nguyên 32bit có dấu hoặc không dấu.
VD:
prod = 10 * 5 ; đánh giá 1 biểu thức
maxInt = 7FFFh ; giá trị tối đa 16bit có dấu
minInt = 8000h ;giá trị tối thiểu 16bit có dấu
maxUInt = 0FFFFh
chuỗi = ‘XY’ ; lên đến 2 ký tự được phép
count = 500
endvalue = count + 1
.386
maxLong = 7FFFFFFh
minLong = 8000000h
maxULong = 0FFFFFFFFh
b) EQU
Gán tên ký hiệu cho 1 hằng hoặc chuỗi.
Một ký hiệu được định nghĩa bằng EQU không thể định nghĩa lại về sau trong ct.
Biểu thức số nguyên đánh giá theo trị số.
Giá trị dấu chấm động đánh giá theo các chuỗi.
Các vế phương trình chuỗi có thể được bao trong dấu ngoặc < … >
VD:
maxint equ 32767 ; numeric
maxuint equ 0FFFFh ; numeric
count equ 10 * 20 ; numeric
floatl equ <2.345> ; String
c) TEXTEQU
Tạo ra macro văn bản.
Cú pháp:
name TEXTEQU
name TEXTEQU textmacro
name TEXTEQU %constExpr
Trong đó:
: chuỗi văn bản bất kỳ
textmacro: 1 macro văn bản được định nghĩa trước
%constExpr: biểu thức đánh giá theo văn bản
Macro văn bản có thể xuất hiện ở bất kỳ chỗ nào trong chương trình.
Vd: tên ký hiệu có thể gán cho chuỗi
continueMsg textequ <“Continue or not (Y/N)?”>
.data
prompt db continueMsg
VD: tạo 1 bí danh (alias) biểu thị 1 ký hiệu khác đã định nghĩa trước
; các khai báo ký hiệu:
move textequ
address textequ
; Mã ban đầu:
move bx,address value1
move al,20
; Được hợp dịch là:
mov bx, offset value1
mov al,20
VD: TEXTEQU được dùng để định nghĩa biến trỏ (p1) theo 1 chuỗi. Sau đó p1 được gán cho 1 nguyên dạng chứa “0”:
.data
myString db “A string”,0
.code
p1 textequ
mov bx,p1 ;bx = offset myString
p1 textequ <0>
mov si,p1 ; si = 0
9. Lệnh chuyển giao dữ liệu
Lệnh MOV:
MOV reg,reg
MOV mem,reg
MOV reg,mem
MOV mem,immed
MOV reg,imed
Trong đó:
reg là thanh ghi phi đoạn bất kỳ, trừ IP không thể là 1 toán hạng đích.
Kích cỡ 2 toán hạng phải như nhau.
Với các thanh ghi đoạn:
mov segreg,reg16
mov segreg,mem16
mov reg16,segreg
mov mem16,segreg
Lưu ý: lệnh MOV không thể sử dụng 2 toán hạng bộ nhớ
VD:
mov ax,var1
mov var2, ax
Vd: lệnh mov với 3 kiểu toán hạng
.data
count db 10
total dw 412.6h
bigVal dd 12345678h
.code
mov al,bl ; thanh ghi 8-bit đến thanh ghi
mov bl,count ; bộ nhớ 8 bit đến thanh ghi
mov count,26 ; giá trị tức thời 8bit đến bộ nhớ
mov bl,1 ; giá trị tức thời 8bit đến thanh ghi.
mov dx,cx ; thanh ghi 16bit ->thanh ghi
mov bx,8FE2h
mov toal,1000h
mov eax,ebx ; thanh ghi 32 ->thanh ghi
mov edx,bigVal
Kiểm tra Kiểu:
Khi biến được tạo bằng DB,DW, DD hoặc bất kỳ lệnh định nghĩa dữ liệu nào, trình hợp dịch sẽ gán 1 thuộc tính ngầm định (byte, từ, từ kép)
Các kiểu không khớp sẽ xảy ra lỗi
VD:
.data
count dw 20h
byteval db 1
.code
mov al,count ;lỗi giá trị lớn hơn thanh ghi
mov ax,byteval ;lỗi giá trị nhỏ hơn thanh ghi
b) Độ dịch chuyển của toán hạng
Có thể bổ xung độ dịch chuyển vào tên 1 toán hạng bộ nhớ = p2 định địa chỉ trực tiếp dịch vị (direct-offset)
VD: arrayB+1 tham chiếu vượt quá 1 byte đầu, arrayB+2 tham chiếu vị trí cách 2byte.
arrayB db 10h,20h
arrayW dw 100h,200h
arrayD dd 10000h,20000h
mov al, arrayB ; al = 10h
mov al, arrayB+1 ; al = 20h
mov ax, arrayW+2 ; vượt qua 16bit
mov eax, arrayD+4 ; vượt qua 32bit
c) Lệnh XCHG
Lệnh XCHG (exchange data) trao đổi nội dung của 2 thanh ghi hoặc giữa thanh ghi và biến. Cú pháp
xchg reg,reg
xchg reg,mem
xchg mem,reg
Không thể dùng 2 toán hạng bộ nhớ với nhau.
xchg ax,bx ; trao đổi 2 thanh 16bit
xchg ah,al ; trao đổi 2 thanh 8bit
xchg var1,bx ; trao đổi biến và thanh 16bit
xchg eax,ebx ; trao đổi 2 thanh 32bit
10. Lệnh số học
Lệnh INC và DEC
INC tăng thêm 1
DEC giảm 1
Cú pháp:
inc destination
dec destination
destination có thể là thanh ghi hoặc toán hạng bộ nhớ.
Tất cả các cờ đều bị ảnh hưởng ngoại trừ cờ Carry.
VD:
inc al ; tăng giá trị thanh ghi 8bit
dec bx ; giảm giá trị thanh ghi 16bit
inc eax ; tăng giá trị thanh ghi 32bit
inc membyte ; tăng giá trị toán hạng bộ nhớ
dec byte ptr membyte ; tăng toán hạng 8 bit
dec memword ; giảm toán hạng bộ nhớ
inc word ptr memword ; tăng toán hạng 8bit
byte ptr định danh 1 toán hạng 8 bit
word ptr định danh 1 toán hạng 16bit
b) Lệnh ADD
Cộng toán hạng nguồn vào toán hạng đích.
Cú pháp:
add destination,source
Source không bị thay đổi, destination được gán tổng.
Kích cỡ toán hạng phải ăn khớp
Chỉ có 1 toán hạng là toán hạng bộ nhớ.
Thanh ghi đoạn không thể là đích.
Các cờ trạng thái đều bị ảnh hưởng.
VD:
add cl,al
add eax,edx
add bx,1000h
add var1,ax
add dx,var1
add var1,10
add dword ptr memVal,ecx
c) Lệnh SUB
Trừ toán hạng nguồn với toán hạng đích
Cú pháp:
sub destination,source
Kích cỡ phải khớp
Chỉ có 1 toán hạng là toán hạng bộ nhớ
Trong CPU, toán hạng nguồn được “âm hoá” trước rồi mới được cộng vào đích.
VD:
sub eax,12345h
d) Các cờ bị ảnh hưởng bởi add và sub
Nếu kết quả là 0, cờ zero được bật
Nếu kết quả âm, cờ sign được bật
VD:
mov ax,10
sub ax,10 ; ax = 0, ZF = 1
mov bx,1
sub bx,2 ; bx = FFFF, SF = 1
Cờ zero ấn định khi kết quả số học = 0. Lưu ý: inc và dec tác động đến zero chứ không phải carry.
Vd:
mov bl, 4Fh
add bl,0B91h ;BL=00,ZF=1,CF=1
mov ax,0FFFFh
inc ax ;ZF = 1 (CF không ảnh hưởng)
Việc xác định toán hạng có dấu và không dấu là tuyền thuộc vào lập trình viên. CPU cập nhật cờ Carry và Overflow để bao hàm 2 khả năng.
Các phép toán không dấu:
Khi thực hiện phép toán không dấu, Carry sẽ có tác dụng.
Nếu kết quả quá lớn với toán hạng đích, Carry sẽ bật. VD: 0FFh+1 = 100h nhưng kết quả không vừa với al (lưu 2 giá trị 00):
mov ax,0FFh
add al,1 ; al=0, CF = 1
Đây là phép toán 8bit (al được dùng), nếu muốn câu trả lời đúng, ta phải cộng 1 vào ax
mov ax,0FFh
add ax,1 ; AX = 0100, CF = 0
Từ 1 toán hạng lớn hơn với 1 toán hạng nhỏ hơn, cờ Carry bật để thông báo kết quả là bất hợp lệ
mov al,1
sub al,2 ; al = FF, CF = 1
Phép toán có dấu: Cờ Overflow được ấn định khi 1 phép toán cộng, trừ phát sinh 1 giá trị có dấu ngoài miền giá trị (byte: -128~127,..)
mov al,+126
add al,2 ;al = 80h, OF = 1
mov al,-128
sub al,2 ; al = 7Eh, OF = 1
11. Các kiểu toán hạng cơ bản
Có 3 kiểu toán hạng cơ bản:
tức thời: hằng giá trị
thanh ghi: một trong các thanh ghi của CPU
bộ nhớ: tham chiếu đến vị trí bộ nhớ.
Quy ước:
độ dịch chuyển: con số hoặc độ dịch vị của biến
địa chỉ thực: tham chiếu độ dịch vị của dữ liệu từ đầu phân đoạn của nó.
Chế độ định địa chỉ: tham chiếu kiểu toán hạng bộ nhớ đang dùng
mov ax, [si] ; sử dụng chế độ định địa chỉ thanh ghi gián tiếp.
Bài 2
1. Số có dấu
Bit đầu tiên bên trái được sử dụng làm bit dấu.
0 là dương, 1 là âm.
VD:
11110110: -10
00001010: +10
NX: -10 và +10 không hẳn là giống nhau. Đó là do các số âm được lưu trữ theo dạng thức bù hai.
Để tìm bù hai của 1 số, ta đảo trạng thái các bit và + thêm 1.
VD:
+10 được lưu trữ là 00001010
Đảo trạng thái: 11110101
Cộng thêm 1: 11110101 + 1 = 11110110
Đây là ký hiệu bù 2 của –10.
Do bit cao nhất được dùng làm bit dấu, do đó tầm lớn của số sẽ giảm ½
Bộ xử lý thực hiện phép tính không quan tâm đến dấu của các con số, do đó LTV phải nhớ toán hạng có dấu hay không dấu.
VD:
Mov ax, +16 ;00010000
Add ax, -23 ;11101001
Kết quả là 11111001, cái này là –7, cũng có thể là 249.
2. Lưu trữ ký tự
Máy tính lưu trữ bằng số nhị phân.
Các ký tự được lưu trữ dưới dạng lược đồ mã hoá ký tự, phổ dụng nhất là ASCII (American Standard Code for Information Interchange).
Một chuỗi các ký tự được biểu thị trong bộ nhớ dưới dạng 1 dãy liên tiếp các byte chứa con số.
VD:
“ABC123” là 41h, 42h, 43h, 30h, 31h, 32h
3. Hằng và biểu thức
Nguyên dạng số: là tổ hợp các chữ số và các phần tuỳ chọn: một dấu, một dấu chấm thập phân, và một số mũ.
VD:
5
5.5
-5.5
26.E+05
Các hằng nguyên kết thúc bằng 1 ký hiệu định danh cơ số, nếu không có ký hiệu định danh, ngầm định sẽ là số thập phân.
H: thập lục phân
Q (hoặc o): bát phân
D: thập phân
B: nhị phân
VD:
thập phân: 26, 34d, 34D
thập lục phân: 0F6h, 2BH, 1Ah
Bát phân: 36q, 72Q
Nhị phân: 10101b
Khi một hằng thập lục phân bắt đầu bằng một một mẫu tự, nó phải chứa một số 0 dẫn đầu.
Một biểu thức hằng gồm tổ hợp các nguyên dạng số, các toán tử, các hằng ký hiệu đã được định nghĩa.
Giá trị của biểu thức phải xác định được vào thời gian hợp dịch, và giá trị của nó không thể thay đổi vào thời gian thực hiện (runtime).
VD: các biểu thức liên quan đến nguyên dạng số:
25.3
4 * 20
-3 * 4 / 6
2.301E+04
Một hằng ký hiệu được tạo bằng cách gán một biểu thức theo tên hằng.
VD:
Rows = 5
Columns = 10
tablePos = rows * columns
Các lệnh trên chỉ được đánh giá vào thời gian hợp dịch.
Hằng chuỗi hoặc ký tự: Một hằng có thể biểu diễn cho 1 chuỗi các ký tự, được bao trong các dấu nháy đơn hoặc kép.
Có thể dùng dấu nháy nhúng
VD:
‘ABC’
‘X’
“This is a test”
‘4096’ ; chứa 4 byte, mỗi byte là 1 mã ASCII
“This isn’t a test”
‘Say “hello” to Bill.’
4. Các điều lệnh
Lệnh hợp ngữ gồm: tên, từ gợi nhớ chỉ lệnh, các toán hạng và một chú giải.
Gồm 2 lớp:
Chỉ lệnh: các lệnh thi hành
Chỉ thị: các lệnh cung cấp thông tin để báo cho trình hợp dịch cách phát sinh mã thi hành.
Dạng thức chung: [tên] [từ gợi nhớ] [các toán hạng] [;chú giải]
Một điều lệnh phải viết trên cùng 1 dòng, không vượt quá cột 128. Có thể tiếp tục 1 dòng trên dòng kế tiếp, nếu ký tự cuối của dòng đầu tiên là
VD:
longArray dw 1000h, 1020h, 1030h
1040h, 1050h, 1060h, 1070h, 1080h
Chỉ lệnh: là lệnh được thi hành bởi bộ xử lý theo thời gian thực hiện. Gồm các kiểu: chuyển giao điều khiển, chuyển giao dữ liệu, số học, logic và nhập xuất.
Các chỉ lệnh được trình hợp dịch phiên dịch trực tiếp thành mã máy.
VD:
call MySub ;chuyển giao điều khiển
mov ax, 5 ;chuyển giao dữ liệu
add ax, 20 ;số học
jz next1 ;logic (nhảy nếu ấn định cờ Zero)
in al,20 ;nhập/xuất (đọc từ cổng phần cứng)
Chỉ thị là lệnh ảnh hưởng đên bảng kê chương trình hoặc cách phát sinh mã máy.
VD:
chỉ thị db báo cho trình hợp dịch tạo kho lưu trữ cho 1 biến byte tên count và khởi tạo nó theo 50:
count db 50
chỉ thị stack báo cho trình hợp dịch dành riêng 4096 byte không gian ngăn xếp.
.stack 4096
5. Tên
Tên định danh một nhãn, biến, ký hiệu hoặc từ khoá. Nó có thể chứa các ký tự:
A … Z, a … z : Các mẫu tự
0 … 9 : Các chữ số
? : Dấu hỏi
_ : Dấu gạch dưới
@ : Dấu @
$ : Dấu $
. : Dấu chấm
Quy tắc đặt tên:
Tối đa 247 ký tự (trong MASM)
Không phân biệt chữ hoa, chữ thường.
Ký tự đầu tiên có thể là một mẫu tự, @, _ hoặc $. Tránh dùng @ làm ký tự đầu tiên, vì nó thường được dùng tại đầu của nhiều tên ký hiệu được định nghĩa sẵn.
Tên không trùng với từ dành riêng của trình hợp dịch.
Biến: một vị trí trong vùng dữ liệu của chương trình đã được gán tên.
VD:
count1 db 60 ; biến count1
Nhãn: nếu 1 tên xuất hiện trong vùng mã chương trình, nó được gọi là 1 nhãn.
Nhãn được sử dụng như các dấu giữ cho khi một chương trình cần nhảy hoặc lặp vòng từ vị trí này sang vị trí khác
Nhãn nằm trên một dòng trắng hoặc nằm chung với chỉ lệnh.
VD:
Label1: mov ax, 0
mov bx, 0
…
Label2:
jmp Label1 ; nhảy đến Label1
Từ khoá: là chỉ lệnh hoặc chỉ thị của trình hợp dịch: MOV, ADD, PROC, TITLE, AX, END.
Từ khoá không thể được dùng ngoài ngữ cảnh hoặc dưới dạng các dấu định danh.
VD:
add: mov ax,10
6. Hợp dịch và kết nối
7. Các chỉ thị phân bổ dữ liệu
Biến là ký hiệu dành cho một vị trí trong bộ nhớ nơi lưu trữ một số dữ liệu.
Độ dịch vị(offset) của một biến là khoảng cách từ đầu phân đoạn đến biến đó.
Tên biến sẽ tự động kết hợp với độ dịch vị
VD: khai báo mảng chứa 4 ký tự aList thì aList sẽ chỉ định danh độ dịch vị của ký tự đầu tiên (A).
.data
aList db “ABCD”
Độ dịch vị
Offset của aList = 0
Ta sử dụng chỉ thị phân bổ dữ liệu để phân bổ kho lưu trữ, dựa trên một số kiểu được định nghĩa sẵn.
a) Định nghĩa byte(DB)
Phân bổ cho một hoặc nhiều giá trị 8-bit
[name] DB initval [,initval]…
name: tuỳ chọn
initval: dấu khởi tạo. Có thể là một biểu thức hằng chứa các nguyên dạng số, các ký hiệu được định nghĩa, ký tự, các chuỗi có dấu nháy. Ít nhất phải có 1, nhiều hơn 1 thì sử dụng dâu ‘,’ để phân tách.
Có thể để ở dạng không xác định bằng cách dùng dấu ? thay cho dấu khởi tạo.
VD:
Char1 db ‘A’ ; ký tự ASCII
char2 db ‘A’-10 ; biểu thức
signed1 db –128 ;giá trị có dấu nhỏ nhất
signed2 db +127 ; giá trị có dấu lớn nhất
unsigned db 255 ; giá trị không dấu lớn nhất
myval db ? ; không xác định
Nhiều dấu khởi tạo:
list db 10,20,30,40
Các ký tự và số nguyên là như nhau đối với trình hợp dịch. Các biến dưới đây chỉ tới cùng 1 giá trị.
char db ‘A’ ; ký tự (ASCII 41h)
hex db 41h ; thập lục phân
dec db 65 ; thập phân
bin db 01000001b ; nhị phân
oct db 101q ; bát phân
Có thể tự do pha trộn các hằng số, ký tự và chuỗi.
Có thể sử dụng cơ số khác khi định nghĩa danh sách các mục
Khi có một số thập lục phân bắt đầu bằng A-F, bổ xung thêm số zero để ngăn cấm trình hợp dịch diễn dịch nó thành nhãn. Trong vd dưới, list1 và list2 có cùng nội dung.
VD:
list1 db 10, 32, 42h, 00100010b
list2 db 0Ah, 20h, ‘A’, 22h
Cách biểu thị chuỗi
Một chuỗi được định danh bởi 1 biến, đánh dấu độ dịch vị của đầu chuỗi.
VD: một chuỗi kết thúc rỗng, tên Cstring và chuỗi Pstring có chiều dài đã mã hoá trong byte đầu tiên
Cstring db “Good afternoon”,0
Pstring db 14, “Good afternoon”
Chuỗi có thể tiếp tục trên nhiều dòng.
VD:
LongString db “This is a long string, that “
db “clearly is going to take “
db “serveral lines to store”,0
Trình hợp dịch tự động tính kho lưu trữ được sử dụng bằng cách trừ độ dịch vị khởi đầu của nó với độ dịch vị kết tiếp theo sau biến. Toán tử $ sẽ trả về bộ đếm vị trí hiện hành:
VD:
(offset)
0000 mystring db “This is a string”
0010 mystring_len = ($ - mystring)
Trong vd trên, mystring_len = 10h.
Toán tử DUP
Xuất hiện sau 1 chỉ phị phân bổ bộ nhớ, như DB, DW.
Sử dụng để lặp lại 1 hoặc nhiều giá trị khi phân bổ bộ nhớ.
VD:
db 20 dup(0) ; 20 bytes, tất cả = 0
db 20 dup(?) ; 20 bytes, không khởi tạo
db 4 dup(“ABC”) ; 12 bytes” “ABCABCABCABC”
db 4096 dup(0) ; vùng đêm 4096 byte, tất cả = 0
Có thể lồng ghép DUP.
Vd: lệnh đầu tiên tạo bộ nhớ chứa 000XX000XX000XX000XX. Lệnh thứ hai tạo 1 bảng từ 2 chiều gồm 3 hàng, 4 cột.
aTable db 4 dup( 3 dup(0), 2 dup(‘X’) )
aMatrix dw 3 dup( 4 dup(0) )
b) Định nghĩa từ (DW)
Tạo kho lưu trữ cho 1 hoặc nhiều giá trị 16-bit. Cú pháp:
[name] DW initval [,initval]…
Mỗi dấu khởi tạo tương đương 1 số nguyên không dấu 0~65535(FFFFh). Nếu có dấu –32768(8000h)~+32767(7FFFh).
Một hằng ký tự có thể lưu trong nửa dưới của từ.
VD:
dw 0,65535 ; các giá trị ko dấu nhỏ/lớn nhất
dw –32768,+32767
dw 256 * 2 ; biểu thức tính toán (512)
dw 1000h, 4096, ‘AB’,0 ; nhiều giá trị khởi tạo
dw ? ; chưa khởi tạo
dw 5 dup(1000h) ; 5 từ, mỗi từ = 1000h
dw 5 dup(?) ; 5 từ, chưa được khởi tạo
Biến trỏ: Độ dịch vị của 1 biến hoặc chương trình con có thể được lưu trong 1 biến khác, có tên là biến trỏ (pointer).
Vd: khởi tạo P theo độ dịch vị của list
list dw 256, 257, 258, 259 ; định nghĩa 4 từ
P dw list ; P trỏ đến list
Lưu trữ đảo ngược: Trình hợp dịch đảo ngược các byte trong 1 giá trị từ khi lưu trữ nó trong bộ nhớ. Byte thấp nhất xảy ra tại địa chỉ thấp nhất.
Khi biến dừoi đến 1 thanh ghi 16-bit, CPU tái đảo ngược byte.
VD: 1234h được lưu trữ trong bộ nhớ như sau:
Độ dịch vị: 00 01
Giá trị 34 12
c) Định nghĩa từ kép (DD)
Chỉ thị DD phân bỏ bộ nhớ cho 1 hoặc nhiều giá trị 32-bit:
[name] DD initval [, initval]…
Mỗi dấu tương đương 0 ~ BFFFFFFFFh
VD:
signed_val dd 0, 0BCDA1234h, -2147483648
đ 100h dup(?) ;256 từ kép (1024 byte)
Lưu trữ đảo ngược:
Độ dịch vị: 00 01 02 03
Giá trị: 78 56 34 12
Một từ kép có thể lưu địa chỉ đoạn dịch vị 32-bit của 1 biến hay thủ tục.
VD: tạo pointer1 lưu địa chỉ của subroutine1
pointer1 dd subroutine1
8. Hằng ký hiệu
Các lệnh lập phương trình cho phép gán các tên ký hiệu cho các hằng và các nguyên dạng số.
Một hằng có thể định nghĩa tại đầu chương trình, và trong 1 số trường hợp có thể định nghĩa lại về sau.
a) Dấu bằng
Được xem như một phép lập phương trình định nghĩa lại được, nó tạo 1 ký hiệu tuyệt đối bằng cách gán giá trị của một biểu thức số cho một tên. Cú pháp:
name = expression
Khác với DB và DW, lệnh = không phân bổ bộ nhớ. Khi được hợp dịch, tất cả name sẽ được thay thế bằng expression.
Biểu thức phải có khả năng diễn tả số nguyên 32bit có dấu hoặc không dấu.
VD:
prod = 10 * 5 ; đánh giá 1 biểu thức
maxInt = 7FFFh ; giá trị tối đa 16bit có dấu
minInt = 8000h ;giá trị tối thiểu 16bit có dấu
maxUInt = 0FFFFh
chuỗi = ‘XY’ ; lên đến 2 ký tự được phép
count = 500
endvalue = count + 1
.386
maxLong = 7FFFFFFh
minLong = 8000000h
maxULong = 0FFFFFFFFh
b) EQU
Gán tên ký hiệu cho 1 hằng hoặc chuỗi.
Một ký hiệu được định nghĩa bằng EQU không thể định nghĩa lại về sau trong ct.
Biểu thức số nguyên đánh giá theo trị số.
Giá trị dấu chấm động đánh giá theo các chuỗi.
Các vế phương trình chuỗi có thể được bao trong dấu ngoặc < … >
VD:
maxint equ 32767 ; numeric
maxuint equ 0FFFFh ; numeric
count equ 10 * 20 ; numeric
floatl equ <2.345> ; String
c) TEXTEQU
Tạo ra macro văn bản.
Cú pháp:
name TEXTEQU
name TEXTEQU textmacro
name TEXTEQU %constExpr
Trong đó:
textmacro: 1 macro văn bản được định nghĩa trước
%constExpr: biểu thức đánh giá theo văn bản
Macro văn bản có thể xuất hiện ở bất kỳ chỗ nào trong chương trình.
Vd: tên ký hiệu có thể gán cho chuỗi
continueMsg textequ <“Continue or not (Y/N)?”>
.data
prompt db continueMsg
VD: tạo 1 bí danh (alias) biểu thị 1 ký hiệu khác đã định nghĩa trước
; các khai báo ký hiệu:
move textequ
address textequ
; Mã ban đầu:
move bx,address value1
move al,20
; Được hợp dịch là:
mov bx, offset value1
mov al,20
VD: TEXTEQU được dùng để định nghĩa biến trỏ (p1) theo 1 chuỗi. Sau đó p1 được gán cho 1 nguyên dạng chứa “0”:
.data
myString db “A string”,0
.code
p1 textequ
mov bx,p1 ;bx = offset myString
p1 textequ <0>
mov si,p1 ; si = 0
9. Lệnh chuyển giao dữ liệu
Lệnh MOV:
MOV reg,reg
MOV mem,reg
MOV reg,mem
MOV mem,immed
MOV reg,imed
Trong đó:
reg là thanh ghi phi đoạn bất kỳ, trừ IP không thể là 1 toán hạng đích.
Kích cỡ 2 toán hạng phải như nhau.
Với các thanh ghi đoạn:
mov segreg,reg16
mov segreg,mem16
mov reg16,segreg
mov mem16,segreg
Lưu ý: lệnh MOV không thể sử dụng 2 toán hạng bộ nhớ
VD:
mov ax,var1
mov var2, ax
Vd: lệnh mov với 3 kiểu toán hạng
.data
count db 10
total dw 412.6h
bigVal dd 12345678h
.code
mov al,bl ; thanh ghi 8-bit đến thanh ghi
mov bl,count ; bộ nhớ 8 bit đến thanh ghi
mov count,26 ; giá trị tức thời 8bit đến bộ nhớ
mov bl,1 ; giá trị tức thời 8bit đến thanh ghi.
mov dx,cx ; thanh ghi 16bit ->thanh ghi
mov bx,8FE2h
mov toal,1000h
mov eax,ebx ; thanh ghi 32 ->thanh ghi
mov edx,bigVal
Kiểm tra Kiểu:
Khi biến được tạo bằng DB,DW, DD hoặc bất kỳ lệnh định nghĩa dữ liệu nào, trình hợp dịch sẽ gán 1 thuộc tính ngầm định (byte, từ, từ kép)
Các kiểu không khớp sẽ xảy ra lỗi
VD:
.data
count dw 20h
byteval db 1
.code
mov al,count ;lỗi giá trị lớn hơn thanh ghi
mov ax,byteval ;lỗi giá trị nhỏ hơn thanh ghi
b) Độ dịch chuyển của toán hạng
Có thể bổ xung độ dịch chuyển vào tên 1 toán hạng bộ nhớ = p2 định địa chỉ trực tiếp dịch vị (direct-offset)
VD: arrayB+1 tham chiếu vượt quá 1 byte đầu, arrayB+2 tham chiếu vị trí cách 2byte.
arrayB db 10h,20h
arrayW dw 100h,200h
arrayD dd 10000h,20000h
mov al, arrayB ; al = 10h
mov al, arrayB+1 ; al = 20h
mov ax, arrayW+2 ; vượt qua 16bit
mov eax, arrayD+4 ; vượt qua 32bit
c) Lệnh XCHG
Lệnh XCHG (exchange data) trao đổi nội dung của 2 thanh ghi hoặc giữa thanh ghi và biến. Cú pháp
xchg reg,reg
xchg reg,mem
xchg mem,reg
Không thể dùng 2 toán hạng bộ nhớ với nhau.
xchg ax,bx ; trao đổi 2 thanh 16bit
xchg ah,al ; trao đổi 2 thanh 8bit
xchg var1,bx ; trao đổi biến và thanh 16bit
xchg eax,ebx ; trao đổi 2 thanh 32bit
10. Lệnh số học
Lệnh INC và DEC
INC tăng thêm 1
DEC giảm 1
Cú pháp:
inc destination
dec destination
destination có thể là thanh ghi hoặc toán hạng bộ nhớ.
Tất cả các cờ đều bị ảnh hưởng ngoại trừ cờ Carry.
VD:
inc al ; tăng giá trị thanh ghi 8bit
dec bx ; giảm giá trị thanh ghi 16bit
inc eax ; tăng giá trị thanh ghi 32bit
inc membyte ; tăng giá trị toán hạng bộ nhớ
dec byte ptr membyte ; tăng toán hạng 8 bit
dec memword ; giảm toán hạng bộ nhớ
inc word ptr memword ; tăng toán hạng 8bit
byte ptr định danh 1 toán hạng 8 bit
word ptr định danh 1 toán hạng 16bit
b) Lệnh ADD
Cộng toán hạng nguồn vào toán hạng đích.
Cú pháp:
add destination,source
Source không bị thay đổi, destination được gán tổng.
Kích cỡ toán hạng phải ăn khớp
Chỉ có 1 toán hạng là toán hạng bộ nhớ.
Thanh ghi đoạn không thể là đích.
Các cờ trạng thái đều bị ảnh hưởng.
VD:
add cl,al
add eax,edx
add bx,1000h
add var1,ax
add dx,var1
add var1,10
add dword ptr memVal,ecx
c) Lệnh SUB
Trừ toán hạng nguồn với toán hạng đích
Cú pháp:
sub destination,source
Kích cỡ phải khớp
Chỉ có 1 toán hạng là toán hạng bộ nhớ
Trong CPU, toán hạng nguồn được “âm hoá” trước rồi mới được cộng vào đích.
VD:
sub eax,12345h
d) Các cờ bị ảnh hưởng bởi add và sub
Nếu kết quả là 0, cờ zero được bật
Nếu kết quả âm, cờ sign được bật
VD:
mov ax,10
sub ax,10 ; ax = 0, ZF = 1
mov bx,1
sub bx,2 ; bx = FFFF, SF = 1
Cờ zero ấn định khi kết quả số học = 0. Lưu ý: inc và dec tác động đến zero chứ không phải carry.
Vd:
mov bl, 4Fh
add bl,0B91h ;BL=00,ZF=1,CF=1
mov ax,0FFFFh
inc ax ;ZF = 1 (CF không ảnh hưởng)
Việc xác định toán hạng có dấu và không dấu là tuyền thuộc vào lập trình viên. CPU cập nhật cờ Carry và Overflow để bao hàm 2 khả năng.
Các phép toán không dấu:
Khi thực hiện phép toán không dấu, Carry sẽ có tác dụng.
Nếu kết quả quá lớn với toán hạng đích, Carry sẽ bật. VD: 0FFh+1 = 100h nhưng kết quả không vừa với al (lưu 2 giá trị 00):
mov ax,0FFh
add al,1 ; al=0, CF = 1
Đây là phép toán 8bit (al được dùng), nếu muốn câu trả lời đúng, ta phải cộng 1 vào ax
mov ax,0FFh
add ax,1 ; AX = 0100, CF = 0
Từ 1 toán hạng lớn hơn với 1 toán hạng nhỏ hơn, cờ Carry bật để thông báo kết quả là bất hợp lệ
mov al,1
sub al,2 ; al = FF, CF = 1
Phép toán có dấu: Cờ Overflow được ấn định khi 1 phép toán cộng, trừ phát sinh 1 giá trị có dấu ngoài miền giá trị (byte: -128~127,..)
mov al,+126
add al,2 ;al = 80h, OF = 1
mov al,-128
sub al,2 ; al = 7Eh, OF = 1
11. Các kiểu toán hạng cơ bản
Có 3 kiểu toán hạng cơ bản:
tức thời: hằng giá trị
thanh ghi: một trong các thanh ghi của CPU
bộ nhớ: tham chiếu đến vị trí bộ nhớ.
Quy ước:
độ dịch chuyển: con số hoặc độ dịch vị của biến
địa chỉ thực: tham chiếu độ dịch vị của dữ liệu từ đầu phân đoạn của nó.
Chế độ định địa chỉ: tham chiếu kiểu toán hạng bộ nhớ đang dùng
mov ax, [si] ; sử dụng chế độ định địa chỉ thanh ghi gián tiếp.
* Một số tài liệu cũ có thể bị lỗi font khi hiển thị do dùng bộ mã không phải Unikey ...
Người chia sẻ: Đỗ Quang Huy
Dung lượng: |
Lượt tài: 1
Loại file:
Nguồn : Chưa rõ
(Tài liệu chưa được thẩm định)