Bước đầu Với Lập Trình Assembly Trên Vi Xử Lý Intel 8086/8088

OPTADS360 intTypePromotion=1 zunia.vn Tuyển sinh 2024 dành cho Gen-Z zunia.vn zunia.vn tailieu.vn NÂNG CẤP Đăng Nhập | Đăng Ký Chủ đề »
  • Ngôn ngữ lập trình
  • Lập trình hướng đối tượng
  • Lập trình Android
  • Lập trình Java
  • Lập trình IOS
  • HOT
    • FORM.07: Bộ 125+ Biểu Mẫu Báo Cáo...
    • LV.11: Bộ Luận Văn Tốt Nghiệp Chuyên...
    • FORM.08: Bộ 130+ Biểu Mẫu Thống Kê...
    • CEO.27: Bộ Tài Liệu Dành Cho StartUp...
    • LV.26: Bộ 320 Luận Văn Thạc Sĩ Y...
    • FORM.04: Bộ 240+ Biểu Mẫu Chứng Từ Kế...
    • CEO.29: Bộ Tài Liệu Hệ Thống Quản Trị...
    • CEO.24: Bộ 240+ Tài Liệu Quản Trị Rủi...
    • TL.01: Bộ Tiểu Luận Triết Học
    CMO.03: Bộ Tài Liệu Hệ Thống Quản Trị Marketing...
TUYỂN SINH YOMEDIA ADSENSE Trang Chủ » Công Nghệ Thông Tin » Kỹ thuật lập trình 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ý intel 8086/8088

Chia sẻ: Vuong Dinh | Ngày: | Loại File: DOCX | Số trang:66

Thêm vào BST Báo xấu 738 lượt xem 59 download Download Vui lòng tải xuống để xem tài liệu đầy đủ

Bài 1 "Bước đầu với lập trình assembly trên vi xử lý intel 8086/8088" hướng dẫn các bạn việc tự học lập trình assembly. Đây là tài liệu lập trinh Assembly giảng dạy tại Trường Đại học Bách khoa Hà Nội dùng cho việc học vi xử lí rất quan trọng. Mời các bạn cùng tham khảo.

AMBIENT/ Chủ đề:
  • Tự học lập trình assembly
  • Bước đầu với lập trình assembly
  • Vi xử lý intel 8086/8088
  • Vi xử lý
  • Lập trình assembly
  • Hướng dẫn học vi xử lí

Bình luận(0) Đăng nhập để gửi bình luận!

Đăng nhập để gửi bình luận! Lưu

Nội dung Text: 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ý intel 8086/8088

  1. 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ý Intel  8086/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ột cá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ến trú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úp chú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ều hà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ọ  Intel 8088/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 trong sự 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ác ngô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ệnh hợ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ập trì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ình hỗ 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ác chươ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ực hiệ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ệnh hợ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 
  2. 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 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ít hoặ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àm thư 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ớ  (khi chươ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 trong chươ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               
  3. 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 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ũng là 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ến kiể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  định nghĩ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,  byte cao 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.
  4. 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ồm  nhiề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. 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ận giá 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  nhau trong 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ến tiế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ến TieuDe bắt đầu tại offset 102, biến SoNguyen định vị tại offset 109, biến DaySo bắt  đầu tại offset 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  qua tê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:   Microsoft  MacroAssembler và A86 MacroAssembler V4.05 để  dịch các chương trình hợp ngữ  (*.asm)  sang chươ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ập tin 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 COM ta phải sử dụng thêm một chương trình khác của MS_DOS, đó là EXE2Bin.com.   
  5.             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ình  Turbo Pascal. Chức năng của các tập tin biên dịch hợp ngữ liên quan: 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ập tin 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ình nguồ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 tin chí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ừng lệ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ảo chươ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ạn thảo Notepad trên Windows (Windows XP) để viết và chỉnh sửa chương trình hợp  ngữ, trong trườ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ịch a86.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.
  6. ­      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ình thà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ình  In_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 đã được  chè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.
  7. 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 tin  chươ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ác dò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ột chương trình hợp ngữ viết theo dạng COM thành tập tin thực thi dạng 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  EXE và 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ượng ngô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. 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ình  hợ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òng  chươ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ỗi tạ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 tin  chươ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ải  viế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.crf Vớ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  thi duy nhất. Cú pháp đơn giản:     
  9. LINK              [đường dẫn]; 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 đối  tượ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 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.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 COM  chú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ư mong  muố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ạng COM 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ình nà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ạn củ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 đó,  khi thiế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  modun chươ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ạng EXE 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 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 
  10. thường mỗ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ác hướ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ên dị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  định nghĩa đoạn đơn giản (.Model, .Code, .Stack, .Data) phù hợp với MASM, TASM (Turbo  Macro Assembler), 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áng sủ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ương trì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ướng dẫ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  trong chươ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 định nghĩ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  đây của tài liệu này. Cấu trúc chương trình dạng EXE: .Model            .Stack           100h .Data           .Code                                PROC              
  11.                      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ác  hướ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ện nhiệ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ữa hai 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ẽ được trình bày ngay sau đây. Chương trình viết theo cấu trúc dạng COM: .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
  12. 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ệnh Jmp. 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ết thú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                         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 định  nghĩ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ắt 21h để 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ần hướ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 
  13. nhau. Hai chươ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ến MyChildren). 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ởi  nó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  trong mộ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ữ. ­ 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ơn 64 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ệu có 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ương trì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ạn Data 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ạn Stack 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  đầu tiê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ùng nhớ PSP. Do đó, DOS phải đưa địa chỉ segment của vùng nhớ chứa PSP  vào cả DS và ES trước khi 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 ở  đầu chươ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ày chươ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. 
  14. Đị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à linh  hoạ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. 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ợp ngữ [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ày  hoà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). 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 
  15. ghi đoạn về đ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ế Assume DS: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ạp trự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 SS sẽ đượ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ũng  khô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òng chỉ 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/8086 có 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ì 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ợp nà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 
  16. 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ấu chấ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ệnh Mov. 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  thanh ghi đ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                                                  ; (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ấy nộ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]  (trong lệ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:      
  17.               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ủa  mộ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ủa  mộ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                                                     ; ô 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  đương với lệnh (3) nhưng khác lệnh (4): ­             Mov        Ax, DS:[DI]                ; (3)     
  18. ­             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  thanh ghi đ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                     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  DI và 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:
  19. 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). 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:
  20.                     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ội  dung 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 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ội dung 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 địa  chỉ 0100:0120.
