Tải bản đầy đủ (.pdf) (303 trang)

Các bài tập lập trình bằng ngôn ngữ assembler

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (29.8 MB, 303 trang )


TS ĐẶNG THÀNH PHU

CÁC BÀI TẬP LẬP TRÌNH
BẰNG NGƠN NGỮ ÂSSEMBLER

NHÀ XUẤT BẢN KHOA HỌC VÀ KỸ THUẬT
HÀ NÔ I - 2001


Chịu trúi h nhiệm xuất hàn :
Biên tập :
V ẽ h ìa :

PGS. TS TƠ ĐÀNG HẢI
TIÊN KHANG, KIM ANH
H U ^N G L A N

6.6T7
KHKT-2001

In lOTO bản khổ 14,5x20,5cm . Tại X í ngh iệp in 19-8 sơ' 3đuờiig
Nguyền Phong sắc- Nghĩa Târih- Cầu Giấy - Hà Nội.
Số giáy f tó p 1380, ngày 11 -1 0 - 2001
In xong và nộp lưu chiéu th án g 11 năm 2001


LỜI NĨI ĐẦU
Ngơn ngữ Assembler là ngồn ngữ bậc thấp, rất gần với ngơn ngữ
máy và tất nhiên râì gán với {Aần cứng của máy tính. Với đặc điểm như
vậy nên lập trình bằng ngơn ngữ Assem bler có những đặc thù riêng có


phán khác với ngơn ngữ bậc cao. Những ngưịi bưóc đẩu làm quen với
Assembler thường thấy lúng túng. Cuốn sách “ Cúc hài tập lập trình băng
n^ơn n^ữ Assem hỉer ” là nối tiếp cuốn sách Turbo Assemhler vá irng
dụn^ “ của chúng tôi nhằm giúp người lập trình làm quen với cách lập
trình bằng ngồn ngữ Assembler thông qua các bài tập cụ thể. Trong mỏi
bài tẠp, chúng tôi tiến hành theo ba bước : nêu yêu cẩu của bài tập; nói
(ịua ý tưởng giải (thuật tốn) và sau đó thể hiện chiromg trình (có kèm giải
thích). Để có thể dể dàng hiểu và giải được các bài tập trong cuốn sách
này đòi hòi người lập trình cắn nắm vồng:
• Phần lý thuyết vể lập trình bằng ngôn ngữ Assembler, các cơ chế liên
kết giữa ngôn ngữ bậc cao (C hoặc P a sc al) với ngơn ngữ Assembler.
• Cấu tróc m áy tính nói chung và máy vi tính nói riêng.
• Cơ chế ngắt và các ngắt hệ thống (các ngắt của BIOS và EX)S ).
Cuốn sách này được dành cho những người chuyên tin và tất cả
những ai có nhu cầu tìm hiểu, sử dụng ngôn ngữ Assembler, đặc biệt là
những người đi sâu vào các hệ thống gần với ỹhẳn cứng, những người hoạt
động trong các ĩĩnh vực đo lưồ^g, điều khiển và những nguời ứng dụng tin
híK: vào các q trình cơng nghê.
Các bài tập trong quyển sách này được sắp xếp theo hai phần :
Phán ì. Cái hài tập phần sơ họi
Nội dung chính của f^ần I là giải mội sơ' bài tập í^' học thường gặp.
Phdn //. Cáí hải ĩập lién quan đếrt hệ thống
Nơi dung chính của phần II là giải một số bài tập liẽn quan đến hệ thống
thông qua các ngắt cua BIOS và DOS.
Tác giả xin chân thành cảm ơn Viện Công nghệ Thông tin thuộc
Trung tâm Khoa học Tự nhiên và Công nghệ Ọuốc Gia đã tạo điểu kiện
cho việc nghiên cứu và hoàn thành cuốn sách này. Tác giả xin chân thành
cảm ơn: PGS,TS Nguyẻn Văn Tam, KS Ngô Trần Anh, TS Đặng Văn Đức,



TS Vũ Như Lân và TS Vũ Chấn Hưng đã đọc bản thảo, cổ vũ và đóng góp
nhiểu ý kiến để cuốn sách được ra mắt.
Hy vọng cuốn sách sẽ đáp ứng phần nằo nhu cầu của bạn đọc trong
học tập, nghiên cứu cũng như ứng dụng ngôn ngữ Asseiĩibler vào các cịng
việc của mình.
Mặc dù chúng tơi đã cố gắng sao cho cuốn sách được hoàn chỉnh,
song chắc chắn khịng tránh khỏi sai sót. Chúng tơi rất mong và xin chân
thành cảm ơn mọi ý kiến đóng góp của bạn đọc.

Hù Nội, tháng 9 năm 2001
TÁ C G IẢ


Phầnl

CÁC BÀI TẬP
PHẦN SỐ HỌC




CHƯƠNG 1

CHƯƠNG TRỈNH THUẦN t ủ y ASSEMBLER
TrưcK khi đi vào lập trình cụ thể cho các ví dụ, chúng ta hãy nhắc lại một
sô' phần cơ bản liên quan đến lập trình thuẩn túy Assembler.
1.1 CÁC BƯỚC TIẾN HÀNH MỘT CHƯƠNG TRÌNH ASSEMBLER
TRÊN MÁY TÍNH PC
Thường gồm bốn bước theo thứ tự sau:
1. Dùng một chương trình soạn thảo bất kỳ (ờ chế độ soạn thảo chưcmg

trình - programming mode) để soạn thảo chương trình vì bản thân
chương trình dịch Assembler (TASM-Turbo Assembler của Borland
cũng như MASM của M icrost) khơng có mơi trường soạn thảo như
TC hoặc TP. Cán phải hết sức lưu ý ià tệp của chương trình khi cât giữ
vào dĩa phải có đuởi .ASM. Ngơn ngữ Assembler thuần túy mậc định
không prfiân biệt chữ hoa và chữ thường,
2. Dịch chương trình Assembler, ví dụ như với chương trình dịch TASM
(Turbo Assembler) thì theo cú pháp sau :
TASM í/option] SOURCEfile [.ASM] (có đi ASM) (, OBJfile (có
đuối .OBJ)][, L s r n ie (có đi .LST)](. XRFfi!e (có đi .XRF)]
Chú ỷ: Khi dịch có sai vể cú pháp thì khơng tạo ra các tệp đi .OBJ,
.LST và -XRF. Cách báo của chương trình dịch khi dịch có l ỗ i :
**ERROR** lên_tệp.asm (số dịng lệnh có lỗi) : dang lỗi
Vi dụ :
**ER RO R **vd.asm (19): Undefined Symbol : slcs
(có nghĩa là : dịng 19 của tệp vd.asm bị sai và lồi đó có thế là
biến sỉcs chưa được xác lập- Ịchai báo)
3. Liên kết theo cú pháp sau :
TLINK l/option] OBJfile [,EXEfile (có đi .EXE)! [, M>file (có
đi -MAP))I. LlBHle (có đi .LIB)1
Chú ỷ : Nếu khi liên kếl có lỗi thì khơng tạo ra các tệp đuôi .EXE,
.M A P và.L lB


Chương 1. Chương trỉnh thuẩn túy Assem bler

7

4. Chạy rhử chương trình và nếu có sai thì sửa. Khi đã tạo được tệp .OBJ
và .EXE có nghĩa là vể cú pháp là đúng. Song khi chạy chươtig trình có

thể khơng cho kết quả như mong muốn. Điều đó có nghĩa là chương
trình có thế bị sai vể thuật tốn và chương trình dịch Turbo Assembler
sẽ khơng phát hiện ra điểu này. Loại sai này khó phát hiện hơn nhiều
so với loại sai vể cú pháp. Người lập trình có thể dùng các chức nảng
của Turbo DEBUG (TD) của Turbo Assem bler hoặc DEBUG của DOS
cùng với suy luận của thuật tốn cũng như kinh nghiệm của người lập
trình để tìm lỗi.
Một vài ( hú Vkhi soạn ĩhảo và dịch chương trình :
1. Mỗi lệnh Assem bler chiếm một dịng vói cú pháp tổng quát có dạng
như sau ;
ỉdbelỊ [directive/instruction) [operandsỊ [; comment
2. Mặc định thì ngơn ngữ Assembler khơng phân biệl chữ hoa và chữ
Ihưòmg. Tất cả các chCr đéu hiểu như chữ hoa. Muốn có sự [rfiân biệt
chữ hoa và chữ thường trong các nhãn thì phải sử dụng tùy chọn khi
dịch chương trình, đó là ;
TASM /ml ... cho íất cả mọi ký hiệu (symbol),
TASM /m x . , cho các nhân âxiợc khai báo PUBLIC, EXTRN
hoặc GLOBAL
-V Chương trình dịch TASM tìm các tệp INCLUDE như thế nào ?
• Nếu theo sau directìve (lệnh điẻu khiển khi dịch chương trình)
IN Q .U D E có chi rõ tên ổ dĩa, đường dẫn, tên tệp thì lất nhèn
chương trình dịch sẽ lìm theo sự xác định trên,
• Cịn nếu iheo sau directive INCLUDE chỉ xấc định có tên tệp thơi thì
chương Irình dịch sẽ tìm fệp đó ở thư mục hiện hành, nếu khơng thấy
ĩhì sẽ tìm tên tệp ờ ổ đĩa, thư mục được xác lập bời tùy chọn-/ khi
dịch chưcmg trình :
TASM -i tên_ổ_đĩa\tên_thư_mục chứồ tệp INCLUDE
1.2 CẨU TRÚC THƯỜNG THÂY CỦA MỘT CHƯƠNG TRÌNH THUẦN
TÚY ASSEMBLER
V ề tổng thể cấu trúc của một chương trình thuần túy Assembler thưỀBìg

c ó dạng sau :


8

CÁC BÀI TẬP LẬP TRÌNH BẰNG NGƠN NGỮ ASSEMBLER

[ Phần khai báo MACRO, STRUC, RECORD và UNION 1 (nếu có)
Chú ý phần này có thể đặt chỗ khác song phải trước khi được sử dụng
Phần khai báo segm ent
í
Khai báo segm ent dạng
đơn giản
.MODEL kiểu
.STACK độ lốn (tính theo byte)
.DATA
Khai báo biến

Khai báo segm ent dạng chuẩn
tên_stack_segnient segment
kiểu độ ỉớn dup(? hoặc một giá trị)
tên .stack .segm en t ends
tên .d ata.segm en t segment

.CODE

Khai báo biến
tên_data_segm ent ends

Nhãn :

mov AX,@DATA
mov DS,AX

tên .cod e.segm en t segment
assume tên_thanh_ghi segment:
tẽn^segment (cách nhau bởi dấu,)

thân chương trinh

lệnh trở về ỈX)S

Nhãn:
mov AX,DATA
mov DS,AX

thân chương trinh

{các chương trình con] (nếu có)
END Nhàn
lệnh trở vể DOS
|các chưdng trình con| (nếu có)
tên_code_segm ent ends
END Nh: .
C húý:
1. Chúng ta có thể dùng lệnh điểu khiển (directive) IN Q .U D E để chèn
một khối lệnh Assembler có trong một tệp (thường chứa các MACRO
hoảc các chương trình con) vào bất kỳ ncrt nào của chương trình mà ta
muốn.
2. Phẩn các chưcmg trình con có thể đặt ngay đầu phẩn code segment
(trưóc Nhãn của chưomg trình) thay vì sau phần chương trình chính.



Chương 1. Chương trinh thuẩn túy Assembler

Bài tậ p l . l
Hãy hiện một xâu ký tự ‘Hello TASM V ra màn hình.

Cách g iả i:
Có nhiéu cách giải bài tập này. ở đây chúng ta nêu ra hai cách:
Cách ỉ:
Dùng chức nâng hiện một xâu ký tự kết thúc bằng dấu $ ra màn hình.
Chức năng thứ 9 của hàm ngắt int 2 ìh của DOS cho phép chúng ta hiện
một xâu ký tự kết thúc bằng $ ra màn hình nếu DS:DX chứa địa chỉ
SEG:OFFSET của biến xâu. Do vậy chưcmg trình sc như sau (dùng khai
báo segment dạng đơn giản) :
MODEL small
.STACK lOOh
DATA
Message db ‘HdloTASM ! $’ ; Khai báo biến xâu ký tự
CODE
ProgramStart :
mov AX,@DATA
Đưa phần đia chỉ SEGMENT ảia phân
mov DS.AX
đoạn dữ liệu vào thanh ghi segment DS
mov DX,Oh hSET Message
DX chíồà phần đỊơ chỉ Ohl-SET biến xâu
mov AH,9
Chức năng thứ 9
int

21h
của hàm ngắt int 21h của EX)S
mov A H ,1'
Chítìc năng chờ một ký tự từ bàn phím
int
21h
mov AH,4Ch
Chức năng trở về DOS
int
21h
END ProgramStart
Cách 2 :
Xâu ký tự được kết thúc bằng giá trị 0 tuyệt đối (giống cấu trúc xâu của
ngỏn ngữ lập trình C),

Thuật to á n :
ỏ đày chúng ta đùng lệnh làm việc với xâu ký tự. Q ìúng ta lần lượt đưa
từng ký tự của xâu vào thanh ghi AL và so sánh liệu ký tự đó có ỊÀìãi là 0
tuyệt đôi (ký tự kết thúc xâu) hay chưa? Nếu ký tự đúng ỉà giá trị 0 tuyệt
đối thì kết thúc chương trình, cịn khơng thì hiện ký tự đó ra màn hình-


10

CÁC BÀI TẬP LẬP TRÌNH BẰNG NGƠN NGỮ ASSEMBLER

Chúng la dùng chức năng Oeh của hàm ngắ! inỉ ÌOh của BIOS để hiện
một ký tự nẳm trong thanh ghi AL (dạng A S Q l) ra m àn hình lại vị trí con
trỏ đang đứng.
Chương trình sẽ có dạng sau (dùng khai báo segmeni dạng chuẩn) :

_STACK segment stack ‘stack’
db lOOh dup(?)
_STACK ends
DATA segment
Message db ‘Hello TASM !’,0 ; Khai báo biến xâu ky tự
DATA ends
CODE segment
assume CS:CODE. DS DATA, SS:_STACK
ProgramStart;
Đưa phần địa chỉ SEGMENT củâ phân
mov AX,DATA
mov DS.AX
đoạn dữ liệu vào thanh ghi DS
mov SI,OFFSET Message
DS;Si trỏ đến ứiành phần đầu tiên củd xâu
cld
Cờ DF=0; lấy ký tự theo chiểu tăng địa chỉ
Ll:
E>ưa ký tự được trỏ bởi DS;SI vào AL
lodsb
Dựhg cờ ZF để kiểm tra liệu đã là 0 chưa
and AL.AL
Stop
Nếu là 0 tuyệt đối thì nhảy đến nhãn Stop
jz
mov AH,Oeh
Chứt năng Oeh của hàm ngắt in í JOh của
int
lOh
BIOS đxỉa một ký tự nằm ở AL ra màn hình

jmp LI
Stop ;
mov AH,1
Chíte năng chờ một ký tự từ bàn phím của
21h
hàm ngắt iní 21h của DOS
int
mov AH,4Ch
Vé DOS - kết thúc chưtíng trình
int
21h
CODE ends
END ProgramStart
Bài tập 1.2
Hiện nơi dung của thanh ghi AX ra màn hình dáng cơ sô' 2 (BINAR Y).
Gợi ỷ ;
Nên tạo MAC3ĨO cho việc hiện xâu ký tự dòng nhắc (sửa bài tập 1.1).


Chutm g 1. Chương trình thuẩn túy Assem bler

11

1. M ACRO hiện một xâu ký tự kết thúc bằng $ ra màn hình có dạng sau:
HienString MACRO xau
push AX DX
mov DX,OFFSET xau
mov AH,9
int
21h

pop DX AX

Bảo vệ nội dung hai thanh ghi vào ngăn xếp
Chức năng đưă xâu ký tự kết thúc bằng ký
tự $ ra màn hinh của hàm ngắt int 21 h
của DOS
Hồi phục nội dung hai thanh ghi

ENDM
2. M ACRO hiện ĩTiột xâu ký tự kết thúc bằng \0 tuyệt đối (giống cấu trúc
xâu trong ngôn ngữ C) ra màn hình sẽ như sau :
HienStringO MACRO xau
push AX SI
mov Sl.OhhSh I Message
cld
Ll:
Icxỉsb
and AL,AL
Stop
jz
mov AH,Oeh
int
lOh
jmp LI
Stop;
pop SI AX

; DS:SI trỏ đến thành phần đầu tiên ảia xâu
; Cờ DF»0;lấy ký tự theo chiểu tăng địa chỉ
, EXte ký tự đưụt trỏ bởi DS:(S!] vào AL

; Dựhg cờ Zero để kiểm tra liệu là 0 chxia ?
; Nếu là 0 tuyệt đối thi nhảy đến Stop
; Chức nấng Oeh của hàm ngắt iní lOh của
; BIOS đxia một ký tự ở AL ra màn hình

ENDM
Chúng ta có thể cất MACRO H ien^ring hoặc HìenStringO vào một tệp. ví
dụ là LIBl .ASM và dặt tại thư mục C:\1NCLUDE. Khi cần chèn khối lệnh
nằm trong tệp LIBl.ASM vào chỗ nào trong chương trình thì dùng lệnh
điều khiển khi dịch chuơng trình (directive) INCLƯDE-

Thuật to á n :
Thanfi ghi AX chứa 16 bit dạng cơ sổ nhị phân (BINARY). Phải tiến hành
hiên lần lượt giá trị từ bil cao đến bit thấp. Do vậy chúng ta tiến hành
quay trái 16 lần. Môi lần quay thì bit cao nhất sẽ được đưa vào bit cờ
G íiry (CF) và tiến hành hiên giá trị bir đó lên màn hình bằng cách đưa giá
trị bit cờ Carry (CF) vào thanh ghi AL nhị lệnh cộng có nhớ ADC và hiệu
chỉnh ra dạng A SQ I (cộng với ĨOh).


12

CÁC BÀI TẬP LẬP TRÌNH BẰNG NGƠN NGỮ ASSEMBLER

Ví dụ :
Nếu nội dung của thanh ghi AX=100 thì qua chương trình của chúng ta
sau dịng nhắc sẽ hiện số dạng BINARY là OOOXDOOl 100100.
Chưcmg trình có dạng sau :
ỈNCLUDE C:\INCLUDE\UB1.ASM ; chèn khối lệnh trong tệp UBl ASM
_STACK segment stack ‘stack’

db lOOh dup(?)
_STACK ends
DATA segment
MI db ‘Dang BINARY noi dung thanh ghi AX ỉa : $ ’
DATA ends
CODE scgment
assume CS:CODE, DS DATA, SS:„STACK
ProgramStart:
mov AX.DATA
mov DS,AX
Đưà số cần hiện (số thủ) vào thanh ghi AX
mov AX,100
Hiện dồr^ hướng dẫn ra màn hình
HicnString MI
caỉl HIẺS_BINARY
Gọi chưcíng trình con H1EN_BINARY
mov AH, 1
Chờ một ký tự từ bàn phím
int
21h
; Vể DOS • kết thúc chương trình chính
mov AH,4Ch
int
21h
Chương trình con hiện nội dung có trong
thanh ghi AX ra màn hình dạnh cơ số 2
Vào : AX chứồ số cần hiện
HIEN.BINARY PROC
push AXBX c x
mov BX,AX

mov CU16
HB;
xor AL,AL
shl
BX.1
ddc AL.30h

; Đưa nội dung số cần hiện từ AX vào BX
; Số lần Ịặp là 16 được đưa vào CL
AL«0
Đưa bit cao nhất vào cờ CF (Carry)
Cộng nội dung AL với nội dụng bit cờ CF,


Chương 1. Chuơng trình thuẩn túy Assem bler

mov AH,Oeh
int
lOh
loop HB
pop c x BX AX
ret
HIEN_BỈNARY ENDP
CODE ends
END ProgramStart

13

sau đó hiệu chỉnh ra dạng ASCII để hiện ra
màn hình

Lặp khối lệnh trên 16 ỉần

Bài tập u
Hãy viết chưcmg trình con hiện ra màn hình nội dung của thanh ghi AL ra
dạng cơ số 16 (H E X A ).

Thuật toán :
Thanh ghi AL sẽ chứa hai chữ số HEXA (cứ 4 bit thể hiện một chữ số
HEXA). Do vậy chúng ta tiến hành hiện chữ sơ' dạng HEXA thể hiện 4
bií cao của thanh ghi AL trước và sau đó mới hiện chữ số dạng HEXA thê
hiện 4 bit thấp. Chữ số HEXA sẽ từ 0 đến F (15), Trorig bảng mã ASCII
các ký tự 0 đến 9 được xếp liên tục nhau (mã A S Ơ l từ 30h đến 39h).
Song đến ký tự A (41 h) ihì phải nhảy cóc bảy giá trị so với ký tự 9 (39h).
Do vậy trước khi hiện một ký tự HEXA, phải kiểm tra xem liệu giá trị của
4 bíi có nhị hơn hay bằiìg 10 hoặc lón hơn 10. Nếu nhị hcm 10 thì cộng
với 30h đẻ biến thành giá trị ASCII cùa chữ số, cịn bằng hoậc iớn hơn 10
thì cơng với 37h để được mã A SQ I của các ký tự chữ sơ' dạng HEXA từ
A đến F.
Chương trình con sẽ như sau :
HIEN_HEX PROC
push AX c x
push AX
mov CL.4
shr
AL,CL
Câll
HỈENl
pop AX
and AL.OPh
c a li

HIENl
pop cx AX
ret
HiEN_HEX ENDP

; Cắt nội dung AX vào ngăn xếp (AL vào ngán xếp)
; Chuyển 4 bit cao của AL về vị trí 4 bit thấp
; Hiện ký tự HEXA thể hiện giá trị 4 bit cao
; Hồi phục nội duTìQ AX (AL) đã cất vào ngăn xếp
; Tách giá trị 4 bít thấp của AL
, Hiện ký tự HEXA thể hiện giá trị 4 bit thấp


14

CÁC BÀI TẬP LẬP TRÌNH BẰNG NGƠN NGỮ ASSEMBLER

HIENl
PROC
cmp AL,10
1 FSS 10
jb
ddd AL,7
1 FSS 10:
ãdd AL,30h
mov AH,Oeh
int
lOh
ret
HlENl ENDP


; Chương trình con hiện một ký tự HEXA M màn hinh
; So sánh với 10
; Nếu giá trị của 4 bit < 10 thì nhảy
; Cịn lớn hơn hoặc bằng 10 thì cộng AL với 7
; Hiệu chỉnh sang mã ASCII
; Chửt năng của BIOS hiện một ký tự dạng mã ASCII
; nằm ờ AL ra màn hỉnh tại vị tn' con trỏ đang đứng

Chú ý :
Muốn hiện nội dung thanh ghi AX (16 bit) ra dạng HEXA thì chúng ta
phải hiện hai số dạng HEXA ờ phần thanh ghi AH ra Irưóc, sau đó mới
hiện hai số dạng HEXA ờ phán ihaoh ghi AL. Do vậy có thế tiến hành
như sau ;
• Câì giá ĩrị AX vào ngàn xếp,
• Chuyển giá trị AH vào AL.
• Gọi chương trình con HIEN_HEX (hiện hai số HEXA của AH),
• Hồi phục giá trị AX từ ngán xếp,
• Gọi chưcmg trình con HIEN_HEX (hiện hai sỏ HEXA của AL).
Phần sau sẽ trình bày cách khác hiện nội dung thanh ghi AX ra dạng cơ
sô' 16 (xcm bài tập 1.5).
Bài tập Ỉ.4
Hãy viết chương trình con hiện nội dung cùa thanh ghi AX chứa giá trị
một sơ' ngun (trong giórt hạn từ -32768 đến +32767) ra màn hình dạng
cơ số 10.
Vấn để (láìi của sơ ngun :
Chúng ta biết rất nhiểu lệnh trong lập lênh Assembler có hố trợ vể dấu với
bit cao nhất của tốn hạng thể hiện dấu. Nếu là số âm thì máy tính (CPU
của Intel) sẽ chứa giá trị bù hai của sơ đó. Ví dụ, sơ -1 sẽ được thể hiện
bằng bù 2 của 1 (có nghĩa là FFFFh). Đo vậy để hiện một số nguyên nằm

trong một toán hạng (trong trưòng hợp của chúiig ta là thanh ghi AX),
trước tiên chúng ta phải kiểm tra liệu số đó lầ số âm hay dương bầng cách
xác lập bit cờ dấu SF. Nếu bii cờ dấu SF = 0 (số dương) thì hiện giá tri đó
ra màn hinh, ngược lại bit cờ dấu SF - 1 (số âm) thì tiến hành các bước'
sau trước khi hiện giá tn tuyệt đối của sô' hạng đó ra màn hình :


Chương 1. Chương trinh thuấn túy Assem bler

15

• Hiện dấu Irừ,
• Bù hai tốn hạng đó để được giá trị tuyệt đối của số nằm trong tốn
hạng đó.

Cách g i ả i :
Có nhiều cách giải bài lập này. Ờ đây chúng ta nêu lên ba cách.
Cách I :
Sau khi kiểm tra vé dấu và hiện dấu tương ứng (theo như các bưóc đã
trình bày trên), chúng ta tiến hành chia giá trị của thanh ghi AX cho 10.
Sò bị chia dạng 32 bit được đạt Irong DX:AX (trong trường hợp ở đây thì
DX ln bằng 0) và số chia là 10 được đặt trong một thanh ghi đa năng,
ví du BX. Kết quả của lệnh chia 32 bit cho 16 bii !à ; thanh ghi DX chứa
phần dư và AX chứa thương. Hiệu chỉnh phần dư ra dạng ASCII (cộng
thém giá trị 30h) và tạm cất vào ngản xếp. Thanh ghi c x sẽ chứa số lần
đă cất vào ngăn xếp (để sau này làm chỉ sơ' của vịng lặp lòi các giá trị đã
cấi trong ngăn xếp lẩn lượt hiện ra mằn hình). Sau mỏi lần chia, kiểm tra
Ịiệu ihươiig (nẳm ờ thanh ghi AX) đã bằng 0 hay chưa. Nếu thương chưa
bằng 0 thì quay lại tiếp tục lấy thương chia cho 10, ngược lại nếu thương
báng 0 thì đừng việc chia và thiết lập vịng lặp để lấy các giá trị đã cấi

trong ngăn xếp (dạng A S Q I) lần lượt hiện ra màn hình. Chương trình con
sẽ có dang như sau :
HỈEN_SO_N PRCX:
push AX BX c x
mov BX.10
xor
cx.cx
and AX.AX
ịns
HSNl
push AX
mov AL, mov AH.Och
int
lOh
pop AX
neg AX
HSNl
xor DX.DX
div
BX
add DX.30H
push DX

; SỐ hạng chia là 10 điícte đuồ vào BX
; cx«0 chứà số lần đxtồ vào ngăn xếp : ban đẳu ỉà0
. Dựhg cờ dấu (Sign-bit cao nhất cỉfâ toán hạng)
; Nếu ià số dương (bit cở
0) thi nhảy đến HSN1
; Cất giá trị số nằm ở AX tạm thời vào ngăn xếp
: Hiện dắu trừ ra màn hình


; Lấy lại giá trị số từ ngần xếp đưa vào thanh ghi AX
: Giá trị tuyệt đối của sô cần hiện - Bù 2
: D X -0
; Chia giá trị DX.AX (trong đó DX«0) cho 10 (BX)
; Hiệu chỉnh phần dư ra dạng A ^ I l
; Cất tạm vào ngốn xếp


16

CÁC BÀI TẬP LẬP TRÌNH BẰNG NGƠN NGỮ ASSEMBLER

inc
cx
Số lần cất vào ngăn xếp được táng ỉên 1
and AX.AX
Dựhg cờ ZF (xét liêu thưcfng có bằng 0 hay chitei?)
ịnz
HSNl
Nếu thương chưa bằng 0 thi tiếp tục chia
HSN2:
Vòng lặp hiện các ký tự đâ cất trong ngăn xếp
Lấy từ ngăn xếp ký tự dạng ASCII và đưa vào AX
pop AX
Hiện ký tự ra màn hình
mov AH.Och
lOh
int
loop HSN2

pop DX c x BX AX
ret
HIEN_SO_N ENDP
Cách 2 :
Phần kiểm tra dấu và hiện dấu giống như cách I .
Chúng ta biết rằng thanh ghi AX có khả nảng chứa một số lón nhất có
năm chữ số trừ phần dấu (từ -32768 đến +32767). Do vậy, sau khi kiểm
tra và hiện phẩn dấu như cách 1, chúng fa lần lượt kiểm tra xem số nằm
trong AX gấp bao nhiêu lần 10000, 1000, l o o / i o và 1 (thanh ghi DL
chứa số lần). Và sau khi thiết lập số lần cho từng trường hợp thì lần lượt
biến đổi sang dạng ASCII và hiện ra (dùng chức năng 2 của hàm int 21 h
của DOS). Dùng thanh ghi BX để làm con trò phần địa chỉ OFFSET của
bảng.
Chương trình sẽ như sau :
MODEL smalỉ
.DATA
Bànq dw
10000
dw
1000
dw
100
dw
10
dw
1
.CODE
HIEN_SO_N PROC
push AXBXCXDX
and AX,AX

jns
HSN1
push AX
mov AL.
mov AH,Oeh

; Dựhg cờ dấu (SF)
; Nếu ỉà số dương (bit Sign bằng 0) thi nhảy
; Cất giá tri số ở AX tạm thời vào ngăn xếp
; Hiện dấu trừ (-) ra màn hình


17

Chương 1. ChUdng trình thuẩn túy Assem bler

int

pop
ncg

lOh
AX
AX

Hồi phục giá trị từ ngăn xếp vào AX
Giá trị tuyệt đối của sô cần hiện - Bù 2

[\s m


xor DL.DL
mov c x ,5
mov BX,OFFSET Bang
HSN2:
cmp AX,WORD PTR IBXl
HSN3
jc
AX.WORD PTR IBX
sub
DL
inc
ìmp HSN2
HSN3:
piísh AX
add DL.30h
mov AH.2
21h
int
pop AX
xor DL.DL
inc
BX
inc
BX
loop HSN2
pop DX cx BX AX
ret
HỈEN_SO N ENDP

DL-0

Sô ỉượng chữ số cần in rd
Trỏ đến số đầu của Bang
So sánh giá trị nằm ở AX V(M Bang
Nhỏ hơn thi nhảy
Tãng sổ lần lén 1

Cất giá trị dư vào ngốn xếp
Chuyển về dạng ASCII
Hiện ra màn hình nhờ chức i-iâng thứ 2
củd ngắt in í 21 h của DOS
Lấy iại giá trị AX đã cất vào ngăn xếp
Dl = 0
Trỏ đến giá trị tiếp theo của Bang

Cách 3 :
Kiếm tra dấu và hiện dấu giỗng như hai cách trên. Sau đó đưa số nằm
trong AX sang cx và chuyển số nầm trong cx ra dạng sáu chữ sỏ' dạng
B(’D (Binary CcKỈe Decimal) Irong đó mỗi thanh ghi 1 byle chứa hai chữ
sô ; AL chứa hai chữ số ờ vị trí cao, DH chứa hai chữ số ờ vị trí giữa và
1)L chứa hai chữ sơ ihấp. Síiu đó lán lưcrì biến đổi và hiện ramàn hình
(chưofiig trình con HIEN2).
HiEN^SO_N PROC
push AXBXCXDX
and AX,AX
; Dựng cờ dẫu SF
ins
HSN1; Nếu là sỏ dưf:fíig (SF

#---- ---------- —


ĩ fj* ‘

^

■ ■ 'T GìA HA HOI
ir.TỈ}" tÍ ư VIIN


18

push
mov
mov
int
pop
neg
HSNl
mov
xor
mov
mov
HSN2:
shl
mov
adc
ddd
mov
mov
• ddc
daa

mov
mov
adc
mov
dec
jnz

CÁC BÀI TẬP LẬP TRÌNH BẰNG NGƠN NGỮ ASSEMBLER

AX
AL, •
AH.Oeh
lOh
AX
AX

Cất giá trị số nằm ở AX tạm thời vào ngăn xếp
Hiện dấu trừ ra màn hinh

CX.AX
DX.DX
BX.lOOOh
AL.BL

Chuyển sô cần hiện nằm ớ AX sang cx
D X ^
BH - 16 (số lần lặp tối đa có thể). BL = 0
AL = 0

c x .l

AL.DL
AL.AL

Qudy trái thì bit cao nhất được đưa vào bit cờ CF

DL.AL
AL,DH
AL.AL

Lấy ỉại giá trị số từ ngăn xếp đifâ vào AX
Bù 2 - Giá trị tuyệt đối củd số cần hiện

Hiệu chỉnh giá trị trong AL ra dạng BCD
DL chífâ mã BCD phần thấp nhất củd số cần hiện

DH.AL
DH chùò mã BCD phần giừd cửd số cần hiện
AL.BL
AL,AL
. AL. (tạm thời trong BL) chừứ mã BCD phần cao
BL.AL
. nhất của số cần hiện
BH
. Giảm chỉ số vòng ỉặp
HSN2
. Chưa bằng 0 thi tiếp tục vòng ỉặp
Câll
; Hiện hai chữ sô cao (dạng BCD) ở AL ra màn hinh
HIEN2
mov AL.DH

; Hiện hai chừ sơ giĩítì (dạng BCD) ớ DH ra màn hinh
cali HIEN2
mov AL,DL
; Hiện hai chừ sô thấp (dạng BCD) ớ DL ĩd màn hinh
Câll HIEN2
pop DX c x
AX
ret
HỈEN SO N ENDP

Chương trinh con biến đối và hiện một sỏ dạng BCD nằm
ở thanh ghi AL thành hai chữ số dạng cơ sỏ 10 ra màn hinh
Vào ; AL chừd sỗ rần hiện dạng BCD


Chương 1. Chương trinh thuẩn túy Assem bier

FiIEN2
push
push
mov
shr
acld
mọv
int
pop
and
ddd
mov
int

pop
ret

PROC
AX c x
AX
CL,4
AL,CL
AL.30H
AH,Oeh
lOh
AX
AL.OPh
AL.30H
AH,Oeh
lOh
c x AX

19

. Tạm thời cất giá trị của AL vào ngăn xếp
; Chuyển bốn bít cao của AL sang vị trí bốn bit tìiấp
; Hiệu chinh sang dạng ASCII
: Hiện ra màn hình
; i ấy lai giá tri cũ của AL từ r^ăn xếp
; Tách bốn bit thấp của AL
; Hiệu chỉnh sang dạng ASCII
; Hiện ra màn hình

H1EN2 ENDP

Bài tập ỉ . 5
Hày viết chương trình con hiện nội dung trong thanh ghi AX ra dạng
HEXA.
Cách g iả i:
CTiúng ta có thể hiện nội dung của thanh ghi AX ra dạng HEXA như bài
tập 1.3 đá đế cập. Sau đây sẽ thực hiên bằng cách khác dựa theo phưofng
pháp giống như cách ỉ cùa bài tập ! .4 với một số điổTỉ khác sau :
• Khơng có pháii kiểm tra và hiện dấu,
• Chia giá trị 32 bít nằm ở đòi thanh ghi DX:AX (với DX = 0) cho 16 (ớ
thanh ghi BX) thay vì chia cho 10,
• Trước khi hiệu chỉnh phần dư sau khi chia (ở thanh ghi DX) sang dạng
ASCII phải kiêm tra liệu giá Irị đó nhó hơĩì 10 hay băng hoặc lớn hơìì
10. Nếu nhị hơtì 10 (giá ĩrị sỏ' từ 0 đến 9) thì cộng ihêĩn 30h đẽ
chuyến sang dạng ASCII, cịn bàng hoặc lớn hơn 10 (giá trị số từ A
đén F) thì cộng với 37h đê chuyển sang dạng ASCII.
HỈEN HEXA PROC
push AXBXCXDX
mov BX,16
, Số chia lò được đưa vào BX
xor c x . c x
: c x = 0 chứei số lần đxM vào ngàn xêp:bdn đầu là 0
ỉiSN l


CÁC ĐÀI TẬP LẬP TRỈNH BẰNG NGÔN NGỮ ASSEMBLER

20

xor
div

cmp
jb
add
HSN2;
âdd
push
inc
and
jnz
HSN3:
pop
mov
int
loop
pop
ret

DX,DX
BX
DX,10
HSN2
DX,7

D X *0
Chia giá trị DX:AX (trong đó DX»0) cho 16
So sánh phần dư vcí 10
Nếu phần dư < 10 thì nhảy
Phần dư sẽ có thể từ A-F. Cộng vàì 1 trước

DX,30h

DX

Hiệu chỉnh ra dạng ASCII
Cất tạm vào ngăn xếp
Số lần cất vào ngẫn xếp được tãng lẽn 1
Thương đã là 0? Dựng cờ ZF
Nếu thương chưa bằng 0 thì tiếp tục chia
Vòng lặp hiện các ký tự đã cất trong ngán xếp
ỉ Ẩy từ ngân xếp ký tư dang ASCII và âơa vào AX
Hiện ký tự năm ở thanh ghi AL ra màn hình

cx
AXAX

HSNl
AX
AH.Oeh

lOh
HSN3
DX c x BX AX

HlEN_SO_N ENDP
Bài tập 1.6
Hãy viết chương trình nhận một số dạng BINARY (kết thúc việc vào sơ
bằng phím Enter- mã ũiỉh và sơ' lượng chữ số vào tối đa là 16) và hiện sỏ
đã vào đó ra màii hình dạng cơ số 10 và dạng cơ sơ' HEXA (giá thiết rằng
hai chựcmg trình con HIEN_SO_N và HIEN_HEXA nẳm trong tệp
C:\INCLUDE\LIB2.ASM).
Chú ý :

Nếu sô lượng chữ sơ nhị phân là 16 thì chú ý chữ sơ nhị phân vào đầu
tiên: nếu I thì sơ' hiện ra màn hình dạng cơ số 10 sẽ là sỏ' âm.
INCLUDE C:\INCLUDE\L1B1.ASM
MODEL small
STACK lOOh
DATA
MI db
Hay vao mot so dang BINARY; $'
M2 db
Oah.Odh. So vua vao chuycn sang dang co so 10 ia ; $
M3 db
Oah.Odh,'So vma vao chuyen sang dang HEXA la : $'


Chương 1. Chưdng trình thuán túy Assem bler

CODE
PS
mov AX.ODATA
mov DS.AX
HienString MI
xor
BX.BX
LI
mov AH.l
int
21h
cmp AL.Odh
ie
L2

shr
AL.l
rcl
BX,1
ịmp

LI

L2
HienString M2
mov AX.BX
HIEN_SO_N
call
HienString M3
HIEN_HEXA
call
mov AH.l
int
21h
mov AH,4Ch
21h
int
CLUDE C:\1NCLUC
END PS

21

Hiện xâu ký tự MI
BX chửcỉ các chữ số sẻ vào (lúc đầu=0)
Chờ một ký tự từ bàn phím

Ký tự vừở vào có phải Enter ?
Nếu ỉà Enter thi kết thúc việc vào số
Chuyển bit vừa vào vào bit cờ CF
Dịch các bit của BX sang trái 1 vị trí và
chuyển bit CF vào bit thấp nhất của BX
Quay về chờ vào một ký tự tiếp
Phần hiện các số vừồ vào ra màn hình

Hiện số vìfâ vào ra dạng cơ số 10
Hiện số vừa vào ra dạng HEXA
Chờ một ký tự từ bàn phím
{giống getcho của n/n c )
Về DOS
JB2.ASM

; Chứa các chương trình con
; HIEN_SO_N và HIEN.HEXA

Bài tậ p i.7
Vào m ột số nguyên (số từ -32768 đến 32767) từ bàn phím với qui định
kết thúc viêc vào sơ' bằng ấn phím Enter (mã ASCII là Odh).
Cách g i ã i :
Những vấn để vể dấu của một số nguyên chúng ta đã trình bày ở phần bài
lập 1.4.
Các bưóc sẽ tiến hành như sau :
• Dùng chức năng / của hàm ngắt tnỉ 2 Ih của DOS để nhận một ký tự
ASCII Cừ bàn phím vào thanh ghi AL. Kiểm tra liệu ký tự vừa nhận có
phải là Odh (Enter) - kết thúc viộc vào số hoậc dấu trừ (số âm) thì dựng
cờ dấu.



22

CÁC BÀI TẬP LẬP TRÌNH BẰNG NGỔN NGỮ ASSEMBLER

• Trừ giá trị dạng
đã nhận được ở thanh ghi AL cho 30h để được
dạng số.
• Nhân giá trị các số đã vào Irước với 10 trước khi cộng với số vừa vào.
Kết quả số nguyên đã vào sẽ nằm ở thanh ghi AX trước khi rời khói
chương trình con.
VAO_SO_N PROC
push BX c x DX SI
mov BX.IO
xor c x ,c x
mov Sl,cx
VSNl:
mov AH,1
int
21h
cmp AL.Odh
VSN3
ie
cmp AL,'jne
VSN2
inc
SI
jmp VSNl
VSN2:
xor AH,AH

sub AL.30h
xchg AX,CX
mu!
âdd
jmp
VSN3:
and
jz
neg
VSN4:
mov
pop
ret

BX
CX,AX
VSNl

Bảo vệ các thanh ghi
BX * 10 ìà một số hạng nhân
c x “ 0 - Chứa giá trị số đã vào (ìúc đầu bằng 0)
SI chứố cờ dấu (lúc đầu bằng 0 - dấu dươì ẳg)
Chờ nhận một ký tự từ bàn phim (dùng chức
năng 1 của hàm ngắt iní 21h của DOS )
Ký tự vừa nhận có phải ỉà Enter ?
Đúng thì nhảy (kết thúc việc vào một số)
Ký tự \ÁJa vào có phải là dấu ' hay khơng ?
Kh^-ig phải là dấu - thì nhảy đến VSN2
ngược lại SI -1 (biểu hiện số là âm)
Nhảy về tiếp tuc nhân các ký tư từ bàn phím

AH=0
Chuyển ký tự vìfâ nhận dạng ASCII thành số
Cất số vìfâ vào (AL) vào thanh ghi CL và đư
giá trị số đã vào tniớc (CX) vào ử\anh ghi AX
AX*10, có thể thay bằng C1 con N_AX_10
Cộng giá trị số vừa vào V(^ giá trị vào trước
{ sau khi đã được nhân 10) và đặt ở c x
Quay vể chờ một ký tự tiếp theo từ bàn phím

cx

Dựhg cờ để kiểm tra liệu vào số âm hay dưưiíg
Nếu là dấu dưưíig thì nhảy
NgiiỢc lại số âm thì bù 2 số vừa nhặn vào

AX,CX

AX chùa giá trị số vìfâ vào

S1,S!
VSN4

SI DX c x BX

VAO_SO_N ENDP


Chương 1. Chương trinh thuán túy Assem bler

23


Clìú V :
1. Chúng ta có thể nhân giá trị AX với lơ nhờ các lệnh dịch chuyến và
quay vòng của Assem bler (kết quả đạt ờ thanh ghi DX;AX).
N_AX_10 PROC
push BX
xor DX.DX
mov BX.AX
shl
AX.l
DXJ
rcl
shl
AX.l
DX.l
rcl
ddd AX.BX
adc DX.O
shl
AX.l
rcl
DX.l
pop BX
ret
N_AX_10 ENDP

: DX = 0
, nhân 2
; nhân 4
; nhân 5

. nhân 10

Tuy chương trình con N„A X_10 chứa nhiểu lệnh song việc thực hiện
sè nhanh hơĩì nhiều so với lệnh MUL vì các lộnh dịch chuyển và quay
vòng Irong Assembler thực hiện rất nhanh.
2. Chúng ta cũng có thê xác lập một MACRO thực hiện việc nhân giá trị
nằm trong thanh ghi AX với một giá trị nằm trong đốịfa( ìor với u
cầu sau :
• Nếu fcu tor có giá trị bằng 2 lũy thừa thì thực hiện phép nhân bầng
các lệnh địch chuyển và quay vịng,
• Nếu factoỉ có giá trị khỏng phải là 2 lũy thừa rhì thực hiện phép
nhân bẳng lệnh MUL.

Cách g i ả i :
Với một khối lệnh Assem bler cứ lảp đi lặp lại Irong chươiTg trình nguồn
ihì ngơn ngữ Assem bler có ba cách giúp người lập trình viết gọn chươtìg
trình, đó là : sử dụng chương trìah con, tạo lập íệp INCLUDE và xác lập
MACRO. Mỗi cách có nhữtìg thế mạnh của nó song nhìn chung MACRO
là mểm dẻo hơn cả. Sờ đĩ như vậy là vì MACRO có đối và đặc biệt cht)
phép sừ dụng các lệnh điều khiên lặp khi dịch chương trình (Repeat
blocks : REPT, I P R , . c á c lệnh điểu khiển điều kiện khi tiến hành dịch
chươiig trình (Conditional Assembly Direclives: IF/IFE, IFB/IFNB,


24

CÁC BẢI TẬP LẬP TRÌNH BẰNG NGƠN NGỮ ASSEMBLER

lỉ DL-,MFNDEF. IFIDN/IFDIF . ...) và các lệnh điều khiển khi dịch
LỈÌIUVÌ lĩUih kỉìác. Có thể nói MACRO là một cơ chế cho phép người lập

tĩình Assc^^^HỊ^^.tạo lập một lệnh mới trên cơ sờ lập lệnh Assembler.
Macro sau klii dtrợc xác lập (khai báo) thì tên cùa nó trở thành một lệnh
rnới và ĩigười lập trình có thế sử dụng bằng cách gọi tên chúng với tham
sỏ ihực ĩhay vi tham số hình thức (đối).
MACRO mà chung ta sẽ thiết lập sẽ nói lén phần nào nhữiig điều vừa
trình bày ờ Irên. Đây là một MACRO thực hiện việc nhân giá trị cua
ihanh ghi AX với một giá trị nguyên bất kỳ nằm trong đối /íU tor (AX
nhán với lơ là trườĩig hợp cụ thể khi tham sỏ' thực ứng vói đối fiU tor là
10). I^án đầu của MACRO là đoạn kiểm tra liệu giá trị c ủ a /í/í70/ có phải
là 2 lũy thừa hay khòng. Nếu factor là 2 lũy thừa thì biến cờ
IS_FACTOR_OF_TW O=l, ngược lại sẽ là 0 - xuấl phát gán bầng 0).
Vòng lãp đầu sẽ tiến hành so sánh liệu fơ( ĩor có băng mộl trong các giá
irị
Ì'-*,
2' (nằm ờ biên K)W ER_OF_TW O - lúc đầu là 2 " ) hay
khòng. Nếu bảng một giá trị nào đó thì thốt khịi vịng lập. Phán liếp
theo sẽ liến hành dịch đoạn chưofiìg trình thực hiên phép nhân theo giá trị
biến cờ IS_POWER_OF_TWO.
Cụ thê M ACRO sẽ như sau :
MULTIPLY MACRO íactor
IS_POWER_OF„TWO = 0
Count - 15

; Biến cờ cho biết factor có phải
; !à 2 luỹ ihừã (1-phải; 0-khơng phải)

POWER_OF_TWO = 8000h
; 2^^
REPT 16
; Vịng lặp kiểm tra liệu factor cỏ

IF POWER_OF_TWO EQ íactor ; phải là 2 luỹ thừa ? Nếu đúng tức
iS_POWER_OF_TWO = 1
; là factor =
và dựhg biến cờ
EXITM
: lS_POWER_OF_TWO=l và nhảy
ENDIF
; ra khỏi vịng lặp của REPT,
Count = Count - 1
; cịn khơng thì Couní giảm đi 1 và
POWER ,OF„l'WO«POWER_OF_ TWO SHR l
; POVVER _OF_TWO 2
ENDM
IF !S_POWER_OF_TWO
sub DX,DX
REPT Count

^ và tiếp tục vòng lặp 16 lần
, Kết thúc REPT
; IS.POWER_OF_TWO - 1, tửc là
. factor . nhân nhờ các lệnh dịch và quay

và thực


×