1. Trang chủ
  2. » Công Nghệ Thông Tin

Giới thiệu về Assembly Language (Hợp ngữ) potx

63 952 10

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 63
Dung lượng 368,5 KB

Nội dung

Ví dụ ORG 100h: đoạn mã lệnh bắt đầu ở địa chỉ 100h,Code_seg: segment: tên Code_seg là đại diện cho 1 segment trong bộ nhớ • Chương trình được viết bằng các ký hiệu của ngôn ngữ Assembly

Trang 1

Giới thiệu về Assembly Language (Hợp ngữ)

……… , tháng … năm …….

Trang 2

BÀI 1 : MỞ ĐẦU

I Giới thiệu về Assembly Language (Hợp ngữ)

1 Giới thiệu về Assembly Language (Hợp ngữ)

Việc lập trình bằng ngôn ngữ máy đòi hỏi người lập trình cần phải nhớ các mã lệnh bằng số, phải sắp đặt vị trí của mã lệnh và tất cả các số liệu trong bộ nhớ của máy tính, ngay cả các số liệu cũng phải viết dưới dạng số Công việc này hết sức nặng nhọc và rất dễ gây nhầm lẫn

Chính vì vậy người ta cần đến Assembly Language, nó cho NSD các khả năng sau:

• Cho phép dùng các ký hiệu gợi nhớ thay cho các mã lệnh bằng số của bộ VXL, ví dụ ADD thay cho 00000000; INT 13h thay cho 11001101

00010011 v.v các ký hiệu loại này được gọi là mã lệnh (Op-Code)

• Cho phép dùng các tên gọi (nhãn: Label) để chỉ các địa chỉ nhớ, NSD gọi đến các tên này như việc gọi các thủ tục hoặc như là việc truy nhập đến các biến hay hằng số trong các ngôn ngữ lập trình bậc cao

• Cho phép dùng các chỉ thị cho chính Assembler (Assembler Directive),

để nó biết cần phải chuyển các mã của NSD như thế nào, chương trình bắt đầu

ở đâu; dự trữ khoảng trống bao nhiêu cho dữ liệu; báo rằng không còn lệnh để chuyển mã ngữ tiếp nữa v.v Ví dụ ORG 100h: đoạn mã lệnh bắt đầu ở địa chỉ 100h,Code_seg: segment: tên Code_seg là đại diện cho 1 segment trong bộ nhớ

• Chương trình được viết bằng các ký hiệu của ngôn ngữ Assembly được gọi là chương trình nguồn (Source Program) Chương trình ở dạng số tương tương với chương trình nguồn mà bộ VXL có thể hiểu được (microprocessor-

Trang 3

compatible form) gọi là chương trình đích(Object Program) Assembler là chương trình thực hiện chuyển (convert) chương trình nguồn(Source Program) thành chương trình đích (Object Program).

2 Một số vấn đề về hệ đếm 2, số có dấu, số bù 2

2.1 Hệ đếm 2

Như ta đã biết, các phần tử nhớ cơ bản cấu tạo nên bộ nhớ cũng như các phần

tử trong khối tính toán của máy tính đều là các phần tử có 2 trạng thái cân bằng ổn định 'on' và 'off' (ta có thể dùng để biểu diễn số 1 và 0) giống như trạng thái đóng mạch và cắt mạch của một cái công tắc điện Tất cả chương trình và số liệu mà chương trình sử dụng đều đặt trong bộ nhớ trước khi được bộ VXL đọc Như vậy sự kết hợp của một dãy các số 0 và 1 có thể biểu diễn bất cứ con số nào Hệ đếm chỉ sử dụng các số 0 và 1 được gọi là hệ nhị phân (Binary numbering system) hay hệ đếm

2 , đó là hệ đếm cơ sở cho mọi loại MTĐT ngày nay

Một phần tử nhớ chỉ có 1 trong hai giá trị 0, 1 được gọi là 1 bit, đó là chữ viết tắt của Binary digit Cũng tương tự như trong hệ thập phân, trong một số nhị phân giá trị của mỗi bit trong con số phụ thuộc vào vị trí của nó trong con số đó như được thể hiện sau đây:

7 6 5 4 3 2 1 0 vị trí bit trong con số

x x x x x x x x

27 26 25 24 23 22 21 20 trọng số của bit

128 64 32 16 8 4 2 1 giá trị tương ứng trong hệ thập phân

Để chuyển một số từ hệ thập phân sang hệ nhị phân ta thực hiện một loạt các phép MOD 2 đối với số đó cho tới khi số thập phân bằng 0:

• Giá trị của phép tính MOD 2 đầu tiên là giá trị của bit 0

• Giá trị của phép tính MOD 2 tiếp theo là giá trị của bit 1.v.v Trong các lĩnh vực tin học, thường sử dụng một đơn vị lớn hơn, đó là byte, 1 byte gồm 8 bit, như vậy 1 byte có thể biểu diễn một con số có giá trị từ 00000000 đến 11111111 (0 - 255 trong hệ thập phân)

Ngoài ra còn có các đơn vị 1KB = 210 byte, 1MB = 220 byte

2.2 Số có dấu

Khi sử dụng 1 byte để biểu diễn số có dấu, người ta chỉ sử dụng 7 bit thấp để biểu diễn số, còn bit cao nhất (bit 7) để biểu diễn dấu của con số đó, nếu bit này = 0 thì con số là dương, nếu bit này = 1 thì con số là âm Như vậy với 1 byte có thể biểu diễn các số từ -128 đến +127

Theo quy ước này số -1 có giá trị như sau: 10000001 nếu ta đem cộng

với 1 thì kết quả lại = 10000010 = -2D! không như chúng ta chờ đợi là = 0; chính vì