ADSENSE

CÓ THỂ BẠN MUỐN DOWNLOAD

  • Giáo trình về Hợp ngữ

    doc 96 p | 571 | 257

  • Tài liệu: Lập trình hợp ngữ MIPS

    pdf 10 p | 1145 | 226

  • Chương III : Lập trình hợp ngữ và tóm tắt tập lệnh

    pdf 10 p | 497 | 218

  • Bài thực hành số 2: Lệnh so sánh – Lệnh nhảy – Lệnh lặp

    doc 7 p | 438 | 98

  • Lập trình Virus bằng ngôn ngữ assemble

    doc 11 p | 472 | 80

  • Giáo trình lập trình Verilog Tiếng Việt 7

    pdf 6 p | 231 | 67

  • C# and .NET Framework Lassion 9

    pdf 13 p | 178 | 51

  • LẬP TRÌNH XỬ LÝ ĐĨA&FILE

    ppt 65 p | 160 | 37

  • Giáo trình môn lập trình hợp ngữ

    pdf 0 p | 107 | 21

  • C# và kiến trúc .NET.C# cơ bản - Bài 9

    pdf 13 p | 137 | 14

  • C# and .NET Framework phần 9

    pdf 13 p | 69 | 7

  • Bài giảng Hợp ngữ và lập trình hệ thống: Chương 0 - Phạm Công Hòa

    pdf 7 p | 81 | 4

Thêm tài liệu vào bộ sưu tập có sẵn: Đồng ý Thêm vào bộ sưu tập mới: *Tên bộ sưu tập Mô Tả: *Từ Khóa: Tạo mới Báo xấu
  • Hãy cho chúng tôi biết lý do bạn muốn thông báo. Chúng tôi sẽ khắc phục vấn đề này trong thời gian ngắn nhất.
  • Không hoạt động
  • Có nội dung khiêu dâm
  • Có nội dung chính trị, phản động.
  • Spam
  • Vi phạm bản quyền.
  • Nội dung không đúng tiêu đề.
Hoặc bạn có thể nhập những lý do khác vào ô bên dưới (100 ký tự): Vui lòng nhập mã xác nhận vào ô bên dưới. Nếu bạn không đọc được, hãy Chọn mã xác nhận khác.. Đồng ý LAVA AANETWORK THÔNG TIN
  • Về chúng tôi
  • Quy định bảo mật
  • Thỏa thuận sử dụng
  • Quy chế hoạt động
TRỢ GIÚP
  • Hướng dẫn sử dụng
  • Upload tài liệu
  • Hỏi và đáp
HỖ TRỢ KHÁCH HÀNG
  • Liên hệ
  • Hỗ trợ trực tuyến
  • Liên hệ quảng cáo
Theo dõi chúng tôi

Chịu trách nhiệm nội dung:

Nguyễn Công Hà - Giám đốc Công ty TNHH TÀI LIỆU TRỰC TUYẾN VI NA

LIÊN HỆ

Địa chỉ: P402, 54A Nơ Trang Long, Phường 14, Q.Bình Thạnh, TP.HCM

Hotline: 093 303 0098

Email: support@tailieu.vn

Giấy phép Mạng Xã Hội số: 670/GP-BTTTT cấp ngày 30/11/2015 Copyright © 2022-2032 TaiLieu.VN. All rights reserved.

Đang xử lý... Đồng bộ tài khoản Login thành công! AMBIENT

Từ khóa » Tự Học Assembly