Tự Học Lập Trình Assembly

download Tự Học Lập Trình Assembly

of 74

Transcript of Tự Học Lập Trình Assembly

  • 8/19/2019 Tự Học Lập Trình Assembly

    1/74

    Tự học lập trình Assembly - Bài 1: Bước đầu với lập trình Assembly trên vi xử lý Intel8086/8088

    BƯỚC ĐẦU VỚI LẬP TRÌNH ASSEMBLY TRÊN VI XỬ LÝ 8088/8086 

    1. Giới thiệu về Hợp ngữ: Hợp ngữ (Assembly) là một ngôn ngữ lập trình cấp thấp, nó thực chất là dạng gợi nhớ(Mnemonic), hay dạng kí hiệu, của ngôn ngữ máy. 

     Như đã biết, lệnh ngôn ngữ máy là một dãy các con số 0, 1 nên rất khó đọc và khó lập trình, vìthế các nhà thiết kế vi xử lý đã đưa ra tập lệnh hợp ngữ gần với ngôn ngữ tự nhiên hơn nên dễđọc và dễ lập trình hơn. Tuy vậy, các lệnh hợp ngữ vẫn giao tiếp với phần cứng máy tính mộtcách rất chặt chẽ, nhờ đó việc tiếp cận với lập trình hợp ngữ giúp chúng ta hiểu rõ hơn về kiếntrúc và tổ chức hoạt động của máy tính. 

     Ngoài ra nó còn giúp chúng ta thấy rõ hơn mối quan hệ giữa các thành phần chức năng bên trong

    máy tính và hệ điề hành. Có thể nói ngược lại là, việc tìm hiểu và lập trình trên hợp ngữ giúpchúng ta hiểu rõ hơn về kiến trúc máy tính, tổ chức hoạt động bên trong máy tính và hệ điềuhành.

    Trong giới hạn của tài liệu này chúng ta chỉ tìm hiểu tập lệnh hợp ngữ của các vi xử lý họ Intel8088/8086, để  lập trình chạy trên các máy IBM-PC: Sử dụng họ vi xử lý này và hoạt động trongsự phối hợp với hệ điều hành MS_DOS. 

    Một trong những đặc điểm của hợp ngữ là chương trình viết trên nó có kích thước nhỏ hơn và tốcđộ nạp/thực hiện chương trình nhanh hơn so với viết (chương trình cùng chức năng) trên cácngôn ngữ lập trình bậc cao. 

     Ngoài ra, hầu hết các ngôn ngữ lập trình bậc cao hiện nay đều cho phép viết (“nhúng”) mã lệnhhợp ngữ trong nó. Điều này giúp người lập trình khai thác tối đa thế mạnh của các ngôn ngữ lậptrình, hợp ngữ rất mạnh trong các thao tác can thiệp sâu vào các thành phần bên trong hệ thống,trong khi đó ngôn ngữ bậc cao mạnh trong các thao tác xử lý dữ liệu và thiết kế giao diện. Nhưvậy sẽ là rất thuận lợi nếu sử dụng ngôn ngữ bậc cao để viết chương trình xử lý thông tin hệthống, khi đó nhiệm vụ truy xuất hệ thống (thanh ghi, bộ nhớ, cổng vào/ra, thiết bị,...) để lấy dữliệu sẽ được giao cho các đoạn mã lệnh hợp ngữ được nhúng trong chương trình này.  

    Hợp ngữ hỗ trợ 2 chế độ tương tác hệ thống: (1) Nhập trực tiếp từng lệnh/đoạn lệnh vào bộ nhớrồi cho phép thực hiện ngay trên bộ nhớ mà không cần qua bước biên dịch chương trình. Chương

    trình gỡ rối Debug (đi kèm hệ điều hành MS_DOS: Debug.exe) là một trong những chương trìnhhỗ trợ chế độ này cho hợp ngữ 16 bít; (2) Viết chương trình hợp ngữ, rồi sau đó sử dụng cácchương trình biên dịch để dịch nó sang chương trình thực thi (dạng EXE hoặc COM) và cho thựchiện chương trình này. 

    Hiện nay có hai loại trình biên dịch được sử dụng để biên dịch chương trình hợp ngữ (từ tập lệnhhợp ngữ của các vi xử lý họ Intel) sang chương trình thực thi: Trình biên dịch hợp ngữ 16 bít,MASM (Macro Assembler), được sử dụng để dịch thành các chương trình chạy trên nền hệ điều

    http://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tap-lenh-hop-ngu-cua-vi-xu-ly-8088-8086-bai-1.htmhttp://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tap-lenh-hop-ngu-cua-vi-xu-ly-8088-8086-bai-1.htmhttp://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tap-lenh-hop-ngu-cua-vi-xu-ly-8088-8086-bai-1.htmhttp://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tap-lenh-hop-ngu-cua-vi-xu-ly-8088-8086-bai-1.htmhttp://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tap-lenh-hop-ngu-cua-vi-xu-ly-8088-8086-bai-1.htmhttp://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tap-lenh-hop-ngu-cua-vi-xu-ly-8088-8086-bai-1.htm

  • 8/19/2019 Tự Học Lập Trình Assembly

    2/74

    hành 16 bít MS_DOS; Trình biên dịch hợp ngữ 32 bít, MASM32 (Macro Assembler 32 bít),được sử dụng để dịch thành các chương trình chạy trên nền hệ điều hành 32 bít MS_Windows.Trong thực tế, để chuyển một chương trình hợp ngữ sang dạng chương trình thực thi EXE 16 bíthoặc COM 16 bít thì cần phải có sự hỗ trợ của chương trình tiện ích của hệ điều hành MS_DOS:Link (Link.exe) và EXE2Bin (EXE2Bin.com).

    Chương trình hợp ngữ 16 bít sử dụng hệ thống các ngắt mềm (Interrupt) của BIOS và DOS nhưlà thư viện lập trình của nó, trong khi đó chương trình hợp ngữ 32 bít sử dụng tập hàm API làmthư viện lập trình của nó. 

    2. Biến –  Hằng trong chương trình hợp ngữ : 

    Biến và hằng 

    Biến và hằng (hằng có tên) trong chương trình hợp ngữ có tính chất, mục đích sử dụng, kiểu dữliệu, quy tắc đặt tên, quy tắc gán giá trị,... tương tự như biến và hằng trong các ngôn ngữ lập trình bậc cao khác. Biến trong chương trình hợp ngữ chỉ có các kiểu dữ liệu là: Byte, Word,

    Doubleword,... và hằng trong chương trình hợp ngữ có thể là số, kí tự hoặc một xâu kí tự.  

    Khi viết chương trình hợp ngữ chúng ta cần quan tâm đến địa chỉ của biến trong bộ nhớ. Một biến được khai báo trong chương trình sẽ được hệ thống gán cho một địa chỉ trong bộ nhớ (khichương trình được nạp vào bộ nhớ để hoạt động). Cụ thể: mỗi biến trong chương trình sẽ đượcđịnh vị tại một địa chỉ xác định trong bộ nhớ, và các biến được khai báo liên tiếp nhau trongchương trình (từ trên xuống dưới) sẽ được định vị tại các địa chỉ liên tiếp nhau trong bộ nhớ (từoffset thấp đến offset cao). Nhờ đó, nếu chương trình xác định được địa chỉ của một biến nào đóthì nó dễ dàng có được địa chỉ và nội dung của các biến khác trong chương trình.  

    Khác với biến, hằng trong chương trình hợp ngữ không được cấp phát bộ nhớ để lưu trữ, tức là,

    nơi nào trong chương trình chứa trên hằng thì sẽ được trình biên dịch thay bằng giá trị của nómột cách trực tiếp. 

    Hợp ngữ cung cấp các toán tử giả để định nghĩa/khai báo dữ liệu: DB (định nghĩa byte), DW(định nghĩa word), DD (định nghĩa doubleword),.... Và toán tử EQU để khai báo hằng. Biến cóthể được khai báo ở đầu hoặc ở  cuối chương trình. Trong khi đó, hằng có thể khai báo ở bất kỳnơi đâu trong chương trình, khi đó ta có thể sử dụng toán tử dấu “=” để gán giá trị cho hằng.  

    Khai báo biến –  hằng: 

    Cú pháp khai báo:

     

    a:    DB    b:    DW    c:    DD    d:    EQU   

    Trường hợp a được sử dụng để khai báo biến kiểu byte, trường hợp b được sử dụng đểkhai báo biến kiểu word, trường hợp c được sử dụng để khai báo biến kiểu doubleword, trường

  • 8/19/2019 Tự Học Lập Trình Assembly

    3/74

    hợp d được sử dụng để khai báo hằng. có thể một hoặc nhiều giá trị, nó có thể làmột số, một kí tự hoặc một xâu kí tự, và cũng có thể là một dấu hỏi chấm (“?”). cóthể là một số, một kí tự hay một xâu kí tự. 

    Ví dụ 1: 

      Spt DB 0 

      KiTu DB ‘a’   TieuDe DB ‘Tin hoc’   SoNguyen DW ? 

      DaySo DD 1020, 1345, 2389, 5763 

    Trong ví dụ trên, hai biến Spt và Kitu đều là biến kiểu byte, kích thước 1byte. BiếnTieuDe cũnglà biến kiểu byte nhưng gồm 7 byte ô nhớ liên tiếp (kích thước 7 byte), mỗi byte chứa 1 kí tựASCII. Biến SoNguyen là biến kiểu word, chưa được gán giá trị khởi tạo. Biến DaySo là biếnkiểu doubleword, gồm 4 phần tử có giá trị lần lượt (từ thấp đến cao) là: 1020, 1345, 2389, 5763.  

    Ví dụ 2: 

      LF EQU 0Ah 

      TB EQU ‘Cong nghe Thong tin’   TieuDe DB TB 

    Khai báo trên cho thấy, có thể khởi tạo giá trị ban đầu cho biến thông qua một hằng đã được địnhnghĩa trước. 

    Ví dụ 3:  TenKhoa DB ‘Cong nghe Thong tin’, 0Ah, 0Dh, ‘$’ 

    Khai báo biến TenKhoa cho thấy, có thể khai báo một biến mà trong đó bao gồm cả số, kí tự vàxâu kí tự, đây là biến kiểu byte, gồm 22 byte. 

    Ví dụ 4:  SoPT DW 2345h 

    Biến SoPT ở trên là một biến word, trong trường hợp này byte thấp của nó nhận giá trị 45h, bytecao nhận giá trị 23h, nhưng byte thấp định vị tại địa chỉ SoPT, byte cao định vị tại địa chỉ SoPT+ 1.

    Trong hợp ngữ, một dãy các byte hay word liên tiếp nhau trong bộ nhớ có thể xem là một mảng(mảng byte hay mảng word). Biến DaySo trong ví dụ 1 ở trên có thể được xem là một mảng

    word gồm 4 phần tử. Giá trị của các phần tử trong mảng có thể  được xác định thông qua tên biến và chỉ số tương ứng (địa chỉ). Cụ thể: DaySo[0] = 1020; DaySo[2] = 1345; DaySo[4] = 2389; DaySo[6] = 5763.

    Hợp ngữ cho phép sử dụng toán tử DUP để khai báo một biến dạng mảng mà trong đó gồmnhiều phần tử có cùng giá trị khởi tạo. Dạng sử dụng toán tử DUP là m Dup (n): gồm m phần tửcó cùng giá trị khởi tạo là n. 

  • 8/19/2019 Tự Học Lập Trình Assembly

    4/74

    Ví dụ 5:  MangSN DW 23, 45, 50 Dup (0), 12 

     Như vậy, biến MangSN được xem là một mảng word gồm 53 phần tử, hai phần tử đầu tiên nhậngiá trị lần lượt là 23 và 45, 50 phần tử tiếp theo nhận cùng giá trị 0 và phần tử cuối cùng nhận giátrị 12. 

    Trong ví dụ 1 ở trên: Các biến được khai báo ở đây sẽ được định vị tại các địa chỉ liên tiếp nhautrong bộ nhớ. Nếu biến Spt được định vị tại địa chỉ offset 100 trong đoạn nhớ dữ liệu thì các biếntiếp theo sẽ được định vị tại các offset sau đó. Cụ thể: Biến KiTu bắt đầu tại offset 101, biếnTieuDe bắt đầu tại offset 102, biến SoNguyen định vị tại offset 109, biến DaySo bắt đầu tạioffset 111 (xem hình sau):

    100 101 102 103 104 105 106 107 108 109 111 113 115 117

    0  a  T  i  n   _   H  o  c  1020  1345  2389  5763 

    (dòng trên là địa chỉ offset của biến, dòng dưới là các ô nhớ chứa giá trị của các phần tử trong biến) 

    Điều cần quan tâm ở đây là, có thể truy xuất đến giá trị của một phần tử trong biến này thông quatên của một biến khác. Ví dụ: Spt[0] = 0, TieuDe[0] = ‘T’, TieuDe[1] = ‘’i, DaySo[0] = 1020,DaySo[6] = 5763,... nhưng cũng có thể Spt[2] = KiTu[1] = ‘T’, KiTu[5] = ‘h’, DaySo[-5] = ‘h’, TieuDe[11] = 1345,...

    Tự học lập trình Assembly - Bài 2: Biên dịch chương trình Assembly chạy trên môi trường hệđiều hành 16bit 

    Thứ Năm, 29/08/2013 18:47 

    Bài viết này hướng dẫn sử dụng các chương trình biên dịch  16 bít: MicrosoftMacroAssembler và A86 MacroAssembler V4.05 để dịch các chương trình hợp ngữ (* .asm) sangchương trình thực thi (*.exe và *.com), chạy được trên nền hệ điều hành MS_DOS: 

    · Chương trình A86 Macro Assembly (tập tin chính là: A86.com) thường được sử dụng đểdịch chương trình hợp ngữ sang chương trình thực thi dạng COM. 

    · Chương trình Macro Assembly (tập tin chính là: MASM.exe) thường được sử dụng đểdịch chương trình hợp ngữ sang chương trình thực thi dạng EXE. Tuy nhiên, MASM chỉ có thểdịch tập tin chương trình hợp ngữ sang dạng tập tin đối tượng mã máy dạng Obj. Để chuyển tậptin Obj sang tập tin chương trình thực thi EXE ta phải sử dụng chương trình liên kết của

    MSDOS, đó là Link.exe. Để chuyển tập tin thực thi dạng EXE sang tập tin thực thi dạng COMta phải sử dụng thêm một chương trình khác của MS_DOS, đó là EXE2Bin.com. 

    Có thể sử dụng các tập tin TASM.Exe và TLINK.Exe để thay thế cho MASM.exe vàLink.exe. Các tập tin này, và cả tập tin EXE2Bin.com, có thể tìm thấy trong bộ chương trìnhTurbo Pascal.

    Chức năng của các tập tin biên dịch hợp ngữ liên quan: 

    http://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tu-hoc-lap-trinh-assembly-bai-2-bien-dich-chuong-trinh-assembly-chay-tren-moi-truong-he-dieu-hanh-16bit.htmhttp://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tu-hoc-lap-trinh-assembly-bai-2-bien-dich-chuong-trinh-assembly-chay-tren-moi-truong-he-dieu-hanh-16bit.htmhttp://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tu-hoc-lap-trinh-assembly-bai-2-bien-dich-chuong-trinh-assembly-chay-tren-moi-truong-he-dieu-hanh-16bit.htmhttp://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tu-hoc-lap-trinh-assembly-bai-2-bien-dich-chuong-trinh-assembly-chay-tren-moi-truong-he-dieu-hanh-16bit.htmhttp://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tu-hoc-lap-trinh-assembly-bai-2-bien-dich-chuong-trinh-assembly-chay-tren-moi-truong-he-dieu-hanh-16bit.htmhttp://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tu-hoc-lap-trinh-assembly-bai-2-bien-dich-chuong-trinh-assembly-chay-tren-moi-truong-he-dieu-hanh-16bit.htmhttp://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tu-hoc-lap-trinh-assembly-bai-2-bien-dich-chuong-trinh-assembly-chay-tren-moi-truong-he-dieu-hanh-16bit.htm

  • 8/19/2019 Tự Học Lập Trình Assembly

    5/74

      Tập tin MASM.exe/TASM.exe: Hỗ trợ dịch chương trình hợp ngữ nguồn sang tập tin mãmáy dạng Obj tương ứng.

      Tập tin Link.exe/TLink.exe: Hỗ trợ liên kết các tập tin mã máy, dạng tập tin đối tượng(*.Obj), thành tập tin thực thi dạng EXE. 

      Tập tin EXE2Bin.exe: Hỗ trợ chuyển các tập tin EXE, viết theo cấu trúc dạng COM, thành

    tập tin thực thi dạng COM. 

    MASM có thể dịch tập tin chương trình hợp ngữ sang các tập tin: tập tin đối tượng (*.Obj), tậptin liệt kê thông tin (*.Lst), tập tin tham khảo chéo (*.Crf). 

      Tập tin đối tượng (Object File): Chứa bảng dịch mã máy của các lệnh trong chương trìnhnguồn hợp ngữ, và các thông tin cần thiết để có thể tạo nên một tập tin thực thi. Đây là tập tinchính để tạo nên tập tin thực thi. 

      Tập tin liệt kê thông tin (List File): Là một tập tin văn bản cho biết địa chỉ offset của từnglệnh trong đoạn Code; mã lệnh của các lệnh trong chương trình; danh sách các tên/nhãn dùng

    trong chương trình; các thông báo lỗi và một số thông tin khác. Đây là tập tin cơ sở hỗ trợviệc gỡ rối chương trình.   Tập tin tham khảo chéo (Cross Reference File): Liệt kê các tên sử dụng trong chương trình

    và dòng mà chúng xuất hiện. 

    Hầu hết các chương trình biên dịch hợp ngữ 16 bít đều không hỗ trợ màn hình soạn thảochương trình. Nhưng, nó cho phép chúng ta sử dụng bất kỳ chương trình/màn hình soạn thảo nàođó, như Turbo Pascal, C,…, để viết chương trình. Chúng ta có thể sử dụng chương trình soạnthảo Notepad trên Windows (Windows XP) để viết và chỉnh sửa chương trình hợp ngữ, trongtrường hợp này ta nên đặt phần mở rộng cho tập tin chương trình là asm (*.asm).  

    Sử dụng A86 để dịch chương trình hợp ngữ sang chương trình dạng COM:  

    - Trước hết, các bạn nên viết chương trình hợp ngữ theo cấu trúc chương trình dạng COM vàlưu tập tin với phần tên mở rộng là asm. 

    Các bạn nên đặt tập tin chương trình hợp ngữ cần dịch ở cùng thư mục với tập tin dịcha86.com. Ở đây chúng tôi giả sử chúng được đặt ở E:\ASSEM.

    - Sử dụng A86 để biên dịch chương trình: 

    Cú pháp : A86 [đường dẫn]; 

    Ví dụ:  E:\>\ASSEM\A86 In_Ascii.asm

    Trên môi trường hệ điều hành Windows các bạn phải chuyển về cửa sổ MSDOS (Cmd)để thực hiện việc biên dịch này. 

  • 8/19/2019 Tự Học Lập Trình Assembly

    6/74

    -

     Nếu chương trình không có lỗi thì màn hình sẽ xuất hiện thông báo như sau: 

    Thông báo này cho biết việc biên dịch chương trình đã thành công. Tập tin chương trình hợp ngữIn_Ascii.asm đã được dịch thành tập tin chương trình In_Ascii.COM (chính xác hơn là hìnhthành thêm 2 tập tin mới In_Ascii.COM và In_Ascii.SYM).

    -  Nếu chương trình bị lỗi thì A86 sẽ xuất hiện thông báo lỗi như sau: 

    Thông báo này cho biết, trong quá trình biên dịch A86 đã phát hiện thấy lỗi trong chương trìnhIn_Ascii.asm, tức là, chưa thể dịch chương trình In_Ascii.asm sang chương trình thực thi. Cụthể: 

    - Thông báo “Error message inserted into In_Asscii.asm” cho biết thông báo lỗi đã đượcchèn vào ngay trong tập tin chương trình In_Asscii.asm.  

    - Thông báo “Original source renamed as In_Ascii.OLD” cho biết tập tin chương trình gốcđã được đổi tên thành In_Asscii.OLD. 

  • 8/19/2019 Tự Học Lập Trình Assembly

    7/74

    Trong trường hợp này chúng ta phải quay về chương trình Notepad để mở (Open) lại tập tinchương trình In_Ascii.asm và tiến hành tìm và chỉnh sửa lỗi. Tập tin In_Ascii.asm xuất hiện cácdòng thông báo lỗi như sau: 

    - Sau khi sửa lỗi và ghi lại chúng ta tiếp tục dịch lại chương trình như ban đầu. 

    Chúng ta có thể sử dụng kết hợp cả 3 tập tin Masm.exe, Link.exe và EXE2Bin.com để dịch mộtchương trình hợp ngữ viết theo dạng COM thành tập tin thực thi dạn g COM. 

    Sử dụng MASM để dịch chương trình hợp ngữ sang chương trình dạng EXE:  

    - Trước hết, các bạn nên viết chương trình hợp ngữ theo cấu trúc của chương trình dạng EXEvà lưu vào file với phần mở rộng là asm. 

    - Quá trình biên dịch chương trình gồm 2 bước: 

    Bước 1:  Dùng MASM hoặc TASM để dịch chương trình hợp ngữ sang tập tin đối tượngngôn ngữ máy. Cú pháp đơn giản như sau: 

    - MASM [đường dẫn]   ; 

    - TASM [đường dẫn]   ; 

    Ví dụ:  E:\>\ASSEM\Tasm In_Ascii.asm In_Ascii.obj

  • 8/19/2019 Tự Học Lập Trình Assembly

    8/74

     

     Nếu chương trình không có lỗi thì TASM sẽ xuất hiện thông báo như trên.

    Thông báo này cho biết quá trình biên dịch chương trình đã thành công.  Tập tin chương trìnhhợp ngữ In_Ascii.asm đã được dịch sang tập tin đối tượng ngôn ngữ máy In_Ascii.obj.  

     Nếu chương trình bị lỗi thì TASM sẽ xuất hiện thông báo lỗi, cùng với số thứ tự của dòngchương trình bị lỗi và nội dung lỗi trên màn hình, thông báo sau đây cho biết In_Ascii.asm bị lỗitại dòng 10 và 11: 

    Trong trường hợp này chúng ta phải quay về chương trình Notepad để mở (Open) lại tập tinchương trình In_Ascii.asm và tiến hành tìm và chỉnh sửa lỗi. 

    Chú ý: Để MASM/TASM tạo ra các tập tin LST và CRF trong khi biên dịch thì ta phảiviết ra tên của các tập tin này trong câu lệnh biên dịch.  

    Ví dụ: 

    E:\>\ASSEM\Tasm In_Ascii.asm, In_Ascii.obj, In_Ascii.lst, In_Ascii.crfVới câu lệnh dịch này Tasm sẽ đồng thời tạo ra cả 3 tậ p tin In_Ascii.obj, In_Ascii.lst,In_Ascii.crf, các tập tin này rất thiết cho việc kiểm tra lỗi và gỡ rối chương trình.  

    Bước 2: Dùng Link hoặc Tlink để liên kết một hoặc nhiều file đối tượng thành một file thực thiduy nhất. Cú pháp đơn giản: 

    LINK [đường dẫn]; 

  • 8/19/2019 Tự Học Lập Trình Assembly

    9/74

    TLINK [đường dẫn]; 

    Ví dụ:  E:\>\ASSEM\TLink In_Ascii.obj;

     Nếu việc liên kết không bị lỗi (đối với các chương trình đơn giản chỉ có một file đốitượng thì bước này thường không gây ra lỗi) thì màn hình sẽ xuất hiện thông báo: 

    Microsoft (R) Overlay Linker Version 3.64

    Copyright (c) Microsoft Corp 1981, 1988. All right reserved.

    Thông báo này cho biết việc liên kết các tập tin đối tượng chương trình đã thành công. Tập tinchương trình hợp ngữ In_Ascii.asm đã được dịch thành tập tin chương trình In_Ascii.exe.  

    Sau khi biên dịch chương trình hợp ngữ thành chương trình thực thi EXE hoặc COMchúng ta tiến hành cho chạy thử chương trình để kiểm tra, nếu kết quả không đúng như mongmuốn thì phải xem và thay đổi lại nội dung chương trình và sau đó thực hiện biên dịch trở lại từđầu. 

    Tự học lập trình Assembly - Bài 3: Cấu trúc của một chương trình Assembly 

    Hầu hết các hệ điều hành máy tính hiện nay, đặc biệt là các hệ điều hành của Microsoft,đều hỗ trợ hai dạng cấu trúc tập tin thực thi có thể hoạt động trên nó, đó là tập tin cấu trúc dạngCOM và tập tin cấu trúc dạng EXE. Có nhiều điểm khác nhau giữa hai cấu trúc chương trìnhnày, nhưng điểm khác biệt lớn nhất là: Các chương trình cấu trúc dạng EXE gồm 3 đoạn: Mãlệnh (Code), dữ liệu (Data) và Ngăn xếp (Stack). Khi hoạt động, 3 đoạn này sẽ được nạp vào 3đoạn (Segment) bộ nhớ tách biệt trên bộ nhớ; 

    Các chương trình dạng COM thì ngược lại, nó chỉ có 1 đoạn mã lệnh, trong đó chứa cảmã lệnh và ngăn xếp. Vì thế, khi được nạp vào bộ nhớ để hoạt động nó chỉ được cấp phát mộtđoạn bộ nhớ. Rõ ràng kích thước của một chương trình dạng COM không thể vượt quá giới hạncủa một đoạn bộ nhớ (với Intel 8088/80286 và MSDOS, 1 Segment bộ nhớ = 64KB). 

    Trong khi đó một chương trình dạng EXE có thể lớn hơn 3 Segment bộ nhớ. Do đó, khithiết kế các chương trình lớn, với chức năng phức tạp, trong đó có liên kết giữa các modunchương trình khác nhau thì ta phải thiết kế theo cấu trúc chương trình dạng EXE. 

    Hợp ngữ hỗ trợ thiết kế cả hai dạng cấu trúc chương trình EXE và COM, mỗi dạng phùhợp với một nhóm trình biên dịch nào đó. Muốn biên dịch một chương trình hợp ngữ sang dạngEXE thì ngoài việc nó phải được viết theo cấu trúc dạng EXE ta còn cần phải sử dụng một trình biên dịch phù hợp. Điều này cũng tương tự với việc muốn có một chương trình thực thi dạng

    COM.

    Văn bản của một chương trình hợp ngữ dạng EXE cũng cho thấy rõ nó gồm 3 đoạn:Code, Data và Stack. Tương tự, văn bản của chương trình hợp ngữ dạng COM cho thấy nó chỉ có1 đoạn: Code, cả Data và Stack (không tường minh) đều nằm ở đây.  

    Một chương trình hợp ngữ gồm hai thành phần chính: phần lệnh hợp ngữ và phần chỉdẫn biên dịch. Chỉ có các lệnh là được biên dịch thành ngôn ngữ máy. Phần hướng dẫn biên dịch

    http://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tu-hoc-lap-trinh-assembly-bai-3-cau-truc-cua-mot-chuong-trinh-assembly.htmhttp://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tu-hoc-lap-trinh-assembly-bai-3-cau-truc-cua-mot-chuong-trinh-assembly.htmhttp://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tu-hoc-lap-trinh-assembly-bai-3-cau-truc-cua-mot-chuong-trinh-assembly.htmhttp://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tu-hoc-lap-trinh-assembly-bai-3-cau-truc-cua-mot-chuong-trinh-assembly.htmhttp://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tu-hoc-lap-trinh-assembly-bai-3-cau-truc-cua-mot-chuong-trinh-assembly.htm

  • 8/19/2019 Tự Học Lập Trình Assembly

    10/74

    không được dịch sang ngôn ngữ máy, nó chỉ có tác dụng với các trình biên dịch. Thông thườngmỗi chương trình biên dịch có một nhóm hướng dẫn biên dịch phù hợp với nó, những với cáchướng dẫn biên dịch cơ bản và đơn giản thì nó phù hợp với hầu hết các trình biên dịch hợp ngữhiện nay. Trong tài liệu này chúng tôi sử dụng các hướng dẫn biên dịch phù hợp với trình biêndịch Microsoft Macro Assembler (MASM). 

    Cấu trúc chương trình được giới thiệu sau đây sử dụng các hướng dẫn biên dịch địnhnghĩa đoạn đơn giản (.Model, .Code, .Stack, .Data) phù hợp với MASM, TASM (Turbo MacroAssembler), A86. Việc sử dụng định nghĩa đoạn đơn giản sẽ làm cho văn bản chương trình sángsủa và dễ đọc hơn. Với các định nghĩa đoạn đơn giản ta cũng có thể xây dựng được các chươngtrình từ đơn giản đến phức tạp. 

    Cấu trúc chương trình dạng COM: 

    .Model   

    .Code 

    ORG  100h 

    JMP  

     

    PROC 

     

      Endp 

     

    End   

    Trong cấu trúc chương trình trên các từ khóa Model, Code, ORG, Proc, Endp, End là các hướngdẫn biên dịch. là nhãn của lệnh Jmp. 

    Cấu trúc này cho thấy rõ, một chương trình hợp ngữ dạng COM chỉ có 1 đoạn, đó chính là đoạn

    Code (đoạn mã lệnh), trong này bao gồm cả phần khai báo dữ liệu. Các khai báo dữ liệu trongchương trình dạng COM có thể đặt ở đầu hoặc ở cuối chương trình, nhưng với việc sử dụng địnhnghĩa đoạn đơn giản các khai báo dữ liệu phải đặt ở đầu chương trình.

    Chỉ dẫn ORG 100h  và lệnh JMP   sẽ được đề cập trở lại ở các phần sau đâycủa tài liệu này. 

    Cấu trúc chương trình dạng EXE: 

  • 8/19/2019 Tự Học Lập Trình Assembly

    11/74

    .Model  

    .Stack   100h 

    .Data 

     .Code 

      PROC 

     

      Endp 

     

    END 

    Trong cấu trúc chương trình trên các từ khóa Model, Code, Data, Stack, Proc, Endp, End là cáchướng dẫn biên dịch. 

    Cấu trúc này cho thấy rõ, một chương trình hợp ngữ dạng gồm 3 đoạn: đoạn Code, chứa toàn bộmã lệnh của chương trình. Đoạn Data, chứa phần khai báo dữ liệu của chương trình. Đoạn Stack,nơi chứa stack (ngăn xếp) của chương trình khi chương trình được nạp vào bộ nhớ để hoạt động.  

    Chỉ dẫn .Stack đặt ở đầu chương trình với mục đích khai báo kích thước của Stack dùng cho

    chương trình sau này. Kích thước thường được chọn là 100h (256) byte. Chỉ dẫn .Model được đặt ở đầu cả cấu trúc chương trình dạng COM và EXE với mục đích khai báo chế độ bộ nhớ mà chương trình sử dụng. 

    Ví dụ: Sau đây là hai chương trình hợp ngữ đơn giản, dạng COM và dạng EXE, cùng thực hiệnnhiệm vụ in ra màn hình 3 dòng văn bản như sau : 

    Nguyen Kim Le Tuan 

    Nguyen Le Tram Thanh 

    Nguyen Le Tram Uyen 

     Hai chương trình dưới đây chỉ có tác dụng minh họa cho việc sử dụng các hướng dẫn biên dịchđịnh nghĩa đoạn đơn giản và giúp các bạn thấy được những điểm giống nhau, khác nhau giữahai dạng cấu trúc chương trình dạng COM và EXE, vì vậy, ở đây các bạn chưa cần quan tâmđến ý nghĩa của các lệnh và các hàm/ngắt trong nó. Phần lệnh hợp ngữ và các hàm/ngắt sẽ đượctrình bày ngay sau đây. 

    Chương trình viết theo cấu trúc dạng COM: 

  • 8/19/2019 Tự Học Lập Trình Assembly

    12/74

    .Model  Small 

    .Code 

    ORG  100h 

    Start: Jmp Main 

    MyChildren  DB ‘Nguyen Kim Le Tuan’,0Ah,0Dh 

    DB ‘Nguyen Le Tram Thanh’,0Ah,0Dh 

    DB ‘Nguyen Le Tram Uyen’,’$’ 

    Main PROC 

    ;------- in ra mot xau voi ham 09/21h ------- 

    Mov Ah, 09h 

    Lea Dx, MyChildren 

    Int 21h 

    ;------- ket thuc chuong trinh ------- 

    Int 20h 

    Main Endp 

    End  Start 

    Chương trình này chọn chế độ bộ nhớ Small. Tên thủ tục chính là Main (tên thủ tục chính là tùyý). Nhãn chính của chương trình là Start (tên thủ tục chính là tùy ý), đó chính là nhãn của lệnhJmp. Phần khai báo dữ liệu chỉ khai báo một biến, đó là MyChildren. 

    Chương trình này gọi hàm 4Ch của ngắt 21h để kết thúc chương trình. Có thể gọi ngắt 20h để kếtthúc các chương trình dạng COM.

    Chương trình viết theo cấu trúc dạng EXE: 

    .Model  Small 

    .Stack   100h 

    .Data 

    MyChildren  DB ‘Nguyen Kim Le Tuan’,0Ah,0Dh 

    DB ‘Nguyen Le Tram Thanh’,0Ah,0Dh 

    DB ‘Nguyen Le Tram Uyen’,’$’ 

    .Code 

  • 8/19/2019 Tự Học Lập Trình Assembly

    13/74

    Main PROC 

    ;------- khởi tạo DS ------- 

    Mov Ax, @Data 

    Mov DS, Ax ;------- in ra mot xau voi ham 09/21h ------- 

    Mov Ah, 09h 

    Lea Dx, MyChildren 

    Int 21h 

    ;------- ket thuc chuong trinh ------- 

    Mov Ah, 4Ch 

    Int 21h 

    Main Endp 

    END  Main 

    Chương trình này chọn chế độ bộ nhớ Small. Khai báo kích thước Stack là 100h byte. Phần khai báo dữ liệu được đặt trong đoạn Data, ở đây chỉ khai báo một biến, đó là MyChildren. Tên thủtục chính là Main (tên thủ tục chính là tùy ý). 

    Thao tác đầu tiên của chương trình là trỏ thanh ghi đoạn DS về đầu đoạn Data, hay còn gọi làkhởi tạo thanh ghi đoạn DS: 

    Mov Ax, @Data 

    Mov DS, Ax 

    thao tác này được xem như là bắt buộc đối với cấu trúc chương trình dạng EXE sử dụng địnhnghĩa đoạn đơn giản. Các chương trình viết theo cấu trúc dạng EXE phải gọi hàm 4Ch của ngắt21h để kết thúc. 

    Có thể thấy, cấu trúc chương trình dạng COM và cấu trúc chương trình dạng EXE chỉ khác phầnhướng dẫn biên dịch, phần khai báo biến và phần lệnh thao tác chính hoàn toàn giống nhau. Haichương trình đơn giản ở trên hoàn toàn giống nhau ở biến là MyChildren và các lệnh gọi hàm

    09h của ngắt 21h để in ra màn hình một xâu kí tự (xâu này chính là giá trị khởi tạo của biếnMyChildren).

    Chú ý 1: Trình biên dịch hợp ngữ (Macro Assembler) cho phép các chương trình được dịch bởinóc họn sử dụng một trong các chế độ bộ nhớ sau:  

    - Small: Đoạn mã lệnh (Code) và đoạn dữ liệu (Data) của chương trình đều chỉ có thể chứa trongmột đoạn (segment) bộ nhớ. Tức là, kích thước của chương trình chỉ có thể tối đa là hai đoạn bộnhớ. Tuy vậy chế độ bộ nhớ này đủ dùng cho hầu hết các chương trình hợp ngữ.  

  • 8/19/2019 Tự Học Lập Trình Assembly

    14/74

    - Medium: Đoạn Code của chương trình có thể chiếm nhiều hơn một đoạn bộ nhớ. Trong khi đó,đoạn Data chỉ có thể chiếm 1 đoạn bộ nhớ. 

    - Compact: Đoạn Data của chương trình có thể chiếm nhiều hơn một đoạn bộ nhớ. Trong khiđó, đoạn Code chỉ có thể chiếm 1 đoạn bộ nhớ. 

    - Large: Đoạn Code và đoan Data của chương trình đều có thể chiếm nhiều hơn một đoạn bộnhớ. Nhưng trong trường hợp này không thể định nghĩa một mảng dữ liệu có kích thước lớn hơn64 Kbyte.

    - Huge: Tương tự như Large, nhưng trong trường hợp này có thể định nghĩa một mảng dữ liệucó kích thước lớn hơn 64 Kbyte. 

    Chế độ bộ nhớ Small là đơn giản nhất, được hầu hết các chương trình lựa chọn.  

    Chú ý 2: Với các chương trình hợp ngữ sử dụng định nghĩa đoạn đơn giản: Khi được nạp vào bộnhớ để hoạt động thì các thanh ghi đoạn sẽ tự động trỏ về các đoạn chương trình tương ứng. Cụthể: Thanh ghi đoạn CS chứa địa chỉ segment của đoạn bộ nhớ chứa đoạn Code của chươngtrình. Thanh ghi đoạn DS (và có thể cả ES) chứa địa chỉ segment của đoạn bộ nhớ chứa đoạnData của chương trình. Thanh ghi đoạn SS chứa địa chỉ segment của đoạn bộ nhớ chứa đoạnStack của chương trình.

    Tuy nhiên, trong thực tế, khi nạp chương trình EXE vào bộ nhớ DOS luôn dành ra 256 byte đầutiên của vùng nhớ, mà DOS cấp phát cho chương trình, để chứa PSP (Program Segment Prefix)của chương trình. PSP chứa các thông tin cần thiết mà trình biên dịch chuyển đến cho DOS để hỗtrợ DOS trong việc thực hiện chương trình này, đặc biệt, chương trình cũng có thể truy xuất vùngnhớ PSP. Do đó, DOS phải đưa địa chỉ segment của vùng nhớ chứa PSP vào cả DS và ES trướckhi chương trình được thực hiện. Tức là, ngay khi chương trình được nạp vào bộ nhớ DS không  

     phải chứa địa chỉ segment của đoạn Data của chương trình mà chứa địa chỉ segment của PSP. Vì vậy, để trỏ DS về lại đoạn Data chương trình chúng ta phải đặt ngay hai lệnh sau đây ở đầuchương trình viết theo cấu trúc EXE: 

    Mov Ax, @Data 

    Mov DS, Ax

    Với việc khởi tạo thanh ghi đoạn DS ở trên, địa chỉ segment của tất cả các biến khai báo trongđoạn Data đều được chứa trong thanh ghi DS, do đó, trong các thao tác xử lý biến sau nàychương trình không cần quan tâm đến địa chỉ segment của nó nữa.

    Chú ý 3: Hợp ngữ còn cho phép các chương trình sử dụng các hướng dẫn biên dịch định nghĩađoạn toàn phần, các định nghĩa này phù hợp với hầu hết các trình biên dịch hợp ngữ hiện nay.Định nghĩa đoạn toàn phần giúp cho việc viết chương trình hợp ngữ trở nên mềm dẻo và linhhoạt hơn, nó giúp người lập trình có thể điều khiển thứ tự các đoạn chương trình, kết hợp cácđoạn chương trình, liên kết các đoạn chương trình trong bộ nhớ,... , ngay trong khi lập trình.  

  • 8/19/2019 Tự Học Lập Trình Assembly

    15/74

    Chi tiết về cách sử dụng và mục đích sử dụng của các hướng dẫn biên dịch nói chung và cácđịnh nghĩa đoạn toàn phần nói riêng dễ dàng tìm thấy trong rất nhiều tài liệu về lập trình hợpngữ [1], [2]. Ở đây chúng tôi chỉ giới thiệu sơ lược về nó  thông qua ví dụ dưới đâ y.

    Ví dụ: Sau đây là một chương trình dạng EXE sử dụng các hướng dẫn biên dịch định nghĩa đoạn

    toàn phần (phù hợp với Macro Assembler): S_Seg Segment  Stack  

    DB 100h DUP (?) 

    S_Seg Ends 

    D_Seg Segmet 

    MyChildren  DB ‘Nguyen Kim Le Tuan’,0Ah,0Dh 

    DB ‘Nguyen Le Tram Thanh’,0Ah,0Dh 

    DB ‘Nguyen Le Tram Uyen’,’$’ 

    D_Seg Ends 

    C_Seg Segment 

    ASSUME CS:C_Seg, SS:S_Seg, DS:D_Seg

    Main PROC 

    ;------- khởi tạo DS ------- 

    Mov Ax, D_Seg 

    Mov DS, Ax 

    Mov Ah, 09h 

    Lea Dx, MyChildren  ; địa chỉ offset của biến MyChildren 

    Int 21h 

    Mov Ah, 4Ch 

    Int 21h 

    Main Endp 

    C_Seg Ends 

    END Main 

    Điều dễ nhận thấy đầu tiên là phần khai báo biến và phần lệnh chính trong chương trình nàyhoàn toàn giống như trong chương trình sử dụng định nghĩa đoạn đơn giản (hai chương trình vídụ ở  trên).

  • 8/19/2019 Tự Học Lập Trình Assembly

    16/74

    Chương trình này sử dụng hướng dẫn biên dịch định nghĩa đoạn toàn phần  Segment ... Ends đểđịnh nghĩa 3 đoạn chương trình với tên lần lượt là: S_Seg (đoạn stack), D_Seg (đoạn Data),C_Seg (đoạn Code). Tên của các đoạn được định nghĩa ở đây là tùy ý .

    Hướng dẫn biên dịch Assume được sử dụng để báo cho trình biên dịch biết  chương trình muốn

    chứa địa chỉ segment của các đoạn chương trình trong các thanh ghi đoạn nào (trỏ thanh ghi đoạnvề đoạn chương trình). Cụ thể ở đây là: Thanh ghi đoạn CS chứa địa chỉ segment của đoạn Code(CS:C_Seg). Thanh ghi đoạn SS chứa địa chỉ segment của đoạn Stack (SS:S_Seg). Thanh ghiđoạn DS chứa địa chỉ segment của đoạn Data (DS:C_Seg). Tuy nhiên, trong thực tế  AssumeDS:D_Seg không tự động nạp địa chỉ segment của D_Seg vào DS, do đó chương trình phải nạptrực tiếp bằng các lệnh: 

    Mov Ax, D_Seg 

    Mov DS, Ax 

     Nên nhớ, hướng dẫn biên dịch Segment ... Ends chỉ có tác dụng định nghĩa đoạn, nó  không thể

     báo cho trình biên dịch biết đoạn được định nghĩa thuộc loại đoạn chương trình nào (Code, Data,Stack, Extra). Chỉ có định nghĩa Segment Stack ... Ends là báo cho trình biên dịch biết đoạnđược định nghĩa là đoạn Stack, nhờ đó, khi chương trình được nạp vào bộ nhớ thanh ghi đoạn SSsẽ được trỏ về đoạn này.

    Tự học lập trình Assembly - Bài 4: Tập lệnh assembly của Intel 8086/8088 (1) 

    MỘT SỐ LỆNH ASSEMBLY CƠ SỞ  

    Cú pháp lệnh: 

    Một lệnh hợp ngữ đầy đủ gồm bốn thành phần sau đây: 

     [Nhãn lệnh:]     [Các toán hạng]   [;Lời giải thích]  

    Trong đó: 

    -  [Nhãn lệnh:] : Là một dãy các kí tự đứng trước câu lệnh (kết thúc bởi dấu hai chấm (:)), nóđược chỉ định thay thế cho địa chỉ của câu lệnh trong các đoạn lệnh lặp, rẽ nhánh,... Do đó, nóchỉ được sử dụng khi cần. 

    Trong một chương trình hợp ngữ không thể có hai nhãn lệnh trùng tên, tên của các nhãn cũngkhông thể trùng với tên của các thủ tục trong chương trình.  

    - : Là một trong các lệnh thuộc tập lệnh hợp ngữ (lệnh gợi nhớ: Mnemonic) của vi

    xử lý trên máy tính thực hiện lệnh này. 

    Lệnh hợp ngữ không phân biệt chữ hoa hay chữ thường. Trong chương trình hợp ngữ mỗi dòngchỉ có thể chứa một lệnh và mỗi lệnh phải được đặt trên một dòng. 

    - [Các toán hạng]: Là đối tượng mà lệnh tác động vào. Một lệnh hợp ngữ của Intel 8088/8086có thể không có toán hạng, có một toán hạng, hoặc có hai toán hạng. Nếu có hai toán hạng thì

    http://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tu-hoc-lap-trinh-assembly-bai-4-tap-lenh-assembly-cua-intel-8086-8088-1.htmhttp://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tu-hoc-lap-trinh-assembly-bai-4-tap-lenh-assembly-cua-intel-8086-8088-1.htmhttp://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tu-hoc-lap-trinh-assembly-bai-4-tap-lenh-assembly-cua-intel-8086-8088-1.htmhttp://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tu-hoc-lap-trinh-assembly-bai-4-tap-lenh-assembly-cua-intel-8086-8088-1.htmhttp://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tu-hoc-lap-trinh-assembly-bai-4-tap-lenh-assembly-cua-intel-8086-8088-1.htm

  • 8/19/2019 Tự Học Lập Trình Assembly

    17/74

    toán hạng đứng trước gọi là [Toán hạng đích], toán hạng đứng sau gọi là [Toán hạng nguồn].[Toán hạng đích] không thể là một hằng số. 

    Một số lệnh hợp ngữ của các Intel 80286/80386/... có thể có đến 3 toán hạng, trong trường hợpnày cũng chỉ có một [Toán hạng đích]. 

    -  [;Lời giải thích] : Chỉ có tác dụng với người viết và người đọc chương trình, nó không có ýnghĩa với trình biên dịch, tức là, không được dịch sang mã máy. Lời giải thích thường được sửdụng để làm rõ ý nghĩa của câu lệnh (khi người viết thấy cần). Lời giải thích phải nằm sau dấuchấm phảy (;).

    Ví dụ 1: Xét lệnh sau đây: 

     Lenh_VD:  Mov  AX,BX ; đặt giá trị thanh ghi BX vào thanh ghi AX  

    Trong đó: 

      Lenh_VD : Trong trường hợp này dãy kí tự Lenh_VD được sử dụng làm nhãn lệnh cho lệnhMov.

      Mov: Là tên lệnh. 

      AX và BX: Là các toán hạng (đích và nguồn). Trong trường hợp này toán hạng là các thanhghi đa năng 16 bít. 

      “đặt giá trị thanh ghi BX vào thanh ghi AX”:  Là lời giải thích cho lệnh này. Trong thực tếlời giải thích thường là tiếng Việt không dấu. 

    Ví dụ 2: Xem các lệnh sau đây: 

    -  NOP ; đây là lệnh không có toán hạng 

    - Mov Ax, Bl ; lệnh này có hai toán hạng, [Toán hạng đích] là thanh  

    ; ghi 16 bít, [Toán hạng nguồn] là thanh ghi 8 bít 

    - Add Cl, Spt  ; lệnh này có hai toán hạng, [Toán hạng đích] là thanh  

    ; ghi 8 bít, [Toán hạng nguồn] là một biến byte 

    - Mov Ax, [SI] ; lệnh này có hai toán hạng, [Toán hạng đích] là thanh  

    ; ghi 16 bít, [Toán hạng nguồn] là một ô nhớ  

    - Sub Dl, ‘a’ –  ‘A’ ; lệnh này có hai toán hạng, [Toán hạng đích] là thanh  

    ; ghi 8 bít, [Toán hạng nguồn] là một hằng số 

    - IMul Ax, Bx, 20 ; lệnh này có ba toán hạng, [Toán hạng đích] là thanh 

    ; ghi 16 bit (Ax), [Toán hạng nguồn] là thanh ghi 16 bít 

  • 8/19/2019 Tự Học Lập Trình Assembly

    18/74

      ; (Bx) và một hằng số (20) 

    Lệnh Imul ở trên là một lệnh nhân mới của vi xử lý Intel 80286. Lệnh này thực hiện như sau: lấynội dung/giá trị hai [Toán hạng nguồn] nhân với nhau, kết quả chứa ở [Toán hạng đích] (tronglệnh trên là: Bx*20, tích kết quả chứa ở thanh ghi Ax (chỉ lấy 16 bít thấp của tích để đưa vào

    Ax)).1. Lệnh Mov (Move): 

    Cú pháp lệnh:

    Mov [Toán hạng đích], [Toán hạng nguồn] 

    Trong đó: 

    - [Toán hạng đích]: Có thể là thanh ghi (8 bít hay 16 bít), ô nhớ (chính xác hơn là địa chỉ củamột ô nhớ) hay một biến nào đó. [Toán hạng đích] không thể là hằng số.

    - [Toán hạng nguồn]: Có thể là hằng số, biến, thanh ghi, ô nhớ (chính xác hơn là địa chỉ củamột ô nhớ) nào đó. 

    Tác dụng: Lấy nội dung (giá trị) của [Toán hạng nguồn] đặt vào [Toán hạng đích]. Nội dung của[Toán hạng nguồn] không bị thay đổi.  

    Ví dụ 1: 

    - Mov Ax, 5 ; Ax ß 5: đặt giá trị 5 vào thành ghi Ax 

    - Mov Ax, 5*2 ; Ax ß 5*2: đặt giá trị 10 vào thành ghi Ax 

    - Mov Bx, (80*(Dong - 1) + (Cot - 1))*2

    ; Dong, Cot là các biến 

    - Mov Dl, ‘A’ ; Dl = 41h: đặt mã ASCII của ‘A’ vào thanh ghi Dl 

    - Mov Cx, Var1  ; Cx = Var1: đặt giá trị của biến Var1 vào thanh ghi Cx 

    - Mov Ax, Bx ; Ax = Bx: đặt giá trị của thanh ghi Bx vào Ax 

    - Mov Ax, Dl ; Ax = Dl: đặt giá trị của Dl (8 bít) vào Ax (16 bít) 

    - Mov Bl, Dx ; Bl = Dx: không hợp lệ, vì: Dx (16 bít) mà Bl (8 bít) 

    - Mov Dl, 300 ; Dl = 300: không hợp lệ, vì 300 vượt giới hạn 1 byte 

    Ví dụ 2: Giả sử DI = 100; Ô nhớ tại địa chỉ offset 100 trong đoạn nhớ Data (được chỉ bởi DS)chứa kí tự B. Thì :

    - Mov Ax, DI ; (1) đặt giá trị thanh ghi DI vào thanh ghi Ax: Ax = 100 

    - Mov Ax, [DI] ; (2) Ax = . Tức là, đặt nội dung của 

  • 8/19/2019 Tự Học Lập Trình Assembly

    19/74

      ; ô nhớ được chỉ bởi DI vào thanh ghi Ax: Ax = 41h 

    Hãy phân biệt sự khác nhau giữa hai lệnh trên: Lệnh (1) sử dụng chế độ địa chỉ thanh ghi. Lệnh(2) sử dụng chế độ địa chỉ gián tiếp thanh ghi. 

     Nhớ lại rằng: Trong chế độ địa chỉ gián tiếp thanh ghi, các thanh ghi chỉ có thể là BX, DI, SI (địa

    chỉ đoạn chứa trong DS) hay BP (địa chỉ đoạn chứa trong SS). Như vậy lệnh (2) tương đươngvới lệnh (3) nhưng khác lệnh (4): 

    - Mov Ax, DS:[DI] ; (3)

    - Mov Ax, ES:[DI] ; (4) 

    Ví dụ 3: 

    - Mov Ax, [SI] ; đặt nội dung ô nhớ được chỉ bởi SI vào thanh ghi Ax 

    - Mov [DI], Bx ; đặt giá trị của thanh ghi bx vào ô nhớ được chỉ bởi DI 

    - Mov [DI], [SI] ; [DI] ß [SI] : lệnh không hợp lệ, vì: không thể chuyển  

    ; nội dung của ô nhớ vào một ô nhớ một cách trực tiếp 

    - Mov Var1, Ax ; Var1 ß Ax : đặt giá trị t/ghi Ax vào biến word Var1 

    Chú ý: 

    - Lệnh Mov không làm ảnh hưởng đến các cờ. 

    - Mov DS:[DI], ES:[SI] ; lệnh không hợp lệ, vì: không thể chuyển dữ liệu 

    ; trực tiếp giữa hai toán hạng bộ nhớ với nhau 

    - Mov DS, ES ; DS ß ES: lệnh không hợp lệ, 

    - Mov ES, 0100 ; lệnh không hợp lệ, vì:  không thể chuyển 

    ; trực tiếp một hằng số vào thanh ghi đoạn. 

    Để chuyển giá trị của hai thanh ghi đoạn hay nội dung của hai ô nhớ ta  có thể mượn một thanhghi đa năng làm trung gian: 

    - Mov Ax, ES ; hai lệnh này chuyển nội dung của thanh ghi đoạn ES  

    Mov DS, Ax ; vào thanh ghi đoạn DS thông qua thanh ghi Ax 

    Theo cách thông thường, để hoán đổi giá trị của hai thanh ghi đoạn hay nội dung của hai ô nhớngười ta thường sử dụng hai thanh ghi đa năng làm trung gian: 

    - Mov Ax, [DI] ; lưu tạm nội dung ô nhớ được chỉ bởi DI và Ax 

    Mov Bx, [SI] ; lưu tạm nội dung ô nhớ được chỉ bởi SI và Bx 

    Mov [DI], Bx ; chuyển giá trị của t/ghi Bx và ô nhớ được chỉ bởi DI 

  • 8/19/2019 Tự Học Lập Trình Assembly

    20/74

      Mov [SI], Ax ; chuyển giá trị của t/ghi Ax và ô nhớ được chỉ bởi SI 

    Bốn lệnh trên có tác dụng hoán đổi nội dung của hai ô nhớ trong đoạn Data (DS) được chỉ bởi DIvà SI (DI và SI chứa địa chỉ Offset của các ô nhớ).  

    - Không thể dùng thanh ghi đoạn CS làm [Toán hạng đích] trong lệnh Mov.  

    2. Các lệnh Inc –  Dec –  Add và Sub 

    Cú pháp lệnh: 

      Inc [Toán hạng đích] 

      Add [Toán hạng đích],[Toán hạng nguồn] 

      Dec [Toán hạng đích] 

     

    Sub [Toán hạng đích],[Toán hạng nguồn] 

    Trong đó: [Toán hạng đích], [Toán hạng nguồn]: tương tự lệnh Mov.  

    Tác dụng: 

      Lệnh Inc (Increment): làm tăng giá trị của [Toán hạng đích] lên 1 đơn vị. 

      Lệnh Dec (Decrement): làm giảm giá trị của [Toán hạng đích] xuống 1 đơn vị. 

      Lệnh Add (Addition): lấy giá trị/nội dung của [Toán hạng nguồn] cộng vào giá trị/nội dung

    của [Toán hạng đích], kết quả này đặt vào lại [Toán hạng đích].  

      Lệnh Sub (Subtract): lấy giá trị/nội dung của [Toán hạng đich] trừ đi giá trị/nội dung của[Toán hạng nguồn], kết quả này đặt vào lại [Toán hạng đích].  

    Ví dụ 1: 

    Mov Ax, 121 ; đặt giá trị 121 vào thanh ghi Ax 

    Mov Bx, 223 ; đặt giá trị 232 vào thanh ghi Bx 

    Inc Ax ; Ax = Ax + 1: tăng Ax lên 1 đơn vị (Ax = 122) 

    Dec Bx ; Bx = Bx + 1: giảm Bx xuống 1 đơn vị (Bx = 222) 

    Sub Ax, Bx ; Ax = Ax –  Bx : Ax = -100 

    Add Ax, 120 ; Ax = Ax + 120 : Ax = 20 

    Mov Cx, Ax ; Cx= Ax : Cx = 20 

    Dãy lệnh trên, đặt giá trị cuối cùng của thanh ghi Ax vào thanh ghi Cx (Cx = 20).  

  • 8/19/2019 Tự Học Lập Trình Assembly

    21/74

    Ví dụ 2: 

    - Inc Spt  ; Spt = Spt + 1; tăng giá trị biến Spt lên 1 đơn vị 

    - Inc DS:[SI] ; tăng ndung ô nhớ được chỉ bởi DS:SI lên 1 đơn vị 

    - Add Ax, Var1  ; Ax = Ax + Var1; cộng giá trị biến Var1 vào Ax - Add Var2, Dx ; Var2 = Var2 + Dx. Biến Var2 là biến dạng word 

    - Add Dx, [SI] ; cộng thêm nội dung ô nhớ được chỉ bởi SI vào Dx 

    - Add [DI], [SI] ; [DI] = [DI] + [SI] : lệnh không hợp lệ, vì: không thể  

    ; cộng trực tiếp nội dung hai ô nhớ với nhau. 

    ; Yêu cầu của lệnh trên có thể được viết lại như sau: 

    Mov Ax, [SI] ; lưu tạm nội dung ô nhớ được chỉ bởi SI và Ax 

    Mov Bx, [DI] ; lưu tạm nội dung ô nhớ được chỉ bởi DI và Bx 

    Add Bx, Ax ; cộng Ax và Bx, kết quả chứa ở Bx 

    Mov [DI], Bx ; đặt kết quả phép cộng vào lại ô nhớ được chỉ bởi DI 

    Ví dụ 3: Cộng thêm giá trị của thanh ghi Ax vào nội dung của ô nhớ tại địa chỉ offset 0100 trongđoạn DS: 

    Mov DI, 0100 ; trỏ DI về ô nhớ offset 0100 

    Mov Bx, DS:[DI] ; lưu tạm ndung ô nhớ DS:DI vào thanh ghi Bx 

    Add Bx, Ax ; cộng thêm Ax vào Bx Mov DS:[DI], Bx ; đặt kết quả vào lại ô nhớ DS:DI (DS:0100) 

    Trong trường hợp này ta có thể sử dụng lệnh Add DS:[DI],Ax. 

    Ví dụ 4: Giả sử tại ô nhớ  0B800:0100 trong bộ nhớ có chứa một word dữ liệu. Hãy tăng nộidung của ô nhớ này lên một đơn vị. 

    Mov Ax, 0B800h ; mượn thanh ghi Ax làm trung gian để chuyển 

    Mov ES, Ax ; địa chỉ đoạn của ô nhớ cần truy xuất vào ES 

    Mov DI, 01 ; đặt địa chỉ offset của ô nhớ cần truy xuất vào DI ;----------------------- ; (gọi ngắn gọn: trỏ ES:DI về ô nhớ cần truy xuất) 

    Mov Dx, ES:[DI] ; chuyển tạm nội dung ô nhớ cần tăng vào Dx 

    Inc Dx ; tăng giá trị thanh ghi Dx lên 1 đơn vị 

    Mov ES:[DI], Dx ; đặt giá trị Dx đã tăng vào lại ô nhớ cần tăng 

  • 8/19/2019 Tự Học Lập Trình Assembly

    22/74

    Ví dụ 5: Giả sử tại địa chỉ 0A00:0100 trong bộ nhớ có chứa một byte dữ liệu. Hãy chuyển nộidung của ô nhớ này vào thành ghi AL. 

    Mov Ax, 0A00h ; (1); Các lệnh (1), (2), (3) trỏ cặp thanh  

    Mov ES, Ax ; (2); ghi ES:DI về ô nhớ có địa chỉ 0A00:0100 

    Mov DI, 0100h ; (3); trong đó 0A00 là địa chỉ Segment và 

    ;------------------------- ; 0100 là địa chỉ Offset. Lệnh (4) chuyển nội  

    Mov Al, ES:[DI] ; (4); dung ô nhớ được chỉ bởi ES:DI vào Al. 

    Ví dụ 6: Giả sử tại địa chỉ 0100:0100 trong bộ nhớ có chứa 2 word dữ liệu liên tiếp (hai ô nhớliên tiếp). Hãy tính tổng nội dung hai word nhớ này, rồi lấy kết quả ghi vào ô nhớ tại địachỉ 0100:0120.

    Mov Ax, 0100

    Mov ES, Ax ; trỏ cặp thanh ghi ES:SI về đầu vùng nhớ  

    Mov SI, 0100 ; cần truy xuất. 

    Mov DI,0120 ; trỏ cặp thanh ghi ES:DI về ô nhớ chứa kết quả 

    ;------------------------- ; các ô nhớ này ở trong cùng một Segment 

    Mov Ax, ES:[SI] ; lưu tạm nội dung ô nhớ đầu tiên vào Ax 

    Add Ax, ES:[SI+2] ; cộng nội dung ô nhớ kế tiếp vào Ax 

    Mov ES:[DI], Ax ; ghi kết quả vào ô nhớ 0100:0120 

    Lệnh Add Ax, ES:[SI+2] ở trên sử dụng chế độ định địa chỉ bộ nhớ gián tiếp, cụ thể là địnhđịa chỉ chỉ mục (sử dụng thanh ghi chỉ mục SI). 

    Qua 3 ví dụ 4, 5, 6 ta có thể rút ra nguyên tắc cơ bản khi truy xuất dữ liệu/nội dung của một ônhớ là: Sử dụng một cặp thanh ghi thích hợp (DS:DI, DS:SI, ES:DI, ES:SI,...) để chứa địa chỉlogic (gồm cả Segment và Offset) của ô nhớ cần truy xuất. Thao tác này thường gọi là trỏ về ônhớ cần truy xuất. Sau đó sử dụng cặp thanh ghi này để ghi/đọc nội dung của ô nhớ đã được trỏtới. 

     Ngoài ra, khi truy xuất ô nhớ cần phải xác định dữ liệu/nội dung tại đó là một Byte hay mộtWord và nếu là truy xuất đọc thì kết quả sẽ được lưu vào đâu (thanh ghi hay ô nhớ).  

    Chú ý 1: 

      Không thể cộng trực tiếp hai thanh ghi đoạn. Trong trường hợp này phải sử dụng các thanhghi đa năng làm trung gian. 

      Lệnh Add thực hiện phép cộng không nhớ. Để thực hiện phép cộng có nhớ (cộng thêm giátrị của cờ nhớ (CF) hiện tại vào kết quả) phải sử dụng lệnh ADC (ADD with Carry) [2 -171]. Tương tự với lệnh Sub và SBB [2 - 180].

  • 8/19/2019 Tự Học Lập Trình Assembly

    23/74

      Để thực hiện phép cộng trên các số/giá trị BCD (Binary Coded Decimal) ta phải sử dụng cáclệnh cộng AAA (Ascii Adjust for Addition) và DAA (Decimal Adjust for Addition) để điềuchỉnh (adjust) kết quả cuối cùng [2 - 172]. Tương tự, với phép trừ trên các số BCD phải sửdụng lệnh AAS và DAS [2 - 183].

    Chú ý 2: 

      Các thanh ghi của vi xử lý Intel 8086/8088 đều là 16 bít, nên để chứa một đại lượng dữ liệu32 bít nó phải dùng 2 thanh ghi, thường là các thanh ghi đa năng (thanh ghi tích lũy): Ax, Bx,Cx, Dx. Cặp thanh ghi Dx:Ax thường được sử dụng nhất, khi đó Ax chứa 16 bít thấp, Dxchứa 16 bít cao của đại lượng 32 bít. 

      Để cộng/trừ trên các số 32 bít ta không thể sử dụng Add/Sub theo cách thông thường, mà phải thực hiện như sau: Cộng/Trừ 16 bít thấp, sau đó Cộng/Trừ 16 bít cao. Nếu phépCộng/Trừ trên 16 bít thấp xuất hiện bít nhớ/bít mượn thì phải tiến hành điều chỉnh kết quả,nếu không kết quả sẻ sai. Sử dụng các phép kiểm tra cờ để biết phép Cộng/Trừ có xuất hiện

     bít nhớ/bít mượn hay không [1 - 477].

    Tự học lập trình assembly - Bài 4: Tập lệnh assembly của Intel 8086/8088 (2) 

    3. Lệnh LOOP 

    Cú pháp: 

    Loop

    Trong đó:  là một nhãn lệnh và nó phải đứng trước lệnh lặp Loop không quá 126 byte.

    Tác dụng: Khi gặp lệnh này chương trình sẽ lặp lại việc thực hiện các lệnh sau đủn lần, với n được đặt trước trong thanh ghi CX. Sau mỗi lần lặp CX tự động giảm 1 đơn vị (Cx =Cx - 1) và lệnh lặp sẽ dừng khi Cx = 0. 

    Lệnh Loop thường được sử dụng để cài đặt các đoạn chương trình lặp với số lần lặp xác định,được cho trước trong thanh ghi Cx (tương tự các vòng lặp For trong các ngôn ngữ lập trình bậccao).

    Ví dụ 1: Xem đoạn lệnh sau đây: 

    Mov Ax, 6 

    Mov Cx, 4 ; lặp lại 4 lần 

    Lap: Add Ax, 10 ; cộng thêm 10 vào Ax 

    Loop Lap ; lặp lại việc cộng 10 vào Ax đủ 4 lần 

    Kết thúc đoạn lệnh trên: Ax = 46 (cụ thể: Lần 1: Ax = 6 + 10; Lần 2: Ax = 16 + 10; Lần 3: Ax= 26 + 10; Lần 4: Ax = 36 + 10 = 46).

    http://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tu-hoc-lap-trinh-assembly-bai-4-tap-lenh-assembly-cua-intel-8086-8088-2.htmhttp://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tu-hoc-lap-trinh-assembly-bai-4-tap-lenh-assembly-cua-intel-8086-8088-2.htmhttp://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tu-hoc-lap-trinh-assembly-bai-4-tap-lenh-assembly-cua-intel-8086-8088-2.htmhttp://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tu-hoc-lap-trinh-assembly-bai-4-tap-lenh-assembly-cua-intel-8086-8088-2.htmhttp://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tu-hoc-lap-trinh-assembly-bai-4-tap-lenh-assembly-cua-intel-8086-8088-2.htm

  • 8/19/2019 Tự Học Lập Trình Assembly

    24/74

    Ví dụ 2: Xem đoạn lệnh sau đây: 

    Mov Ax, 6

    Mov Bx, 3

    Mov Cx, 4 ; lặp lại 4 lần Lap_TT: 

    Add Ax, Bx ; cộng thêm giá trị thanh ghi Bx vào thanh ghi Ax 

    Inc Bx ; tăng Bx lên 1 đơn vị 

    Loop Lap_TT ; lặp lại các lệnh sau nhãn lệnh Lap_TT đủ 4 lần 

    ;----------------------------- ; sau lệnh lặp này Ax = 24, Bx = 7 

    Mov Dx, Ax ; Dx ß Ax 

    Mov Cx, Bx ; Cx = 7, sau Loop Cx = 0, được thay bằng Bx = 7 

    Kết thúc đoạn lệnh trên: Ax = 24 (Lần 1: Ax = 6 + 3;Lần 2: Ax = 9 + 4; Lần 3: Ax = 13 +5; Lần 4: Ax = 18 + 6) và Dx = Ax = 24.

    Khi gặp lệnh Loop Lap_TT chương trình sẽ quay lại (nếu Cx 0) thực hiệnlệnhAdd Ax, Bx (Lap_TT là nhãn của lệnh này), tất nhiên khi đó nó cũng phải thực hiện lạilệnh Inc Bx. Dó đó, có thể nói lệnh Loop này thực hiện vòng lặp cho cả hai lệnh Add và Inc.Đó cũng chính là lý do mà người ta thường viết nhãn của các lệnh phải được lặp theo kiểu nhưtrên (nhãn lệnh và lệnh không cùng trên một dòng).  

    Ví dụ 3: Xem đoạn lệnh sau đây: 

    Mov Dx, 6

    Mov Cx, 5 ; lặp lại 5 lần 

    TT: 

    Add Dx, Cx ; cộng thêm giá trị thanh ghi Cx vào thanh ghi Dx 

    Loop TT ; lặp lại các lệnh sau nhãn lệnh TT đủ 5 lần 

    ;-----------------------------;  

    Mov Bx, CxKết thúc đoạn lệnh trên Bx = Cx = 0 (khi Cx = 0 thì vòng lặpLoop TT kết thúc) và Dx = 21(Lần 1: Dx = Dx + Cx = 6 + 5;Lần 2: Dx = Dx + Cx = 11 + 4; Lần 3: Dx = Dx + Cx = 15 +3; Lần 4: Dx = Dx + Cx = 18 + 2;Lần 5: Dx = Dx + Cx = 20 + 1 = 21).

    Ví dụ 4: Các lệnh sau đây thực hiện phép gán: 

    Ax = 2 + 4 + ...+ 100 

  • 8/19/2019 Tự Học Lập Trình Assembly

    25/74

      Mov Ax, 0 

    Mov Bx, 2 

    Mov Cx, 50 

    Lap_TT: Add Ax, Bx 

    Add Bx, 2 

    Loop Lap_TT 

    Ví dụ 5: Giả sử tại địa chỉ offset 100 trong đoạn nhớ Data (được chỉ bởi thanh ghi đọan DS) cóchứa một mảng dữ liệu, gồm 100 ô nhớ, mỗi ô là một byte. Hãy cộng thêm 50 đơn vị vào tất cảcác ô nhớ trong mảng này. 

    Mov DI, 0100 ; trỏ cặp thanh ghi DS:DI về 

    ; vùng nhớ cần truy xuất (DS:0100) 

    ;------------------------

    Mov Cx, 100 ; lặp 100 lần vì mảng gồm 100 ô nhớ  

    Lap_TangThem: 

    Mov Dl, DS:[DI] ; lấy nôi dung ô nhớ chỉ bởi DS:DI lưu vào DL 

    Add Dl, 50 ; cộng thêm 50 vào Dl 

    Mov DS:[DI], Dl ; đặt giá trị đã tăng thêm vào lại ô nhớ DS:DI 

    Inc DI ; chỉ đến ô nhớ kế tiếp (vì ô nhớ byte nên tăng 1) 

    Loop  Lap_TangThem ; lặp lại đủ 100 lần (duyệt qua đủ 100 ô nhớ) 

    Trong trường hợp này ta có thể sử dụng lệnh Add DS:[DI], 50 để tăng trực tiếp nội dung củaô nhớ, hợp ngữ cho phép điều này. Nhưng cách đã viết thường được áp dụng hơn, vì tính tổngquát của nó. Nói chung, chúng ta nên hạn chế tác động trực tiếp lên nôi dung của ô nhớ.  

    Ví dụ 6: Giả sử tại địa chỉ 0100:0C00 trong bộ nhớ có chứa một xâu kí tự gồm 50 kí tự (tức là,gồm 50 ô nhớ, mỗi ô 1 byte). Hãy copy xâu kí tự này sang vùng nhớ bắt đầu tại địa chỉ0200:0100.

    Mov Ax, 0100

    Mov DS, Ax ; trỏ cặp thanh ghi DS:SI về 

    Mov SI, 0C00 ; đầu vùng nhớ chưa xâu cần copy (0100:0C00) 

    Mov Ax, 0200

    Mov ES, Ax ; trỏ cặp thanh ghi ES:DI về 

  • 8/19/2019 Tự Học Lập Trình Assembly

    26/74

      Mov DI, 0100 ; vùng nhớ chứa xâu kết quả copy 0200:0100 

    ;------------------------

    Mov Cx, 50 ; lặp 50 lần vì xâu gồm 50 kí tự 

    Lap_Copy: Mov Bl, DS:[SI] ; mượn Bl để chuyển tường kí tự từ ô nhớ được 

    Mov ES:[DI], Bl ; chỉ bởi DS:SI sang ô nhớ được chỉ bởi ES:DI 

    Inc SI ; chuyển đến kí tự tiếp theo 

    Inc DI

    Loop  Lap_Copy ; lặp lại đủ 50 lần (để copy đủ 50 kí tự) 

    Trong ví dụ này, vùng nhớ chứa xâu kí tự cần copy (vùng nhớ nguồn) và vùng nhớ chứa kết quảcopy (vùng nhớ đích) nằm ở hai đoạn (segment) nhớ khác nhau, do đó, ta phải sử dụng hai thanhghi đoạn dữ liệu khác nhau: DS và ES. 

    Qua 2 ví dụ 5 và 6 ta có thể rút ra nguyên tắc cơ bản để truy xuất dữ liệu trên một vùngnhớ/mảng nhớ: 

    Chú ý: Lệnh Loop thực hiện vòng lặp cho đến khi Cx = 0, vì thế nó được xem như lệnh lặpkhông điều kiện. Thực tế, hợp ngữ còn có các lệnh lặp có điều kiện, nó cho phép kết thúc vònglặp trước khi Cx = 0 dựa vào một điều kiện nào đó. Cụ thể: lệnh LoopE (Loop while Equal): Chỉlặp lại khi Cx 0 và cờ ZF = 1; lệnh LoopZ (Loop while Zero): tương tự LoopE; LoopNE(Loop while Not Equal): Chỉ lặp lại khi Cx 0 và cờ ZF = 0;... [2 - 154].

    4. Lệnh LEA (LoadEffectiveAddress) Cú pháp: 

    LEA  [Toán hạng đích],[Toán hạng nguồn] 

    Trong đó: [Toán hạng đích]: Là các thanh ghi 16 bít. [Toán hạng nguồn]: Là địa chỉ của mộtvùng nhớ hay tên của một biến. 

    Tác dụng: Lệnh LEA có tác dụng chuyển địa chỉ offset của [Toán hạng nguồn] vào [Toán hạngđích]. Lệnh này thường được sử dụng để lấy địa chỉ offset của một biến đã được khai báo trongchương trình. Thanh ghi được sử dụng trong trường hợp này là thanh ghi cơ sở (BX) và thanh

    ghi chỉ mục (SI và DI).Ví dụ 1: 

    Lea  Bx, DS:[0100]  ; chuyển thành phần địa chỉ offset (0100) vào Bx  

    Lea DI, XauKT  ; chuyển địa chỉ offset của biến XauKT vào DI 

    ; thao tác này thường được gọi là trỏ DI và đầu 

  • 8/19/2019 Tự Học Lập Trình Assembly

    27/74

      ; biến XauKT 

    Khi chương trình được nạp vào bộ nhớ để hoạt động thì các biến được khai báo trong chươngtrình sẽ được định vị (cấp phát vùng nhớ) tại một địa chỉ xác định trong vùng nhớ Data. Từ đây,để thao tác đến dữ liệu trên các biến của chương trình thì chương trình phải xác định được địa

    chỉ segment vào offset (hai thành phần của địa chỉ logic) của biến. Lệnh LEA ở trên chỉ lấy đượcđịa chỉ offset của biến, để lấy được địa chỉ segment của nó ta có thể sử dụng lệnh Mov với toántử Seg (tương tự có thể sử dụng lệnh Mov với toán tử Offset để lấy địa chỉ offset của biến). Vídụ: Các lệnh sau lấy địa chỉ Segment:Offset của biến XauKT (hay trỏ DS:SI về đầu biếnXauKT):

    Mov Ax, Seg XauKT  ; đưa địa chỉ Segment của biến XauKT 

    Mov  DS, Ax  ; vào thanh ghi DS 

    Mov SI, Offset XauKT  ; đưa địa chỉ Offset của biến XauKT vào SI 

    Ví dụ 2: Giả sử biến TenGom (là biến kiểu byte) đã được khai báo như sau: 

    TenGom  DB  ‘Nguyen Kim Le Tuan’ 

    Xem các lệnh sau đây (1): 

    Mov Bx, 0 

    Mov Al, TenGom[Bx] ; Al =‘N’ 

    Add Bx, 7 ; 

    Mov Bl, TenGom[Bx] ; Bl =‘K’ 

    Xem các lệnh sau đây (2): Lea DI, TenGom 

    Mov Al, [DI] ; Al =‘N’ 

    Mov Bl, [DI + 7] ; Bl =‘K’ 

    Ta có thể thấy, nhóm các lệnh (1) và nhóm các lệnh (2) là tương đương nhau về tác dụng của nó,nhưng (1): sử dụng trực tiếp tên biến để truy xuất đến các phần tử của nó; (2): sử dụng thanh ghichỉ mục DI để truy xuất đến các phần tử của biến. Trong trường hợp này địa chỉ segment mặcđịnh được chỉ bởi DS, điều này phù hợp với việc sử dụng địa chỉ gián tiếp thanh ghi chỉ

    mục.Ví dụ 3: Giả sử tại địa chỉ 0100:0C00 trong bộ nhớ có chứa một xâu kí tự gồm 50 kí tự (tức là,gồm 50 ô nhớ, mỗi ô 1 byte). Hãy copy xâu kí tự này vào một biến trong chương trình.  

    Với yêu cầu này chương trình phải khai báo một biến byte có độ lớn 50 byte: 

    LuuTru DB 50 Dup (‘ ‘) 

    Mov Ax, 0100

  • 8/19/2019 Tự Học Lập Trình Assembly

    28/74

      Mov  DS, Ax  ; trỏ cặp thanh ghi DS:SI về 

    Mov  SI, 0C00  ; đầu vùng nhớ chưa xâu cần copy (0100:0C00) 

    ;--------------------------------  

    Mov Ax, Seg LuuTru  ; trỏ cặp thanh ghi ES:DI về Mov ES, Ax  ; đầu biến LuuTru 

    Lea DI, LuuTru 

    ;--------------------------------  

    Mov Cx, 50 

    Lap_Copy: 

    Mov Bh, DS:[SI]  ; mượn Bh để chuyển tường kí tự từ ô nhớ được 

    Mov  ES:[DI], Bh  ; chỉ bởi DS:SI sang ô nhớ được chỉ bởi ES:DI 

    Inc SI ; chuyển đến kí tự tiếp theo 

    Inc DI

    Loop  Lap_Copy ; lặp lại đủ 50 lần (để copy  đủ 50 kí tự) 

    Chú : Hợp ngữ còn cung cấp các lệnh LDS (Load Pointer use DS) để lấy  ni dungtoán hạng bộnhớ 32 bít đưa vào các thanh ghi 16 bít (mặc định 16 bít cao vào thanh ghi đoạn dữ liệu DS); vàlệnh LES (Load Pointer use DS) tương tự LDS nhưng  mặc định 16 bít cao vào thanh ghi đoạndữ liệu (thứ hai) ES [2 - 137].

    Tự học lập trình assembly - Bài 4: Tập lệnh assembly của Intel 8086/8088 (3) 

    5. Lệnh Mul và Div 

    Cú pháp: 

      Mul [Toán hạng nguồn] 

      IMul [Toán hạng nguồn] 

      Div [Toán hạng nguồn] 

      IDiv [Toán hạng nguồn] 

    Trong đó: [Toán hạng nguồn]có thể là thanh ghi hay ô nhớ. Với các lệnh nhân: [Toán hạngđích] ngầm định là thanh ghi Al hoặc Ax. Với các lệnh chia: [Toán hạng đích] là một trong cácthanh ghi đa năng Ax, Bx,... 

    Tác dụng: 

    http://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tu-hoc-lap-trinh-assembly-bai-4-tap-lenh-assembly-cua-intel-8086-8088-3.htmhttp://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tu-hoc-lap-trinh-assembly-bai-4-tap-lenh-assembly-cua-intel-8086-8088-3.htmhttp://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tu-hoc-lap-trinh-assembly-bai-4-tap-lenh-assembly-cua-intel-8086-8088-3.htmhttp://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tu-hoc-lap-trinh-assembly-bai-4-tap-lenh-assembly-cua-intel-8086-8088-3.htmhttp://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tu-hoc-lap-trinh-assembly-bai-4-tap-lenh-assembly-cua-intel-8086-8088-3.htm

  • 8/19/2019 Tự Học Lập Trình Assembly

    29/74

    - Lệnh Mul (Multiply): Thực hiện phép nhân trên số không dấu. Nếu [Toán hạng nguồn] làtoán hạng 8 bít thì lệnh sẽ nhân nội dung của [Toán hạng nguồn] với giá trị thanh ghi AL, kếtquả 16 bít chứa ở thanh ghi Ax.

     Nếu [Toán hạng nguồn] là toán hạng 16 bít thì lệnh sẽ nhân nội dung của [Toán hạng nguồn] với

    giá trị thanh ghi Ax, kết quả 32 bít chứa ở cặp thanh ghi Dx:Ax, phần thấp ở Ax, phần cao ở Dx. Nếu phần cao của kết quả (AH hoặc DX) bằng 0 thì các cờ CF = 0 và OF = 0. 

    - Lệnh IMul (Interger Multiply): Tương tự lệnh Mul nhưng thực hiện phép nhân trên hai số códấu. Kết quả cũng là một số có dấu.

    - Lệnh Div (Divide): Thực hiện phép chia trên số không dấu. Nếu [Toán hạng nguồn] làtoán hạng 8 bít thì lệnh sẽ lấy giá trị của thanh ghi Ax (số bị chia) chia cho [Toán hạng nguồn](số chia), kết quả thương số chứa trong thanh ghi Al, số dư chứa trong thanh ghi Ah.

     Nếu [Toán hạng nguồn] là toán hạng 16 bít thì lệnh sẽ lấy giá trị của cặp thanh ghi Dx:Ax (số bịchia) chia cho [Toán hạng nguồn] (số chia), kết quả thương số chứa trong thanh ghi Ax, số dư

    chứa trong thanh ghi Dx. 

     Nếu phép chia cho 0 xảy ra hay thương số vượt quá giới hạn của thanh ghi AL (chia 8 bít) hayAx (chia 16 bít) thì CPU sẽ phát sinh lỗi “Divice overflow”. 

    - Lệnh Idiv (Integer Divide): Tương tự lệnh  Div nhưng thực hiện phép chia trên hai số códấu. Kết quả cùng là các số có dấu.

    Ví dụ 1: 

    - Mul Bl  ; Ax ßAL * Bl: số bị nhân ngầm định trong Al 

    - Mul  Bx  ; Dx:Ax ßAx * Bx: số bị nhân ngầm định trong Ax 

    - Idiv  Bl  ; Ax/Bl, thương số chứa trong Al, số dư chứa trong Ah 

    - Idiv  Bx  ; Dx:Ax/Bx, thương số chứa trong Ax, số dư trong Dx 

    Ví dụ 2: Dãy các lệnh dưới đây sẽ thực hiện phép gán A = 4*A – 3*B, trong đó A và B là các biến kiểu word:

    Mov  Ax, 4  ; số nhân phải được chứa trong Ax 

    IMul  A  ; thực hiện phép nhân 

    Mov  Bx, Ax  ; lưu tạm kết quả vào Bx 

    Mov Ax, 3 ; Ax = 3 

    Imul B ; Ax = Ax * B 

    Sub Bx, Ax

    Mov  A, Bx  ; đặt kết quả cuối cùng vào A 

  • 8/19/2019 Tự Học Lập Trình Assembly

    30/74

    Trong trường hợp này ta đã giả sử hiện tượng tràn đã không xảy ra và kết quả phép nhân chỉchứa trong thanh ghi Ax. 

    Ví dụ 3: Các lệnh sau đây thực hiện phép: chia -123 cho 24:

    Mov Ax, -123  ; đặt số bị chia vào Ax 

    Mov  Bl, 24  ; đặt số chia vào Bl (thanh ghi 8 bít) 

    Idiv  Bl  ; chia Ax cho Bl, kết quả chứa ở Al và Ah 

    Ví dụ 4: Dãy lệnh dưới đây sẽ thực hiện phép gán A = N! (tính N giai thừa). A là một biến word: 

    Mov  Ax, 1  ; chun bị Ax để lưu kết quả 

    Mov  Cx, N  ; tính N! 

    LapNhan:

    Mul Cx ; Ax ßAx * Cx 

    Loop LapNhan

    ;---------------------------  

    Mov  A, Ax  ; trả kết quả vào biến A 

    Trong trường hợp này chúng ta giả sử kết quả không vượt quá gới hạn 16 bít.  

    Chúng ta đã biết: N! = 1 nếu N = 1, N! = N*(N-1)*(N-2)*...*1 nếu N>1, điều này hoàn toàn phùhợp với sự thay đổi của thanh ghi CX trong lệnh lặp Loop. Do đó, ở đây ta có thể sử dụng CXnhư là N trong biểu thức tính giai thừa. 

    Chú : Hợp ngữ cung cấp lệnh AAM (Ascii Adjust for Multiple) để điều chỉnh kết quả phépnhân trên 2 số BCD dạng không dồn. Và lệnh AAD (Ascii Adjust for Division) để điều chỉnh kếtquả phép chia trên 2 số BCD dạng không dồn. Ngoài ra còn có lệnh CBW (Convert Byte toWord) và lệnh CWD (Convert Word to Doubleword) để hỗ trợ cho phép chia trên các số có dấu[2 –  187-200].

    Lệnh IMul của vi xử lý Intel 80286 cho phép ghi rõ [Toán hạng đích], [Toán hạng nguồn] trongcâu lệnh, các lệnh này có thể có đến 3 toán hạng [1 - 541].

    6. Lệnh logic: NOT –  AND –  OR –  XOR –  TEST 

    Trước khi tìm hiểu về các lệnh logic chúng ta xem lại kết quả thực hiện các phép tính logic trên 2 bít nhị phân A và B thông qua bảng sau đây: 

    A B A And B A Or B A Xor B NotA

    0 0 0 0 0 1

  • 8/19/2019 Tự Học Lập Trình Assembly

    31/74

    0 1 0 1 1 1

    1 0 0 1 1 0

    1 1 1 1 0 0

    Bảng trên cho thấy: Với phép And: kết quả = 1 chỉ khi cả hai bít = 1; Với phép Or: kết quả = 0chỉ khi cả hai bít = 0; Với phép Xor: kết quả = 0 khi hai bít giống nhau, kết quả = 1 khi hai bítkhác nhau. Với phép Not: 0 thành 1, 1 thành 0.

    Cú pháp: 

      Not  [Toán hạng đích] 

     

    And  [Toán hạng đích], [Toán hạng nguồn] 

      Or  [Toán hạng đích], [Toán hạng nguồn] 

      Xor  [Toán hạng đích], [Toán hạng nguồn] 

      Test  [Toán hạng đích], [Toán hạng nguồn] 

    Trong đó: [Toán hạng đích], [Toán hạng nguồn] có thể là hằng số (trực hằng), biến, thanh ghihay địa chỉ ô nhớ. [Toán hạng đích] không thể là hằng số.  

    Tác dụng: Mỗi lệnh logic thực hiện phép tính logic tương ứng trên các bít (tương ứng về vị trí)của [Toán hạng đích] và [Toán hạng nguồn], kết quả được ghi vào lại [Toán hạng đích]. Riênglệnh Not, thực hiện phép đảo bít ngay trên các bít của [Toán hạng đích]. Hầu hết các lệnh logicđều ảnh hưởng đến các cờ CF, OF, ZF,...

    - Lệnh Not (Logical Not): Thực hiện việc đảo ngược từng bít trong nội dung của [Toán hạngđích]. Lệnh này không làm ảnh hưởng đến các cờ.  

    Lệnh Not thường được sử dụng để tạo dạng bù 1 của [Toán hạng đích].  

    - Lệnh And (Logical And): Thực hiện phép tính logic And trên từng cặp bít (tương ứng về vịtrí) của [Toán hạng nguồn] với [Toán hạng đích], kết quả lưu vào [Toán hạng đích].  

    Lệnh And thường được sử dụng để xóa (= 0) một hoặc nhiều bít xác định nào đó trong một thanhghi.

    - Lệnh Or (Logical Inclusive Or):Thực hiện phép tính logic Or trên từng cặp bít (tương ứngvề vị trí) của [Toán hạng nguồn] với [Toán hạng đích], kết quả lưu vào [Toán hạng đích].  

    Lệnh Or thường dùng để thiết lập (= 1) một hoặc nhiều bít xác định nào đó trong một thanh ghi.  

  • 8/19/2019 Tự Học Lập Trình Assembly

    32/74

    - Lệnh Xor (eXclusive OR ):Thực hiện phép tính logic Xor trên từng cặp bít (tương ứng về vịtrí) của [Toán hạng nguồn] với [Toán hạng đích], kết quả lưu vào [Toán hạng đích].  

    Lệnh Xor thường dùng để so sánh (bằng nhau hay khác nhau) giá trị của hai toán hạng, nó cũnggiúp phát hiện ra các bít khác nhau giữa hai toán hạng này.

    - Lệnh Test: Tương tự như lệnh And nhưng không ghi kết quả vào lại [Toán hạng đích], nóchỉ ảnh hưởng đến các cờ CF, OF, ZF,... 

    Ví dụ 1: 

    Mov Al,0 ; Al ß0 

     Not Al  ; Al = Not Al. Tức là Al = 0FFh 

    Ví dụ 2: Cho AL = (10010011)2, BL = (11001100)2.

    - And Al, Bl ; Al ß 10010011 And 11001100. Al = 

    - And Al, 0 ; Al ß 10010011 And 0. Al = 

    - Or Bl, Al ; Bl ß 11001100 Or 10010011. Al = 

    - Or Bl, 4 ; Bl ß 11001100 Or 100. Al = 

    - Xor Al, Bl ; Al ß 10010011 Xor 11001100. Al = 

    - Xor Bl, Bl ; Bl ß 11001100 Xor 11001100. Bl = 00000000 

    Ví dụ 3: Để xóa nội dung thanh ghi nào đó, trong hợp ngữ ta có thể sử dụng một trong các lệnhsau đây: 

    - Mov Ax, 0 

    - Sub Ax, Ax 

    - Xor   Ax, Ax  ; các cặp bít giống nhau thì đều = 0 

    Ví dụ 5: Lệnh sau đây sẽ xóa (= 0) các bít 3 và 6 của thanh ghi AL, các bít khác giữ nguyên giátrị: 

    - And AL, 10110111b ; AL ßAL And 10110111 

    Trong trường hợp này: dãy bít  10110111 được gọi là dãy bít mặt nạ, các bít 3 (= 0) và 6 (= 0)được gọi là các bít mặt nạ. Như vậy muốn làm cho bít nào = 0 ta cho bít mặt nạ tương ứng với nó

    = 0, các bít còn lại trong dãy bít mặt nạ đều = 1.

    Ví dụ 6:  Lệnh sau đây sẽ thiết lập (= 1) các bít 3 và 6 của thanh ghi AL, các bít khác giữ nguyêngiá trị: 

    - Or AL, 01001000b ; AL ßAL Or 01001000 

  • 8/19/2019 Tự Học Lập Trình Assembly

    33/74

    Trong trường hợp này: dãy bít 01001000 được gọi là dãy bít mặt nạ, các bít 3 (= 1) và 6 (= 1)được gọi là các bít mặt nạ. Như vậy muốn làm cho bít nào = 1 ta cho bít mặt nạ tương ứng với nó= 1, các bít còn lại trong dãy bít mặt nạ đều = 0. 

    Ví dụ 7: Lệnh sau đây sẽ kiểm tra bít 12 của thanh ghi AX là = 0 hay = 1: 

    - And AX, 0001000000000000b ; AX ßAX And 0001000000000000 

    Với dãy bít mặt nạ như trên, nếu bít 12 của Ax = 0 thì kết quả: Ax = 0, nếu bít 12 của Ax = 1 thìkết quả: Ax 0. 

    Cách dùng lệnh And như trên để kiểm tra bít ít được sử dụng, vì nó làm thay đổi giá trị của thanhghi cần kiểm tra (điều này có thể khắc phục bằng lệnh Test) và phải thêm bước kiểm tra giá trịcủa Ax (= 0 hay 0) mới biết được kết quả kiểm tra. Ngoài ra, nó cũng chỉ kiểm tra được 1 bít.  

    Trong thực tế người ta thường sử dụng kết hợp giữa các lệnh dịch bít, lệnh quay bít, lệnh nhảy,...để kiểm tra các bít trong một thanh ghi. 

    7. Lệnh chuyển dữ liệu qua cng: IN và OUT 

    Cú pháp: 

      IN AL,

      OUT , AL 

    Trong đó: chính là số hiệu cổng (port) mà lệnh nhận nhiệm vụ trao đổi dữ liệuqua nó. Địa chỉ cổng có thể được ghi trực tiếp dưới dạng một hằng số hoặc được ghi thông quathanh ghi Dx.

    Tác dụng: 

    - LênhIn (In put): Đọc một lượng dữ liệu 8 bít từ cổng được chỉ ra ở đưa vàolưu trữ trong thanh ghi AL.

     Nếu địa chỉ cổng nằm trong giới hạn từ 0 đến FF (hệ thập lục phân) thì có thể viết trực tiếp trongcâu lệnh, nếu địa chỉ cổng lớn hơn FF thì ta phải dùng thanh ghi Dx để chỉ định địa chỉ cổng.  

    - LệnhOut (Out put): Gởi một lượng dữ liệu 8 bít từ thanh ghi AL ra cổng được chỉ ra ở . Tương tự lệnh In, địa chỉ cổng có thể được viết trực tiếp trong câu lệnh hoặc thôngqua thanh ghi Dx.

    Ví dụ 1: 

    - In Al, 40h ;

    - Mov Dx, 3B0h ; 

    In Al, Dx ;

    Ví dụ 2: 

  • 8/19/2019 Tự Học Lập Trình Assembly

    34/74

    - Out 40h, Al ;

    - Mov Dx, 3B0h ; 

    Out Dx, Al ;

    Ví dụ 3: Các khai báo hằng: 

    DAT EQU 13h ; 

    POR EQU 7Ch ; 

    Các lệnh: 

    Mov Al, POR ; 

    Mov Bl, DAT ; 

    Out Bl, Al ; 

    Tự học lập trình assembly - Bài 4: Tập lệnh assembly của Intel 8086/8088 (4) 

    Thứ Hai, 02/09/2013 23:37

    Mt s ví dụ minh ha: 

    Ví dụ 1: Giả sử tại địa chỉ 0100:0120 trong bộ nhớ có chứa một mảng dữ liệu, gồm 100 ô nhớ,mỗi ô là 1 word. Hãy tính tổng nội dung của các ô nhớ này, kết quả chứa trong thanh ghi Dx.  

    Mov Ax, 0100

    Mov  DS, Ax  ; trỏ cặp thanh ghi DS:DI về 

    Mov  DI, 0120  ; đầu vùng nhớ cần truy xuất (0100:0120) 

    ;------------------------

    Mov Dx, 0 ; chun bị Dx để lưu tổng 

    Mov  Cx, 100  ; lặp 100 lần vì mảng gồm 100 ô nhớ  

    Lap_TT: 

    Add  Dx, DS:[DI]  ; cộng thêm n/dung ô nhớ chỉ bởi DS:DI vào

    Dx 

    Add  DI, 2  ; chỉ đến ô nhớ kế tiếp (vì ô nhớ word nêntăng 2) 

    Loop  Lap_TT ; lặp lại đủ 100 lần (duyệt qua đủ 100 ô nhớ) 

    ;-----------------------------------  

    http://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tu-hoc-lap-trinh-assembly-bai-4-tap-lenh-assembly-cua-intel-8086-8088-4.htmhttp://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tu-hoc-lap-trinh-assembly-bai-4-tap-lenh-assembly-cua-intel-8086-8088-4.htmhttp://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tu-hoc-lap-trinh-assembly-bai-4-tap-lenh-assembly-cua-intel-8086-8088-4.htmhttp://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tu-hoc-lap-trinh-assembly-bai-4-tap-lenh-assembly-cua-intel-8086-8088-4.htmhttp://www.tuhocanninhmang.com/ngon-ngu-lap-trinh/assembly/tu-hoc-lap-trinh-assembly-bai-4-tap-lenh-assembly-cua-intel-8086-8088-4.htm

  • 8/19/2019 Tự Học Lập Trình Assembly

    35/74

    Kết thúc đoạn lệnh trên tổng nội dung của 100 word nhớ bắt đầu tại địa chỉ 0100:0120 trong bộnhớ được lưu vào thanh ghi Dx. Ở đây chúng ta bỏ qua khả năng tràn dữ liệu trong thanh ghi kếtquả Dx. 

    Ví dụ 2: Các lệnh sau đây sẽ copy 100 word dữ liệu từ vùng nhớ bắt đầu tại địa chỉ 0100:0120

    sang vùng nhớ bắt đầu tại 0100:0500: Mov Ax, 0100 

    Mov DS, Ax 

    Mov SI, 0120 ; trỏ DS:SI về vùng nhớ nguồn 0100:0120 

    Mov DI, 0500 ; trỏ DS:DI về vùng nhớ địch 0100:0500 

    ;--------------------  

    Mov Cx, 100 

    Lap_Copy: 

    Mov Ax, DS:[SI] ; lưu tạm nội dụng word nhớ tại DS:SI  vào Ax 

    Mov DS:[DI], Ax ; ghi giá trị Ax và word nhớ tại DS:DI 

    Add SI, 2 ; đến word nhớ tiếp theo 

    Add DI, 2 

    Loop Lap_Copy 

    ;-------------------------  

    Hai vùng bộ nhớ đã cho đều ở trong cùng một segment nên ở đây ta chỉ  cần sử dụng một thanhghi đoạn dữ liệu DS.

    Ví dụ 3: Các lệnh sau đây sẽ tính tổng nội dung của 100 ô nhớ (100 byte nhớ) trong bộ nhớ, bắtđầu tại địa chỉ 0A00:0120. Kết quả được lưu vào word nhớ ngay trước vùng nhớ này:  

    Mov Ax, 0A00h 

    Mov ES, Ax 

    Mov SI, 0120h ; trỏ DS:SI về vùng nhớ nguồn 0A00:0120 

    Mov DI, SI ; trỏ DS:DI về vùng nhớ nguồn 0A00:0120 Sub DI,2 ; trỏ DS:DI về word nhớ trước vùng nhớ nguồn 

    ;------------------------  

    Mov Cx, 100

    Mov Dx, 0 ; DX chứa tổng 

  • 8/19/2019 Tự Học Lập Trình Assembly

    36/74

      TTong: 

    Add Dx, Byte PTR  ES:[SI] ; cộng n.d của byte nhớ tại ES:SI vàoDX 

    Inc SI ; ô nhớ byte 

    Loop TTong ;----------------------------------------

    Mov Word PTR  ES:[DI], DX 

    ;----------------------------------------

    Trong đoạn lệnh trên chúng ta sử dụng toán tử PTR để định kiểu ô nhớ cần truy xuất.Lệnh Add Dx, Byte PTR ES:[SI]: lấy nội dung của byte nhớ tại ô nhớ được chỉ bởi ES:SIcộng thêm vào thanh ghi DX. Nếu ta viết Add Dx, ES:[SI] thì hệ thống lấy giá trị cả 1word tại ES:SI cộng thêm vào DX (vì DX là thanh ghi word (16 bít), điều này không đúng vớithực tế, vì chúng ta đang cần truy xuất đến các byte nhớ. Trong trường hợp này, nếu không dùngtoán tử PTR thì lệnh Add phải viết như sau: Add DL, ES:[SI], khi đó hệ thống chỉ lấy giá trịcả 1 byte tại ES:SI cộng thêm vào DL (vì DL là thanh ghi byte: 8 bít), 

    Ví dụ 4: Các lệnh sau đây sẽ copy toàn bộ 20 kí tự Ascii từ biến Xau1 vào biến Xau2. Giả sửXau1 và Xau2 đã được khai báo trước như sau: 

    Xau1 DB ‘Khoa CNTT –  DHKH Hue’ 

    Xau2 DB 20 Dup (‘ ’) 

    Các lệnh: 

    Mov Ax, @Data 

    Mov DS, Ax 

    Lea SI, Xau1 

    Lea DI, Xau2 

    ;------------------------  

    Mov Cx, 20 

    Lap_Copy: 

    Mov Al, Byte PTR DS:[SI] 

    Mov Byte PTR DS:[DI], Al 

    Inc SI 

    Dec DI 

    Loop Lap_Copy

  • 8/19/2019 Tự Học Lập Trình Ass