lý do này mà người ta phải dùng một dạng số đặc biệt - dạng bù 2 (two's complemented) để biểu diễn số âm

Trang 4

Để tìm dạng biểu diễn nhị phân của một số âm (nghĩa là tìm dạng bù 2 của nó),

ta chỉ việc lấy số dương tương ứng rồi đảo giá trị các bit, sau đó cộng 1 vào kết quả

là xong Thí dụ tìm biểu diễn nhị phân của số -1: 0000 0001 đảo các bit thành 1111

1110, đem cộng thêm 1 trở thành 1111 1111.Nếu ta đem số -1 này cộng với +1 thì kết quả là 1 0000 0000, ta lờ số nhớ (1) đi thì được số 0000 0000 như mong muốn!

đó là cách biểu diễn số âm trong máy tính!

Nhìn vào số âm dạng bù 2 ta khó mà hiểu được số thập phân (âm) tương ứng bằng bao nhiêu, nếu muốn tính, ta vẫn áp dụng quy tắc trên để tính được số dương tương ứng.Thí dụ muốn biết 1101 0000 có giá trị thập phân tương ứng bằng bao nhiêu?

Ngay từ khi máy tính điện tử mới ra đời, người lập trình cũng đã thường thao tác trên từng nhóm bit chứ không phải trên từng bit Các bộ VXL đầu tiên là loại 4 bit, vì thế người ta có thể nhóm 4 bit lại và biểu diễn bằng một ký hiệu duy nhất Với

4 bit có thể biểu diễn 16 giá trị khác nhau, người ta dùng các ký hiệu 0 9, A, B, C, D,

E, F để biểu diễn các giá trị nhị phân từ 0000 đến 1111 Hệ đếm như vậy được gọi là

hệ thập lục phân (hệ đếm cơ số 16) - hexadecimal numbering system

3 Một số vấn đề cần nhắc lại (sau giáo trình CTMT) về bộ VXL

Các Mode làm việc: Các bộ VXL 80286 (và các bộ VXL mới hơn của INTEL)

có thể hoạt động trong 2 mode khác nhau: Real Address Mode và Protected Virtual Address Mode

• Real Address Mode : Trong Mode này 80286 hoạt động cũng giống như 8086, nhưng thực hiện các chương trình nhanh hơn từ 2 đến

5 lần, nó hỗ trợ tất cả các lệnh của 8086, thêm vào đó là các lệnh của riêng 80286 Khi chúng ta mới bật máy, 80286 bắt đầu ở Mode này, chỉ khi nào chương trình ra lệnh cho nó chuyển sang Mode kia (Protected Mode)

• Protected Mode : Trong Mode này 80286 vẫn có mọi tính năng như ở Real Address Mode nhưng được thêm vào một số tính năng tinh

vi để bảo vệ dữ liệu và quản lý bộ nhớ Tính năng nổi bật nhất của Mode này là nó cho phép 80286 truy cập một bộ nhớ rất lớn (so với 8086) bằng cách sử dụng một kỹ thuật gọi là Virtual Addressing.Bằng

kỹ thuật này 80286 có thể làm việc với 2 loại bộ nhớ: không gian địa chỉ vật lý (Physical address space) và không gian địa chỉ ảo (Virtual address space)

1 Không gian địa chỉ vật lý là miền bộ nhớ mà 80286 có thể làm việc với nó tại một thời điểm, bằng 224 = 16MB

Trang 5

2 Không gian địa chỉ ảo là miền bộ nhớ mà 80286 có thể đánh địa chỉ, bằng 230 = 1GB (1 Giga byte) Thuật ngữ ảo (Virtual) được sử dụng bởi vì nếu một chương trình cần truy cập bộ nhớ mà địa chỉ không thuộc không gian địa chỉ nhớ vật lý, hệ điều hành có thể sử dụng khả năng quản lý

bộ nhớ của 80286 để chuyển đổi (swap) một phần thích hợp (applicable piece) của bộ nhớ ảo Việc chuyển đổi bộ nhớ (swapping) này người lập trình không thấy được vì vậy anh ta có thể viết chương trình truy cập bất cứ địa chỉ nhớ nào trong toàn bộ không gian địa chỉ lớn đến 1GB Virtual Disk từ Version 3.0 trở lên, DOS hỗ trợ việc sử dụng bộ nhớ trên 1MB, ta có thể sử dụng nó như 'Virtual Disk' (đĩa

ảo hay RAM Disk) Để truy cập vùng nhớ cao này, bộ VXL tạm thời (momentarily) chuyển (switch) sang Protected Mode, thực hiện việc (vận) chuyển dữ liệu rồi lại chuyển trở về Real Mode như bình thường Kết quả chung là ta có thể sử dụng một bộ nhớ RAM có kích thước lớn, tốc độ thao tác cực nhanh so với tốc độ thao tác trên đĩa * Protected Mode được người thiết kế OS quan tâm, với người lập trình bình thường chỉ cần quan tâm tới Real Mode là đủ

Trang 6

CMP dest, src so sánh (bằng cách trừ, nhưng không làm thay đổi dest và src) để đặt các cờ hiệu là nhớ, tràn, v.v

MUL src nhân AL hay AX với một số dương (không có dấu) là src (src là reg/mem)

AX:= (AL*src8); DX:AX:=(AX*Immed16)

IMUL src nhân AL hay AX với một số nguyên có dấu

DIV src chia AL hoặc AX cho giá trị trong reg/mem không dấu nếu chia cho 0 hoặc kết quả quá lớn sẽ gây ra INT 0

AL < (AX*src8); AH < (AX MOD src8)

AX < (DX:AX*src16); DX < (DX:AX MOD src16)

IDIV src chia AL hoặc AX cho giá trị trong reg/mem có dấu CBW đổi byte thành Word

AL mở rộng theo dấu vào AH

AH được điền đầy theo bit 7 của AL

CWD đổi Word thành Word

AX mở rộng theo dấu vào DX

DX được điền đầy theo bit 15 của AX

.v.v

2/ Các lệnh logic

AND dest,src : nhân logic từng bit trong dest và src

OR dest,src : OR logic từng bit trong dest và src

XOR dest,src : XOR logic từng bit trong dest và src

NOT dest : đảo từng bit trong dest (lấy bù 1)

.v.v

3/ Các lệnh vận chuyển số liệu

MOV dest,src : copy dữ liệu từ src (reg/mem) tới dest Lưu ý rằng không thể MOV

từ ô nhớ (mem) vào ô nhớ

XCHG dest,src đổi (chỗ) giá trị giữa 2 thanh ghi hoặc giữa thanh ghi và bộ nhớ

IN Port8 (or DX) nhận dữ liệu từ cổng vào AL hay AX

không phải dữ liệu chứa trong mem1

( nạp kết quả việc tính toán EA của địa chỉ tương đối vào

reg16)

PUSH src cất giá trị thanh ghi 16 bit (hoặc r/mem16) vào stack PUSH immed cất giá trị 16 bit (hoặc 8 bit mở rộng dấu) vào stack

PUSHF cất giá trị của thanh ghi cờ vào stack

POP dest chuyển giá trị từ stack vào dest (reg16 hoặc r/mem

hoặc thanh ghi đoạn)

POPF chuyển giá trị từ stack vào thanh ghi cờ

Trang 7

4/ Các lệnh thao tác trên xâu ký tự

CLD Clear direction flag to UP (DF:=0)

string Ops auto-increment

STD set direction flag to Down (DF:=1)

string Ops auto-decrement

5/ Các lệnh điều khiển sự thực hiên chương trình

JMP short/near/far target nhảy không điều kiện đến nhãnshort : IP (IP + (target displacement sign-extended))

báo cho assembler là nhãn đích của lệnh nhảy JMP không xahơn 127 bytes kể từ địa chỉ của lệnh tiếp theo

near : IP (IP + (target displacement)

far : SS target_seg; IP target_offset

indirect : IP (register or value in memory)

JCXZ: nhảy tới nhãn khi CX=0, không kiểm tra cờ

CLD clear direction flag

(các lệnh với xâu ký tự tự động tăng)

Trang 8

(chưa đưa vào chương trình phần này) 3 Phân tích một số mã lệnh - Trong hệ lệnh của 8088/8086 có nhiều lệnh tính chất giống nhau,

chỉ khác nhau ở địa chỉ của các toán hạng Chính vì vậy có những

lệnh chỉ cần 1 byte mã lệnh là đủ để bộ VXL thực hiện, lại có những

lệnh cần thêm một số thông tin nữa mới có thể thực hiện được, các thông tin này được chứa trong 1 byte, đi ngay sau byte mã lệnh thứ nhất Việc xác định xem 1 lệnh nào đó có cần đọc thêm byte lệnh thứ 2

hay không được bộ giải mã lệnh quyết định - Ta phân tích lệnh ADD làm ví dụ:

Có các khả năng sau đối với việc cộng 2 toán hạng

1/ r/m r8 : cộng nội dung thanh ghi 8 bit vào một thanh ghi

hay 1 ô nhớ

2/ r/m r16 : cộng nội dung một thanh ghi 16 bit và một thanh

ghi 16 bit hoặc vào (2) ô nhớ

3/ r8 r/m cộng nội dung từ thanh ghi (8 bit) hoặc từ 1 ô nhớ (tất nhiên là 8 bit) vào

1 thanh ghi 8 bit

4/ r16 r/m cộng nội dung một thanh ghi hoặc ô nhớ vào 1

thanh ghi 16 bit

5/ AL im8 cộng trực tiếp 1 giá trị 8 bit vào AL

6/ AX im16 cộng trực tiếp 1 giá trị 16 bit vào AX

7/ r im8 hoặc im16; trường hợp này r # AX

Cấu tạo của mã lệnh như sau:

1/ trường hợp 1 d: direction

reg/memory with reg to either = 1: 'to' reg

= 0 : 'from' reg

0 0 0 0 0 0 d w mod reg r/m w : word operation

= 1 : with word = 0: with byte

mã lệnh này chứa đựng các khả năng:

1 0 0 0 0 0 s w mod 0 0 0 r/m data data

byte 1 byte 2 nếu

Trang 9

byte 1 byte 2 nếu

s:w = 01

mã lệnh này chứa đựng các khả năng:

nêu ở trên

III Cấu tạo của lệnh, các Mode địa chỉ của Assembly Language

Trên thị trường có một số Assembler, trong tài liệu này chúng ta sử dụng

MACRO ASSEMBLER (MASM); về MASM sẽ được đề cập ở bài 2

1 Cấu tạo của lệnh

nhãn Mã lệnh các toán hạng ghi chú

Data: MOV cx,ax ;nạp vào cx giá trị trong ax

- Trường nhãn (label field), Nhãn dài tối đa 31 ký tự ấn định một tên đại diện cho 1 lệnh assembly, để cho các lệnh khác có thể dùng tên này thay cho địa chỉ của lệnh đó trong bộ nhớ

Nhãn không được bắt đầu bằng 1 con số, không chứa dấu phân cách, nhãn kết thúc bằng dấu:; trong nhãn có thể có các ký tự '$', '?', '@','_' - Mã lệnh (Op-code) dài từ 2-7 ký tự, là những chữ viết tắt gợi trí nhớ, để chỉ các lệnh của bộ vxl Mã lệnh có thể đứng liền sa dấu ': ' của nhãn hoặc phân cách bởi 1 số dấu cách (space) Giữa mã lệnh

và các toán hạng phải có một số dấu cách - Các toán hạng (operands): báo cho MPU biết phải tìm các toán hạng ở đâu - các ghi chú (comments) dùng để diễn giải dòng lệnh trong chương trình, để đọc lại cho dễ hiểu hơn Trong các chương trình dài các chú thích rất quan trọng và cần thiết

ghi chú phải đi sau ký hiệu ';' và kết thúc bởi dấu xuống dòng (Enter)

2 Các Mode địa chỉ

- Phương pháp xác định vị trí trong bộ nhớ của của 1 toán hạng được gọi là Mode địa chỉ (Addressing Mode) Mode địa chỉ của một toán hạng phụ thuộc vào vị trí trong bộ nhớ của dữ liệu ứng với toán hạng đó Có một số cách phân loại Mode địa chỉ khác nhau, dưới đây nêu ra hai trong các cách đó: - Cách thứ nhất: chia làm 3 loại Mode địa chỉ:

1 Mode địa chỉ tức thời (Immediate Addressing Mode): sử dụng chính

giá trị bằng số ở vị trí của toán hạng

ví dụ mov ax,0001h

trong mode địa chỉ này phải có 1 vị trí nhớ hay thanh ghi làm

destination.(số chu kỳ máy cần thiết tương ứng là 10 và 4)

2 Mode địa chỉ thanh ghi (register addressing mode) cả dest và src

đều là thanh ghi Vì cả hai đều ở bên trong MPU nên được thực hiện rất

nhanh

ví dụ mov ax,cx cần 2 chu kỳ máy

3 Mode địa chỉ bộ nhớ (Memory Addressing Mode)

dest hoặc src là địa chỉ nhớ (hay nhãn cũng vậy)

có 2 loại mode địa chỉ bộ nhớ:

1 Địa chỉ trực tiếp (direct)

2 Địa chỉ gián tiếp (indirect)

-direct: dest hoặc src là một địa chỉ nhớ được xác định bằng số địa

chỉ hoặc nhãn

Trang 10

ví dụ: mov ax, mem1 thì nội dung ô nhớ có nhãn mem1 được chuyển

Có một số biến cách của mode gián tiếp này, tuy vậy ý nghĩa cơ bản

không khác nhau - Cách thứ 2: chia làm 7 Mode địa chỉ

1 Register addressing địa chỉ thanh ghi

thí dụ MOV AX,BX

2 Immediate addressing địa chỉ tức thời

MOV CL,-30; MOV CL, PI (PI EQU 3.14)

3 Direct addressing địa chỉ trực tiếp

thí dụ MOV AX,TABLE (trong đó TABLE là một nhãn)

4 Register indirect addressing địa chỉ gián tiếp thanh ghi

MOV AL, TABLE[DI] (trong đó TABLE là một tên của 1 byte (tên biến)

7 Base indexed addressing địa chỉ được chỉ số hoá cơ sở

MOV AX, [BX][DI+2] IV Các chỉ thị cho Assembler (Assembler Directives)

(có khoảng 60)

Các chỉ thị Assembler trông rất giống các mã lệnh ngôn ngữ Assembly, mỗi chỉ thị gồm có 4 trường (Fields)

tên Chỉ thị đối số (argument) ghi chú

PI EQU 3.14 ;xác định giá trị của PI

- tên (name field) cũng giống như trường nhãn trong dòng lệnh

có chỉ thị assembler cần trường tên, có chỉ thị không cần, tên bắt đầu bằng chữ cái, kết thúc bằng khoảng trống - Chỉ dẫn Assembler (directive field)

cũng tương tự như Op_code trong dòng lệnh

bắt đầu bằng khoảng trống và kết thúc bằng khoảng trống hoặc xuống dòng - argument field: chứa 1 địa chỉ nhớ hoặc 1 số để sử dụng cùng với chỉ thị

và do chỉ thị xác định

bắt đầu bằng khoảng trống và kết thúc bằng xuống dòng

*trong các chương trình đơn giản thường dùng các chỉ thị sau:

ASSUME chỉ định các thanh ghi đoạn; giúp Assembler đổi các nhãn thành các địa chỉ bằng cách báo cho Assembler biết ta định

dùng thanh ghi đoạn nào để đánh địa chỉ các nhãn này

format: ASSUME Seg-reg: Seg-name [, ]

trong đó Seg-reg là một trong các thanh ghi đoạn sau DS, CS,

ES, SS; Seg-name là tên sẽ đứng trước chỉ thị SEGMENT

thí dụ assume cs: cseg, ds: dseg

SEGMENT Định nghĩa đoạn

Trang 11

Dạng chung: SEGMENT COMBINE-TYPE ALIGN_TYPE CLASS ALIGN_TYPE: chỉ ra biên của segment bắt đầu ở đâu trong bộ nhớ.

- BYTE: begin anywhere

- WORD: begin at an even-numbered address (word)

- PARA: begin at an address divisible by 16

- PAGE: begin at an address divisible by 256

COMBINE_TYPE: chỉ ra một Segment sẽ được kết hợp với các Segment khác có cùng tên như thế nào Một chương trình có thể sử

dụng 4 Segment: Data, Code, Extra và Stack

Code, Data và Extra có thể được nối lại (joined) với nhau

(PUBLIC) hoặc trùm lên nhau (Overlapped) (COMMON)

Stack Segment nhất thiết phải có kiểu STACK

CLASS TYPE: ảnh hưởng tới thứ tự sắp đặt các Segment trong bộ nhớ Các Segment

có cùng tên Class được sắp đặt liên tiếp, Các Segment khác tên Class được sắp đặt theo thứ tự mà

chương trình LINK gặp

- CODE - DATA

- EXTRA

Với SEGMENT directive ta có thể dùng như sau:

với DATA SEGMENT: SEGMENT PARA PUBLIC 'DATA' với CODE SEGMENT: SEGMENT PARA PUBLIC 'CODE'

với EXTRA SEGMENT: SEGMENT PARA PUBLIC 'EXTRA' với STACK SEGMENT: SEGMENT PARA STACK 'STACK'

ENDS nơi kết thúc đoạn hay cấu trúc SEGMENT và ENDS chỉ đánh dấu điểm đầu

và điểm cuối của một Segment, chúng không cho Assembler biết đang định nghĩa loại Segment gì; việc này là

nhiệm vụ của Pseudo-Op: ASSUME

ORG địa chỉ khởi đầu của chương trình

DB định vùng dữ liệu dạng byte

DW định vùng dữ liệu dạng word

DD định vùng dữ liệu dạng 2 word, thí dụ DD 0 nghĩa là 4 byte

bằng 0

DUP lặp lại dữ liệu

EQU Equate: gán tên cho một hằng số (kiểu số hoặc kiểu String) tên này vĩnh viễn nhận giá trị hằng số đó (khác với

Directive = ') thí dụ PI EQU 3.14

Message EQU 'Hay vao so lieu'

PUBLIC khai báo tên dùng chung, làm cho 1 hoặc nhiều symbol đã được ĐN có thể được dùng chung trong nhiều Module mà các Module

đó sẽ được Linked với Module chứa khai báo PUBLIC này

Trang 12

format: External name: type[, ]

Như EXTRN get_hex

chỉ ra các SYMBOL đã được định nghĩa trong Modul

get_hex

- NAME là một Symbol đã được định nghĩa và được mô tả là

PUBLIC ở một Modul hợp ngữ khác

- TYPE có thể là một trong các kiểu sau:

+ nếu NAME là một ký hiệu trong DATA SEGMENT, EXTRA

SEGMENT thì kiểu có thể là BYTE, WORD hoặc DWORD

+ nếu NAME là một nhãn thủ tục thì kiểu có thể là NEAR

hoặc FAR

+ nếu NAME là một hằng được định nghĩa bởi EQU, =, thì

kiểu phải là ABS

* chú ý:

PUBLIC và EXTRN thường được sử dụng để phân chia các thủ tục Chẳng hạn để chạy một thủ tục có tên là SORT từ chương trình chính thì MODUL trong đó định nghĩa SORT phải chứa khai báo PUBLIC SORT và MODUL chính có chứa lời gọi tới SORT

phải có chứa khai báo:

EXTRN SORT: NEAR (hoặc FAR)

PROC và ENDP đánh dấu chỗ bắt đầu và chỗ kết thúc thủ tục Thủ tục là một khối các chỉ thị (instructions) có thể được gọi thực

hiện từ các vị trí khác nhau trong chương trình

END nơi kết thúc chương trình nguồn

Dạng: END Nhãn điểm vào chương trình (nhãn của lệnh đầu

tiên của chương trình)

Nếu chương trình của ta có chứa nhiều MODUL, ta (phải) gán nhãn cho chỉ dẫn END ở cuối MODUL chương trình chính, còn trong các MODUL phụ khác nhau không được gán nhãn cho chỉ

dẫn END

*sau đây là bảng các chỉ thị cho assembler

AND và logic, ví dụ: mov ax,7 and 8 BYTE định dữ liệu dài 1 byte COMMENT bắt đầu của lời bình CREF cross reference:danh sách các ký hiệu dùng để tham chiếu chéo CGROUP

(TLTK, bản dịch của LNH, trg 44) DGROUP

(TLTK, bản dịch của LNH, trg 44) DQ define quadruple:định vùng dữ liệu dạng 4 word

như DQ 0:tám byte 0 DT define ten: định vùng dữ liệu dạng 10 byte

như DT 0: mười byte 0 DW define word: định vùng dữ liệu dạng word (2 byte) DWORD double word: định dữ liệu dài 2 word

như: JMP DWORD PTR[SI] DUP Duplicate: lặp lại một xâu Như 10 DUP ('stack') ELSE ENDIF ENDM end macro ENDP EQ Equal: so sánh logic EVEN Đặt địa chỉ chẵn EXITM Exit macro Thoát khỏi macro FAR Báo nhãn nằm ở ngoài đoạn Như old_e LABEL FAR GE Greater than or Equal Phép toán logic lớn hơn hay bằng GROUP Nhóm các đoạn thành một đoạn; Như Nhóm GROUP code, data

Trang 13

(TLTK, bản dịch của LNH, trg 44) GT Greater Than Phép toán logic lớn hơn HIGH Chỉ byte cao của một word ;* Về các Pseudo_Op điều kiện, xem

(TLTK, bản dịch của LNH, trg 45) IF Khối điều kiện IF1 Khối điều kiện cho lần duyệt thứ nhất IF2 Khối điều kiện cho lần duyệt thứ hai IFB If blank Khối điều kiện khi không có tham số IFDEF If Defined Khối điều kiện khi đã có định nghĩa IFDIF

If diffent Khối điều kiện khi hai tham số khác nhau IFE If Equal Khối điều kiện khi bằng 0 IFIDN If Identical Khối điều kiện khi hai tham số bằng nhau IFNB If not Blank Khối điều kiện khi có tham số INCLUDE Chèn thêm vào chương trình một số chỉ thị lấy từ một tập tin

khác Như INCLUDE mylib.mac IRP Indefinite Repeat Macro có số lần lặp không xác định

Như IRP para? <one,two,three,four> sẽ lặp lại 4 lần IRPC Indefinite Repeat Character Macro có số lần lặp chữ

không xác định Như IRPC para? ABCD sẽ lặp lại 4 lần LABEL Nhãn

(TLTK, bản dịch của LNH, trg 44) LE Less than or Equal Phép toán logic nhỏ hơn hay bằng LENGTH Xác định chiều dài một kí hiệu LOCAL Định các kí hiệu chỉ được dùng trong nội bộ macro LOW Chỉ byte thấp của một word LT Less Than Phép toán logic nhỏ hơn LALL Liệt kê toàn bộ macro LFCOND Liệt kê khối điều kiện LIST Liệt kê chương trình MACRO Bắt đầu macro MASK Mặt nạ dạng bit MOD Modulo Cho số dư trong phép chia NAME Định tên của một chương trình hay mô-đun NE Not Equal Phép toán logic không bằng NEAR Báo nhãn nằm trong đoạn NOT Phép toán logic lấy bù OFFSET Offset trong đoạn OR Phép toán logic hoặc

%OUT In xâu ra màn hình PAGE Bắt đầu trang mới và định kích thước trang sẽ được in ra

(màn hình và máy in) khi hợp dịch

Dạng: PAGE [LINE], [COLLUMN]

ngầm định là: 57,80 (hợp với khổ giấy A4) PTR Pointer Dùng chung với BYTE, WORD, DWORD, NEAR và FAR để

định kích thước của một nhãn hay một biến RADIX Định cơ số RECORD Định kiểu bản ghi REPT Repeat Macro lặp SALL Không liệt kê macro SEG Giá trị đoạn ứng với một kí hiệu SHL Shift left Phép dịch chuyển trái.Như MOV AX,7 SHL 1 SHORT Nhảy xuôi gần SHR Shift right Phép dịch chuyển phải

Như MOV A,8 SHR 1 SFCOND Không liệt kê các khối điều khiển sai STRUC Structure Định nghĩa cấu trúc TCOND Liệt kê mặc định cho các khối điều kiện TITLE Psuedo_Op để tạo ra một tiêu để được căn thẳng trái trên dòng thứ 2 của mỗi trang (in) TITLE thường được đặt ở đầu chương trình, nhưng ta cũng có thể đặt nó ở bất cứ đâu trong

chương trình

Độ dài tối đa của TITLE: 60 dòng SUBTTL Sub Title để tạo ra một tiêu đề phụ được định tâm ở dòng thứ 3 (của trang tiếp theo ?), tiêu đề này thường được sử

dụng để mô tả nội dung của trang đó

Độ dài tối đa của SUBTITLE: 60 dòng XOR Phép toán logic hoặc Như MOV AX,7 XOR 9 XALL Liệt kê các macro sinh ra các mã lệnh hoặc dữ liệu XCREF Không liệt kê danh sách để tham chiếu chéo XLIST Không liệt kê chương trình WIDTH Định độ rộng của trường trong bản ghi WORD Định dữ liệu dài một word = Gán tên cho một hằng (kiểu số hoặc kiểu String) sau này trong

chương trình có thể gán lại

Trang 14

(khác với Directive EQU) 286C giả lệnh chế độ, báo cho Assembler sử dụng tập lệnh của 80286 phải đặt nó tại đầu chương trình, ngay sau các Pseudo-Op liệt

kê danh sách .8086 giả lệnh chế độ, báo cho Assembler sử dụng tập lệnh của 8086 đây là chế độ ngầm định $ Offset hiện hành

V các toán tử trong Assembly language

( Phần này sử dụng để tra cứu, TLTK số 1, trang 48 )

Toán tử là một sự sửa đổi (modifier) được sử dụng trong trường toán hạng (Operand Field) của một Op_code hay Pseudo_Op Có 5 loại toán tử: Số học, logic, quan hệ, trả lại giá trị, cho thuộc tính (An operator is a modifier used in the operand field of

an assembly language or pseudo-op statement.)

1 Toán tử số học (xem trang 29)

* format: value1 * value2;multiplies value2 by value1 * format: value1 * value2;multiplies value2 by value1

/ format: value1 / value2;divides value1 by value2 and returns the

the quotient

MOD format: value1 MOD value2; divides value1 by value2 and

returns the remainder

SHL format: value SHL expression; shifts values left by expression

bit positions

SHR format: value SHR expression; shifts values right by expression

bit positions 2 Toán tử logic (xem trang 29)

AND format: value1 AND value2; takes logical AND of value1 and

value2

OR format: value1 OR value2; takes logical inclusive-OR of

value1 and value2

XOR format: value1 XOR value2; takes logical exclusive-OR of

value1 and value2

NOT format: NOT value; reverses the state of each bit

in value; that is, it takes the

one's complement 3 Toán tử quan hệ (xem trang 30)

EQ format operand1 EQ operand2; true if the two operands are

GE format operand1 GE operand2; true if operand1 is greater

than or equal to operand2

4 Toán tử trả lại giá trị (xem trang 30)

$ format: $

cho lại giá trị hiện thời của bộ đếm vị trí bộ nhớ

Trang 15

SEG format: SEG Var_name, hoặc

SEG Label_name

trả lại giá trị Segment của biến hoặc nhãn

OFFSET format: OFFSET Var_name hoặc

OFFSET Label_name

trả lại giá trị OFFSET của biến hoặc nhãn

LENGTH format: LENGTH Var_name

trả lại độ dài tính bằng đơn vị (Byte hoặc Word) của biến đã

được định nghĩa bằng DUP

TYPE format: TYPE Var_name, hoặc

TYPE Label_name

đối với các biến, TYPE cho lại 1 nếu là kiểu Byte, 2 nếu là kiểu Word, 4 nếu là kiểu Double Word đối với các nhãn TYPE cho lại

-1 nếu là NEAR, -2 nếu là FAR

SIZE Dạng SIZE Var_name

trả lại giá trị là tích của Length và Type

5 Toán tử thuộc tính

PTR format: TYPE PTR EXPRESSION

khai báo lại kiểu (type) (BYTE hoặc WORD) hoặc khoảng cách (NEAR hoặc FAR) của một toán hạng địa chỉ bộ nhớ TYPE là thuộc tính mới còn Expression là một tên (indentifier) mà thuộc tính của nó

bị thay đổi (overriden)

DS: format: seg-reg:addr-expr hoặc ES: seg-reg:label hoặc

SS: seg-reg:variable

CS: thay thế (overrides) thuộc tính đoạn (segment attribute) của một

nhãn, biến hoặc biểu thức địa chỉ

SHORT xem ở lệnh JMP, trang

HIGH format: HIGH value hoặc

HIGH expression

trả lại giá trị là byte cao của 1 giá trị số hoặc địa chỉ 16 bit

LOW format: LOW value hoặc

LOW expression

trả lại giá trị là byte thấp của 1 giá trị số hoặc địa chỉ 16

bit VI Hằng số trong chương trình nguồn

Assembler chấp nhận việc sử dụng một vài dạng hằng số sau: 1 Binary

là một dãy số 0,1 kết thúc bởi ký tự B, thí dụ 10111010B 2 Decimal

là một dãy các chữ số từ 0 đến 9, có thể kết thúc bởi ký tự D hoặc không

đó là một dãy các chữ cái, chữ số, ký hiệu được ghi trong dấu nháy đơn

hay kép, thí dụ 'Hello World!', "Don't enter a number here" bài tập 1 Đổi các số thập phân sau sang dạng nhị phân:

a) 12; b) 17; c) 45; d) 72 2 Đổi các số nhị phân sau sang dạng thập phân:

Trang 16

a) 00001000; b) 00010101; c) 00011111; d) 11000011 3 Đổi các số ở câu 2 sang dạng thập lục phân 4 Đổi sang dạng thập phân số 0D8H trong trường hợp: - 0D8H biểu diễn số không dấu - 0D8H biểu diễn số có dấu

hết bài 1

Bài giảng môn Assembly Language, Bài 1 - $ - Nguyễn Đình Việt, Khoa CNTT, ĐHQGVN,HN 1995 -

Bài 2 Các bước trong quá trình tạo 1 chương trình chạy được

Trên thị trường có khá nhiều Assembler, trong các bài giảng môn học này chúng ta

sẽ sử dụng Macro Assembler của MicroSoft (MASM.EXE), nó tương thích với IBM Macro Assembler

Cho đến nay (1990), IBM đã đưa ra thị trường 2 Version của Macro Assembler, Version 1 , version2 Để xây dựng chương trình cho họ máy AT, chúng ta cần phải dùng version 2 (của IBM Macro Assembler) hoặc version 3 (của MicroSoft Macro Assembler)

Đĩa Macro Assembler của IBM có 2 chương trình Assembler tách biệt: - Small

Assembler (ASM): để dùng cho các máy tính có bộ nhớ <= 128 KB và

có tập lệnh ít hơn của MASM MicroSoft không có Small Assembler như IBM - Macro Assembler (MASM)

I Các bước chính

Bứơc 0:

Xác định nhiệm vụ của chương trình, thiết kế chương trình Trong bước này ta

thường cần vẽ lưu đồ (Flowchart) Bước này đặc biệt quan trọng nếu chương trình là dài và phức tạp Nên thực hiện chiến thuật "Top-Down Program Design"

Bước 1 Soạn chương trình nguồn

Dùng 1 chương trình soạn thảo văn bản, ví dụ SideKick, Turbo Pascal

để soạn thảo chương trình nguồn - Không nên dùng các hệ soạn thảo trong đó có sử dụng các mã ASCII mở

rộng, hoặc các ký tự điều khiển (Như Word Perfect, Bked v.v ) - dùng SideKick có rất nhiều tiện lợi, vì đó là chương trình thường trú nhỏ

các lệnh soạn thảo khá giống Turbo Pascal Version 3.01a, quen thuộc với

sinh viên - dùng Turbo Pascal để soạn thảo rất dễ trình bày chương trình nguồn đẹp

vì chức năng TAB của nó rất tiện lợi cho soạn thảo chương trình - (hướng dẫn sinh viên sử dụng SideKick nếu cần thiết) - ghi file nguồn lên đĩa, ví dụ với tên là

Trang 17

sau đó ta phải trả lời 3 câu hỏi sau:

Object filename [vidu1.obj]: nếu ta đồng ý thì ấn Enter (nói chung là ta

đồng ý với các gợi ý của MASM)

Source Listing [Nul.lst]: Cross Reference [Nul.crf]:

Sau đó MASM sẽ hiển thị như sau:

Microsoft (R) Macro Assembler Version 5.10 Copyright (C) Microsoft Corp

1981-1985 All right reserved 51712 + 154624 Bytes symbol space free

Trong file lst Macro Assembler còn đưa ra cả địa chỉ (Segment:Offset) của các lệnh

và dữ liệu của chương trình, việc này rất có ích khi chúng ta muốn phân tích các chương trình khó, chẳng hạn phân tích các đoạn mã

Virus v.v - cross-reference listing file:

File vidu1.crf (crf: cross reference) còn gọi là File tham khảo chéo, (cross-reference listing), nó cho số dòng tại đó mỗi ký hiệu (symbol) được định nghĩa và số hiệu tất cả các dòng khác, tại đó có tham chiếu

(refer to) tới ký hiệu này Để MASM.EXE sinh ra file này khi được hỏi:

Cross Reference [Nul.crf]:

ta cần đánh tên file (đuôi ngầm định là crf) Sau khi đã hợp dịch (chạy

MASM.EXE) cần chạy chương trình CREF.EXE

CREF VIDU1; - MAP - Map listing file (file bản đồ chương trình)

Việc tạo ra file này là tuỳ chọn đối với LINK.EXE File này tóm tắt về các đoạn của chương trình, trong mỗi đoạn nó chỉ ra địa chỉ offset 'start' và 'stop' , chiều dài mỗi đoạn của chương trình và class (loại)

của các đoạn

Để tạo ra file MAP ta làm như sau:

LINK VIDU1,,; (2 dấu phẩy trước dấu chấm phẩy)

Lưu ý: - trường hợp có đánh dấu '; ' sau tên của chương trình nguồn: MASM.EXE tự động đặt tên file đích là vidu1.obj , không tạo các file lst và crf

tương ứng - trường hợp không đánh dấu '; ' sau tên của chương trình nguồn:

MASM.EXE

thực hiện theo các bước nêu trên

- cách sử dụng các chỉ dẫn cho MASM.EXE để có thể in các thông báo lỗi ra máy

in, tạo các file tham chiếu chéo, định trang in (số dòng/1 trang,

số cột mỗi dòng)

* sau bước này Assembler mới tạo ra File vidu1.obj; đây là một File trung gian, gọi

là File đích (Object file), nó chứa chương trình của chúng ta ở dạng ngôn ngữ máy, nhưng kèm theo một số thông tin mà chương trình Link

của DOS sẽ dùng đến - sửa các lỗi do Assembler thông báo:

Trang 18

nếu có lỗi, Assembler sẽ thông báo số thứ tự của dòng có lỗi, loại lỗi, sau đó

Assembler tiếp tục hợp dịch các dòng chương trình nguồn tiếp sau

và lại thông báo lỗi nếu gặp phải

Ta nên ghi lại các thông báo lỗi và STT dòng có lỗi để sửa (có thể in

luôn ra giấy bằng lệnh Print Screen) luôn một lần - hợp dịch lại và lại sửa lỗi cho đến khi hết lỗi

* Một số thông báo lỗi của Macro Assembler:

- Block nesting error:

thông báo lỗi này thường kèm theo thông báo "Open procedures" hoặc "Open

segments", hãy xem giải thích về các thông báo này như ở dưới đây - End of file, no END directive:

thiếu chỉ thị assembler END ở cuối file hoặc phải thêm 1 dòng trống sau

dòng chứa chỉ thị END - Must be declared in pass 1:

thông báo này thường liên quan đến giả lệnh GROUP, có thể ta chưa định

nghĩa một tên đoạn được khai báo trong giả lệnh GROUP - No or Unreadable CS:MASM cần thấy giả lệnh ASSUME khi hợp dịch một số chỉ thị như CALL hay

JMP - Open procedures:

thiếu nhãn PROC hay ENDP hoặc các tên không trùng nhau trong cặp giả

lệnh PROC - ENDP - Open segments:

thiếu giả lệnh Segment hoặc ENDS hoặc tên đi cùng với hai giả lệnh này - Symbol not defined

Đây là một thông báo lỗi thường thấy khi chúng ta mới học ngôn

ngữ Assmblly, cần kiểm tra các vấn đề sau:

+ sử dụng một tên chưa khai báo hoặc đánh sai một tên đã được khai báo

+ thiếu khai báo EXTRN mà chương trình lại sử dụng một tên nằm trong Modul ngoài; hoặc tên trong modul ngoài và tên được gọi đến không

trùng nhau (do ta đánh sai chẳng hạn)

Bước 3 Link (kết nối chương trình và số liệu v.v )

chương trình LINK có 2 nhiệm vụ chính: 1./ DOS có thể để 1 chương trình ở chỗ nào đó do nó sắp đặt cho thuận tiện Việc này tránh cho NSD không phải chỉ ra việc đặt chương trình ở đâu Muốn cho chương trình nguồn (và sau đó là dạng obj) sử dụng được đặc

điểm này (relocatable) cần phải có chương trình LINK của DOS 2./ NSD thường viết chương trình theo các modul, thử riêng rẽ từng Modul, do vậy sẽ tạo ra nhiều file obj tương ứng Nhiệm vụ thứ 2 của LINK chính là kết nối các object module lại thành 1 modul duy nhất, chạy

được

Thí dụ LINK MOD1 + MOD2 + MOD3 sẽ kết nối các file MOD1.OBJ,

MOD2.OBJ, MOD3.OBJ để tạo thành file MOD1.EXE chạy được

Ta cần sử dụng chương trình Link.exe (lệnh ngoại trú của DOS) để tạo ra

một file exe từ File obj - A:\> Link vidu1;

Microsoft 8086 Object Linker

Version 3.02 (C) Copyright Microsoft Corp 1983, 1984, 1985

Warning: No stack segment

There was an error detected

Trang 19

Error là lỗi nhưng chính là điều chúng ta muốn, nó báo rằng chưa có đoạn

stack * sau khi thực hiện bước này, ta có file vidu1.exe, nói chung có thể cho

chạy ngay được Tuy nhiên ta cần nghiên cứu cách tạo file com trước đã * Xem tuỳ chọn của LINK để tạo ra file MAP đã trình bày ở bước 2

* Một số thông báo lỗi của LINK

- Fixup offset exceeds field with:

Với thông báo này ta cũng khó tìm ra được lỗi, có thể là do có một lời gọi xa tới một thủ tục (Call far) nhưng trong thủ tục đó lại khai báo nó là near (Proc near) Lỗi này cũng có thể xảy ra nếu toàn bộ chương

trình vượt quá 64KB, dùng file MAP có thể thấy được điều này

- Symbol defined more than once:

xảy ra khi LINK phát hiện thấy 1 biến hay thủ tục được định nghĩa

trong hai file

- Unresolved externals:

có thể do thiếu khai báo public cho 1 biến hay thủ tục, hoặc tên trong

1 thủ tục external sai

- Warning: no stack segment

Đây thực ra không phải là thông báo lỗi mà là lời nhắc nhở của LINK, ta

thường luôn thấy nó khi LINK các file OBJ để tạo ra các file COM

Bước 4 Dịch chương trình sang File dạng COM

Để tạo ra file com, ta cần chương trình Exe2bin.exe của DOS Chương trình này chuyển 1 file dạng exe hay bin sang file dạng com - Exe2bin vidu1 vidu1.comChúng ta dùng lệnh DIR của DOS để kiểm tra sự tồn tại của vidu1.com trên

đĩa

Đôi khi có thể thấy thông báo lỗi 'File cannot be converted', đây là thông báo lỗi duy nhất của EXE2BIN, nguyên nhân sinh ra lỗi này có thể

như sau:

+ các đoạn xếp sai thứ tự, cần kiểm tra lại bằng file MAP (xem phụ lục

C trong sách 'Nhập môn Assembler', Peter Norton

+ chương trình chính không đứng đầu tiên trong lệnh LINK

+ chương trình chính không có chỉ thị Assembler ORG 100H đứng liền dưới

khai báo CODE_SEG SEGMENT PUBLIC

Ngoài ra cần kiểm tra lại xem sau chỉ thị END cuối cùng trong modul chương trình chính đã ghi nhãn của lệnh đầu tiên của chương trình chưa

- Lưu ý: các Version Dos sau 5.0 không có File Exe2bin.exe vì DOS không chủ trương hỗ trợ việc tạo các file com, muốn thực hiện bước 4 này ta

cần đặt lệnh

DEVICE=PATH_NAME\SETVER.EXE

trong file CONFIG.SYS, tất nhiên cần phải có SETVER.EXE tại đường dẫn

PATH_NAME

Bước 5 Chạy thử chương trình

- Nếu chương trình không dài, thì tốt nhất là dùng Debug để chạy thử từng bước Lệnh T (Trace), theo dõi quá trình biến đổi nội dung các thanh ghi,

việc chuyển số liệu v.v - Nếu chia chương trình thành từng khối, có thể hợp dịch từng khối và cho

Trang 20

chạy thử từng Modul, sau khi chạy tốt mới ghép nối lại với nhau - Nếu có lỗi thì lặp lại các bước trên

II Hướng dẫn sử dụng chương trình Debug

Trình bày 19 lệnh của DEBUG, 4 lệnh còn lại liên quan đến bộ nhớ mở rộng

XMS và EMS không cần trình bày

Bài tập 2.1 In ra màn hình 1 ký tự (ký tự 'A')

Bài tập 2.2 In ra màn hình một xâu ký tự 'Darling, I love you'

Bài tập 2.3 hỏi tên người (từ bàn phím) rồi gửi lời chào người đó

Bài tập 2.4 Nhận vào từ bàn phím 5 xâu ký tự (n <= 5); in ra màn hình 1 trong 5 xâu

ký tự đó

Bài tập 2_1 (BT2_1.ASM) In ra màn hình 1 ký tự (ký tự 'A')

Seg_a segment:100 jmp 103

assume cs:seg_a, ds:seg_a:102 db 41

org 100h:103 mov ah,02 start: jmp short loc_1:105 mov dl,[102] data_1 db 41h:109 int 21 loc_1 mov ah,02:10b int 20

assume cs:seg_a, ds:seg_a:102 db'Darling, I love you$'

org 100h:118 mov dx,0102 start: jmp short loc_1:11b mov ah,09 data_1 db'Darling, I love you$':11d int 21 loc_1 mov dx,offset data_1:11f int 20

============== SEG_A SEGMENT BYTE PUBLIC

ASSUME CS:SEG_A, DS:SEG_A

ORG 100h

BT2_3 PROC FAR

94E0:0100 START: 94E0:0100 EB 25 JMP SHORT LOC_1;(0127) 94E0:0102 90

DB 90H 94E0:0103 0D 0A 24 DATA_1 DB 0DH, 0AH, '$' 94E0:0106 57 68 61 74

20 69 DATA_2 DB 'What is your name ?: $' 94E0:010C 73 20 79 6F 75 72;xref 94E0:0129, 012C 94E0:0112 20 6E 61 6D 65 20 94E0:0118 3F 20 3A 20 24

94E0:011D 48 65 6C 6C 6F 20 DATA_3 DB 'Hello Mr.$';xref 94E0:0143, 0146 94E0:0123 4D 72 2E 24 94E0:0127 LOC_1:;xref 94E0:0100 94E0:0127 B4 09

Trang 21

MOV AH,9 94E0:0129 BA 0106 MOV DX,OFFSET DATA_2 94E0:012C CD 21 INT 21H;DOS Service 09h

;display char string at ds:dx 94E0:012E B4 0A MOV AH,0AH 94E0:0130 BA 015F MOV DX,OFFSET DATA_4 94E0:0133 8B DA MOV BX,DX 94E0:0135 C6 07

FE MOV BYTE PTR [BX],0FEH 94E0:0138 CD 21 INT 21H; DOS Service 0Ah

; get keybd line, put at ds:dx 94E0:013A B4 09 MOV AH,9 94E0:013C BA 0103 MOV DX,OFFSET DATA_1 94E0:013F CD 21 INT 21H 94E0:0141 B4 09 MOV AH,9 94E0:0143 BA 011D MOV DX,OFFSET DATA_3 94E0:0146 CD 21 INT 21H 94E0:0148 B4 09 MOV AH,9 94E0:014A BB 015F MOV BX,OFFSET

DATA_4 94E0:014D 8B D3 MOV DX,BX 94E0:014F 02 5F 01 ADD BL,[BX+1] 94E0:0152 83 C3 02 ADD BX,2 94E0:0155 C6 07 24 MOV BYTE PTR [BX],24H; '$' 94E0:0158 83 C2 02 ADD DX,2 94E0:015B CD 21 INT 21H 94E0:015D CD 20 INT 20H; Program Terminate 94E0:015F 3F DATA_4 DB 3FH; '?'

BT2_3 ENDP SEG_A ENDS

END START

Bài tập 2.4 Nhận vào từ bàn phím 5 xâu ký tự (n <= 5); in ra màn hình 1 trong 5 xâu

ký tự đó

;GET 5 STRING FROM KBD, THEN ASK WHICH OF THEM WILL BE SEND

TO SCR CGROUP GROUP CODE_SEG

ASSUME CS: CGROUP CODE_SEG SEGMENT BYTE PUBLIC

ORG 100H

START: JMP FIRST

MSG DB "Enter 5 string ",0DH,0AH,"$" MSG1 DB "one:$" MSG2 DB "two:$" MSG3 DB "three:$" MSG4 DB "four:$" MSG5 DB "five:$" ASK_FOR_OUT DB

"Which string will be out ?: $" NUMBER DB 0

FIRST: MOV AH, 09H

Trang 22

MOV AH,09H;ask for 3rd string

Trang 23

INT 20H ; - CR_LF PROC NEAR

0FEH,?,0FEH DUP(0) STR4 DB 0FEH,?,0FEH DUP(0) STR5 DB 0FEH,?,0FEH DUP(0)

CODE_SEG ENDS END START

Bài giảng môn Assembly Language, Bài 2 - $ - Nguyễn Đình Việt, Khoa CNTT, ĐHQGVN,HN 1995 -

Bài 3 Dạng của 1 chương trình mẫu

Bài này trình bày

-các mô hình tổng quát để xây dựng nên 1 chương trình Mẫu chương trình này là chung nhất cho mọi chương trình Khi chúng ta viết chương trình của mình, ta chỉ cần điền số liệu và các chỉ thị cho chương trình cụ thể đó

-về sự khác nhau giữa com files và exe files

I Main Program Module: Mô dul chương trình chính

Sau đâu là 1 mẫu chung cho 1 modul nguồn, nó bao gồm 1 chương trình đầy đủ hoặc

nó sẽ được kết nối với 1 hoặc 1 số modul (phụ) khác để tạo nên 1 chương trình

PAGE ,132 TITLE (Insert title here) SUBTTL (Insert sub_title here) (Insert EXTRN statement, if approriate)

STACK SEGMENT PARA PUBLIC 'STACK'

DB 64 DUP('STACK ') STACK ENDS

DSEG SEGMENT PARA PUBLIC 'DATA'

(Insert data here) DSEG ENDS

CSEG SEGMENT PARA PUBLIC 'CODE'

ASSUME CS:CSEG, DS:DSEG, SS:STACK

ENTRY PROC FAR;entry point

;set up the stack to contain the proper values so this program ;can return to DOS or Debug

Trang 24

MOV AX,DSEG

MOV DS,AX

(insert instructions here)

RET;return to DOS or Debug ENTRY ENDP CSEG ENDS END ENTRY

chú ý mẫu này là chương trình tổng quát, ta có thể sửa đổi 1 số điểm sau: -Title: Tiêu đề thường chỉ ra tên File trên đĩa của chương trình này -Nếu Modul này có chứa tham chiếu tới các thủ tục hoặc biến, mà chúng được dịnh nghĩa ở Modul phụ, thì nhất thiết phải có chỉ thị EXTRN để liệt kê

danh sách chúng -Ta dùng AX để khởi tạo STACK và địa chỉ đoạn dữ liệu, nhưng cũng có thể

dùng các thanh ghi đa năng khác

Vì vậy, nếu chương trình của ta nhận giá trị vào của người sử dụng từ thanh ghi AX, khi đó ta bắt buộc phải dùng thanh ghi khác (ví dụ DI) để

khởi tạo -Về thủ tục:

Các Pseudo_Op Proc và Endp đánh dấu điểm đầu và điểm cuối của 1 thủ tục Thủ tục

là một khối lệnh mà có thể được gọi thực hiện từ nhiều nơi trong

chương trình

Nếu thủ tục kết thúc bằng lệnh RET (Return from Procedure) thì ta có thể gọi nó là một chương trình con (Subroutine) Lệnh RET làm cho MPU thực hiện chương trình

đã gọi (tới thủ tục)tiếp tục thực hiện lệnh (trình tự)

sau lời gọi đó

Một thủ tục luôn có một trong hai thuộc tính: NEAR và FAR được chỉ

ra bởi Operand đứng ngay sau Proc directive, trong đó NEAR là ngầm định

+ Proc_name PROC NEAR: thủ tục Proc_name chỉ có thể được gọi từ trong chính SEGMENT chứa thủ tục đó Khi gặp lời gọi tới 1 thủ tục NEAR,

MPU chỉ cất Offset (IP) của địa chỉ trở về lên Stack

Với chương trình dạng COM, luôn luôn dùng NEAR

+ Proc_name PROC FAR: thủ tục Proc_name có thể được gọi từ bất cứ

SEGMENT nào Khi gặp lời gọi tới 1 thủ tục FAR, MPU chỉ cất địa chỉ

trở CS:IP lên Stack

Với chương trình dạng EXE, luôn luôn dùng FAR cho thủ tục chính

II SECONDARY Module: Mô dul phụ

sau đây là mẫu modul phụ, sẽ được Linked với Main Modul ở ví dụ trên

Page ,132 Title (điền các tiêu đề ở đây.) public pname

(khai báo public cho các biến tại đây nếu cần thiết) dseg segment para public 'data'(đặt các dữ liệu tại đây) dseg ends cseg segment para public 'code'

assume cs:cseg, ds:dseg pname proc near

(đặt các lệnh ở đây)

ret;trở lại chương trình gọi pname endp cseg ends

end

Chú ý có thể sửa đổi lại một số khai báo như sau:

1 Vì Code segment của modul phụ này có cùng tên (cseg) với tên của code segment thuộc modul chính, nên ta khai báo Pname proc near Để gọi Pname từ segment khác, phải thay near bằng far 2 vì data segment của modul phụ này có cùng tên với data segment của modul chính, nên ta không cần khởi tạo DS (không cần assume

Trang 25

ds:dseg) Nếu modul phụ này dùng data segment khác tên với data segment của modul chính thì ta phải dùng pseudo op: assume ds: tên data segment <> dseg 3 ở đây ta đặt tên thủ tục là Pname, khi lập chương trình của mình, ta có thể thay bằng tên theo ý ta ở các vị trí: + khai báo public ở trên đầu thủ tục + khai báo proc ở giữa + khai báo endp ở cuối 4 ở modul phụ, ta có khai báo public để tương ứng với khai báo Extrn ở modul chính trong 2 ví dụ này, nếu modul chính gọi modul phụ, thì ở modul chính phải có khai báo

extrn pname: near III .com file

DOS có thể chạy được 2 loại file chương trình viết bằng assembly language, đó là com file và exe file Nói chung người sử dụng dùng exe file khi cần tạo các chương trình lớn, dài hơn 64 KB, và dùng com file khi cần tạo các file chương trình <= 64KB việc tạo ra com file cần theo một số quy tắc khác exe file, sau đây là một số điểm quan trọng:

1 Các quy tắc để tạo ra com file

1/ bỏ qua tất cả các stack, data và extra segments

2/ chỉ xác định 1 code segment, nhưng để tất cả lệnh và dữ liệu vào đó

3/ ở assume pseudo-op ta trỏ tất cả 4 thanh ghi đoạn tới code segment

ví dụ

cseg segment para public 'code'

assume cs:cseg, ds:cseg, es: cseg, ss: cseg

4/ đặt trước điểm vào của chương trình (lệnh đầu tiên của ch tr) với

chỉ thị assembler

org 100h; để dành 256 byte đầu tiên cho PSP (Program segment prefix)

5/ đặt tất cả các dữ liệu trước các lệnh của ch trình Tất nhiên trước

dữ liệu phải có 1 lệnh JMP để nhảy qua vùng dữ liệu

2 Các quy tắc tạo các modul phụ của com file

cũng tuân theo các quy tắc trên, nhưng cần lưu ý: - đặt tên cho segment ở modul phụ giống tên segment ở modul chính

ví dụ tên cseg dùng ở cả modul chính lẫn phụ - cũng giống như ở exe file, ở lệnh END cuối modul phụ, không được viết

nhãn sau END

3 Mẫu cho 1 com file

Mẫu cho 1 mô đun chính

Page ,132 Title (ta để tiêu đề ở đây) (đặt khai báo Extrn tại đây nếu cần)

Cseg segment Para Public 'Code'

Assume cs: cseg, ds: cseg, es:cseg, ss:cseg

Trang 26

Mẫu cho 1 mô đun phụ (ch trình con) của com file

Page ,132 Title (ta để tiêu đề ở đây)

public Pname (đặt Public cho các biến tại đây, nếu có)

Cseg segment Para Public 'Code'

Assume cs: cseg, ds: cseg, es:cseg, ss:cseg

jmp Pname; nhảy qua miền dữ liệu

1) ngắn hơn hẳn so với exe files

2) nói chung nạp vào bộ nhớ nhanh hơn exe files

3) dễ viết hơn vì không phải khởi tạo các thanh ghi cho Stack, DS,

ES

4) các ch trình thường trú phải viết dưới dạng com 4.1 nhược điểm

1) Không thể dài hơn 64 KB

2) chúng yêu cầu phương pháp viết ch trình chặt chẽ hơn

3) vì chỉ sử dụng có 1 segment nên không có sự tách biệt hoàn toàn

giữa các lệnh và số liệu

4) Không truy nhập được các thủ tục hoặc số liệu ở các segment khác, do đó rất khó

sử dụng các modul được NSD khác xây dựng, nếu các modul này đặt tên cho

segment mà chúng dùng khác tên segment của

CODE_SEG SEGMENT BYTE PUBLIC

ASSUME CS:CODE_SEG, DS:CODE_SEG

Trang 27

ORG 100H

START: JMP FIRST

MSG DB "Enter 2 number (0 =< x <= 255):$" MSG1 DB "number 1:$" MSG2 DB

"number 2:$" msg3 DB "The Product is: $" NUMBER_1 DB 0 NUMBER_2 DB 0 RESULT LABEL BYTE PRODUCT DW 0

FIRST: MOV AH,09H

; - ;This procedure get in

an integer number between 0 255 ;Return it to calling prog in

AX ; - Get_an_Int_num PROC; 0 <= X <= 255

mov cx,1;CX counts digits typed in loop_2: Call Get_a_dec_digit

cmp al,0Dh je exit_2 sub al,30h

xor ah,ah mov dx,ax

Trang 28

JA EXIT_2 jmp loop_2 exit_2: mov ax,temp_var

pop dx pop cx pop bx

ret Get_an_Int_num

ENDP ; - ;This

procedure gets in a decimal digit between 0 9 ;checks input for digit ;Return it to calling prog in AL ; - Get_a_dec_digit PROC loop_1:

push dx

mov ah,08

int 21h

cmp al,0Dh je exit_1 cmp al,30h jb loop_1 cmp al,39h ja loop_1

mov dl,al mov ah,02

int 21h exit_1: pop dx

ret Get_a_dec_digit ENDP

; - ;This Prog will Write out an Integer number in AX (Int number) ;let refer to example in 'Nhap mon

Assembler', Peter norton, Pg 83 WRITE_INT_NUMBER PROC NEAR

MOV BX,10 XOR CX,CX NONE_ZERO: XOR DX,DX

DIV BX PUSH DX INC CX

MOV AH,02 MOV DL,13

Trang 29

Bài giảng môn Assembly Language, Bài 3 - $ - Nguyễn Đình Việt, Khoa CNTT, ĐHQGVN,HN 1995 -

Bài 5 Các thao với File

TLTK: 1 Assembly Language for Pascal Programmers; Steven Holzner, Brady

Page 71

2 PC Intern System Programming, Michael Tischer, Chapter 19

Mục đích của tính toán là tạo ra các OUTPUT có thể sử dụng được bên ngoài chương trình Output lên màn hình là một trong các phương pháp như vậy, nhưng sử dụng File rất quan trọng vì nó là bộ nhớ ngoài, có thể lưu trữ thông tin ngay cả khi tắt máy

Ta có thể in ra một File, có thể tổ chức một file để lưu giữ dữ liệu và các ký tự cho 1 Editor, file có thể là chính chương trình

DOS có một bộ dịch vụ về File rất phong phú, phần lớn là các dịch vụ trong INT 21h

Các Service của INT 21h represent most of the resources mà những người lập trình

sử dụng trong DOS Bên cạnh INT 20h (kết thúc chương trình) và các ngắt cho phép đặt một chương trình thường trú, những ngắt khác thực sự cần thiết là các ngắt cho phép đọc/ghi đĩa, INT 25h và INT 26h Trong khi đó số lượng các Service của INT 21h không ngừng tăng lên, ở DOS version 4.0 con số đã lên tới 6Ch (=108d)

I File Control Blocks (FCB)

Trước DOS 2.0, DOS thường làm việc với File thông qua FCBs FCBs giữ các

thông tin về file: Filename, tên ổ đĩa chứa file, kích thước file Tuy nhiên FCBs hạn chế độ dài tối đa của File là 11 character Từ DOS 2.0 trở đi, IBM đưa ra Directory

và vì vậy cần phải chỉ ra đường dẫn tới file, tất nhiên 11 ký tự nói chung là không đủ,

đó là lý do mà File handles đã được IBM (và Microsoft) đưa ra

II File handles

Một File handle là một từ 16 bit làm đại diện cho 1 file trước DOS (A file handle is a 16-bit word that stands, to DOS, for a file.) Khi chúng ta muốn sử dụng một file, ta trao cho DOS filename còn DOS thì trả lại một File handle trong một thanh ghi

(thường là AX) Khi chúng ta muốn làm một việc gì đó với file - rename file, open file, read from file thì dịch vụ của INT 21h sẽ cần file handle 16 bit đó trong một thanh ghi nào đó (thường là BX)

Trình tự điển hình để Copy một file rất giống với trong ngôn ngữ lập trình Pascal - ta

sẽ mở, đọc, ghi và đóng file lại - ngưng ta sẽ sử dụng DOS chứ không phải là

PASCAL ở đây

Ta thực hiện công việc đó như sau: - tạo một xâu ký tự tên file (ASCIIZ string) trong

bộ nhớ, ví dụ:

Trang 30

FILE_36 DB "C:\Novel\Chapter.89",0 - mở file và lấy file handle cho nó (INT 21h service 3Dh) - tạo một file mới (INT 21h service 3Ch) - đọc từ file nguồn (file thứ nhất) (INT 21h service 3Fh) - viết vào file mới (file đích hay file thứ hai) (INT 21h service 40h) - sau đó đóng cả hai file lại (INT 21h service 3Eh) service 3Fh giống như Read() service 40h giống như Write() Cũng giống như trong Pascal, chúng ta có thể coi các thiết bị (devices) như các file logic Đặc biệt chúng ta có thể sử dụng Predefined handle để truy cập tới các thiết bị vật lý khác nhau.

Sau đây là một số Predefined handles:

handle Device

0 Standard Input (STDIN), usually keyboard 1 Standard Output (STDOUT), usually screen

2 Standard Erro device (STDERR)

3 Standard Auxiliary device (STDAUX)

4 Standard Printer

Thí dụ, nếu chúng ta chọn service 40h và trao giá trị 04h cho file handle thì Output

sẽ đi ra máy in

II Các dịch vụ file handle của DOS và các mã lỗi (error codes)

1 Các dịch vụ File Handle

Có rất nhiều dịch vụ file handle của DOS, sau đây là một số service:

File Handle Service Number You set It Returns

- Create Subdirectory 39h DS:DX to ASCIIZ if CY=1, AX chứa mã lỗi

string Delete Subdirectory 3Ah DS:DX to ASCIIZ if CY=1, AX chứa mã lỗi

string Change Directory 3Bh DS:DX to ASCIIZ if CY=1, AX chứa mã lỗi

string Create File 3Ch DS:DX to ASCIIZ if CY=1, AX chứa mã lỗi

DS:DX=Buffer Write to File 40h BX=Handle if CY=1, AX chứa mã lỗi CX=#Byte wanted

DS:DX=Buffer Delete a File 41h DS:DX to ASCIIZ if CY=1, AX chứa mã lỗi string Move Read/Write pointer 42h CX:DX=#Bytes to if CY=1, AX chứa mã lỗi

move if CY=0, DX:AX=new

BX=File Handle location in file

AL="Methode" Find 1st Matching file 4Eh DS:DX to ASCIIZ if CY=1, AX chứa mã lỗi

CX=Attribute if CY=0 then DTA has

21 bytes reserved

1 byte: file's attrib

1 word: file's time 1 word: file's date

Trang 31

1 Dword: file's size 13 byte: ASCIIZ name Find next Matching file 4Fh DTA as set same as for 4Eh

by service 4Eh Rename File 56h DS:DX to ASCIIZ if CY=1, AX chứa mã lỗi

ES:DI to new

name (also ASCIIZ)

Còn có rất nhiều Serice khác nữa, trong đó có các Service tạo các file tạm

(temporary file), lấy hoặc đặt lại các thuộc tính Date, Time của file

1.1 Các mã lỗi trả về trong AX (Error Codes)

Trong DOS version 4.0 có 91 mã lỗi khác nhau, ở các version sau này con số đó còn lớn hơn Sau đây là một số mã lỗi thường gặp:

Error codes Means

1 Invalid function number

2 File not found

3 Path was not found

4 Too many files open at once

5 Access denied for this operation

6 File handle used is invalid

7 Memory Control Blocks destroyed

8 Insufficient memory

15 Invalid drive was specified

16 Cannot delete current directory

19 Cannot write on a write-protected diskette

21 Drive not ready 23 Disk data error 25 Disk seek error

27 Sector not found

28 Printer needs paper

29 Write fault

30 Read fault

61 Print queue is full 1.2 File Access Modes

Mode truy cập file được truyền qua AL, có các Mode sau:

Access Mode for Opening Files Means

0 Open file for Read only 1 Open file for Write only

2 Open file for both Read and Write

1.3 Các thuộc tính của File (không được là tên nhãn đĩa) truyền qua CX

File Attribute Means

0 Plain old file

1 Read-Only

2 Hidden File (Hidden from directory searches)

4 A System file

8 Used for the Volume label of a Disk

10 This file name is the name of a subdirectory

1.4 Cách dịch chuyển Read/Write Pointer khi dùng service 42h

Ngày đăng: 07/07/2014, 21:21

TỪ KHÓA LIÊN QUAN

w