(NHỮNG HÌNH NÀY Ở TRONG SÁCH GIÁO KHOA. CHỈ CÓ Ở CHƯƠNG 7) Chương 7 8086 System Connections. Timing, and Troubleshooting Hình 7-1a.TRANG 164 Hình trên trình bày một sơ đồ khối đơn giản của một bộ VXL 8086 cơ bản. Sơ đồ trên chứa CPU 8086, ROM, RAM, các cảng. Có một sự đa dạng lớn của thiết bị cảng có thể sử dụng được. Các thiết bị cảng là nơi giao tiếp với CRTs, với bàn phím và các cảng giao tiếp với đĩa mềm. Ngoài ra còn có các bus điều khiển, bus địa chỉ, bus dữ liệu. Bus điều khiển cơ bản bao gồm các tín hiệu như M/IO, RD, WR tại đỉnh của sơ đồ. Nếu 8086 thực hiện việc đọc từ bộ nhớ hoặc từ các cảng thì tín hiệu RD được xác lập thấp. Nếu 8086 thực hiện việc ghi vào bộ nhớ hoặc đưa dữ liệu ra các cảng thì tín hiệu WR sẽ được xác lập thấp. Khi làm việc với bộ nhớ (đọc, ghi) thì M/IO là cao, khi làm việc với các cảng (đọc, ghi) thì tín hiệu M/IO là thấp. Các tín hiệu RD, WR, M/IO sử dụng để kích hoạt các thiết bị địa chỉ. Bus địa chỉ và bus dữ liệu được trình bày riêng biệt, nhưng nơi chúng ra khỏi 8086 thì 2 bus này sử dụng chung một bus đơn có nhãn ADDR/DATA. Trong các hoạt động, noi nó truy nhập vào bộ nhớ hoặc cảng, 8086 gửi ra ngoài 16bit thấp của địa chỉ trên bus dữ liệu. Các bộ chốt như 74LS373 (hệ số 8) sử dụng để "bắt" lấy địa chỉ này và nắm giữ chúng. Một tín hiệu Address Latch Enable (ALE) để kích hoạt bộ chốt địa chỉ tại thời điểm thích hợp. Khi đia chỉ được tích trữ trên đầu ra của các bộ chốt, 8086 rời địa chỉ này từ bus ADDR/DATA và sử dụng bus cho việc đọc, ghi địa chỉ. Khối 8286 mô tả bộ đệm 3 trạng thái, 2 hướng. ở các hệ thống nhỏ thì bộ đệm này không cần thiết. Nhưng ở hệ thống lớn, có nhiều thiết bị nối tới bus thì chúng trở nên cần thiết. Nó có tác dụng tăng cường tín hiệu điện đến các thiết bị. Các bộ đệm sử dụng trên bus dữ liệu buộc là 2 hướng bởi vì 8086 gửi dữ liệu ra và cũng nhận dữ liệu về trên cùng một bus dữ liệu. Tín hiệu DT/R (data transmit - data receive) từ 8086 đặt hướng truyền hoặc nhận. Khi DT/R cao thì bộ đệm sẽ truyền dữ liệu từ 8086 tới ROM, RAM hoặc cổng. Khi DT/R thấp thì bộ đệm sẽ cho phép dữ liệu từ ROM, RAM hoặc cổng đi vào 8086. Bộ đệm sử dụng trên bus dữ liệu phải có 3 trạng thái đầu ra vì các đầu ra có thể được thả nổi khi bus dữ liệu được sử dụng cho thao tác khác.(VD : Ta không muốn các đầu ra bộ đệm bus dữ liệu được kích hoạt trên bus dữ liệu trong khi 8086 đang đặt ra ngoài 16bit thấp của 1 địa chỉ trên các đường này. 8086 xác lập tín hiệu DEN để cho phép đầu ra 3 trạng thái trên bộ đệm bus dữ liệu tại thời điểm chiếm dụng trong 1 thao tác. 1 Phần cuối của sơ đồ là xem xét 8284A Clock. Ðây là bộ phát điện (tín hiệu. Thiết bị này sử dụng thuỷ tinh (thạch anh) để phát ra xung đồng hồ ổn định. 8284 cũng đồng thời xảy ra tín hiệu RESET và tín hiệu READY với xung nhịp. Vì vậy các tín hiệu này được gắn vào 8086 tại thời điểm tích hợp. Khi đầu vào RESET được thiết lập 8086 nhảy đến địa chỉ FFFF0H để nhận lệnh đầu tiên của chương trình khởi động hệ thống được đặt tại địa chỉ này. AN EXAMPLE PORT DECODER Hình 7-12a.TRANG 189 Hình trên trình bày bộ giải mã 74LS138 được kết nối với hệ thống để đưa ra tín hiệu chọn chip cho một vài thiết bị cảng. Ðường A14 và A15 phải cao để kích hoạt bộ giải mã (A15 =1, A14 = 1), A13, A12 phải là thấp để kích hoạt bộ giải mã (A12, A13 = 0). Các đường địa chỉ A3, A4, A5 được nối với các đầu vào A, B, C tương ứng của bộ giải mã (do đó ta có các trạng thái tổ hợp 3 đầu vào). Các đường địa chỉ A0, A1, A2 được kết nối trực tiếp tới các thiết bị cảng để đánh địa chỉ cụ thể các cảng và các thanh ghi điều khiển trong các thiết bị. A6 - A11 không kết nối tới các thiết bị cảng hoặc bộ giải mã vì chúng không tác động trong việc chọn cảng. Nếu các bit này là 0 ứng với các đầu vào A3, A4, A5 ta sẽ có địa chỉ cá cảng (C000, C008), (C010, C018), (C020, C028), (C030, C038). Nếu thay thế bit A6 = 1, A14, A15 = 1, A13, A12, A5, A4, A3 = 0 khi đó ta sẽ có địa chỉ C040H. Do vậy ta có thể kết hợp các bit 0, 1 từ A6 - A11 để thêm vào các địa chỉ cảng. • Trong một hệ thống 1 cảng có thể được đọc hoặc ghi như bộ nhớ. Ta có thể sử dụng lệnh MOV AL, DS : BYTE PTR 0C000H để đọc 1 byte dữ liệu từ cảng đầu tiên tới thanh ghi AL thay cho lệnh : MOV DX, 0C000h IN AL, DX MEMORY BANK Hình 7-13.TRANG 190 8086 có 20 đường địa chỉ do đó nó có thể địa chỉ được 2^20 = 1.048.576 địa chỉ. Khi ta viết 1 word vào bộ nhớ với lệnh MOV DS : WORD PTR[437AH], BX. Từ này trên thực tế được viết vào 2 địa chỉ bộ nhớ liên tiếp nhau. Coi như DS chứa 0000, byte thấp của Word này được viết vào địa chỉ cụ thể 0437AH, byte cao được viết vào địa chỉ cao hơn tiếp theo 0437BH. Ðể nó có thể đọc, viết 1 word với 1 chu kỳ máy, bộ nhớ của 8086 được thiết lập 2 bank, mỗi bank chứa 524.288 byte. Một chứa tất cả các byte có địa chỉ chẵn (0000, 0002 ) các đường dữ liệu của bank này được nối với 8 đường dữ liệu thấp D0 - D7 của 8086. Băng còn lại chứa các byte có 2 địa chỉ lẻ (0001, 0003, ) các đường dữ liệu của băng này được nối tới 8 đường dữ liệu cao D8 - D15 của 8086. Ðường địa chỉ A0 sử dụng để kích hoạt băng thấp, băng này sẽ đượckích hoạt khi A0 là thấp. A1 - A19 sử dụng để chọn thiết bị bộ nhớ mong muốn trong băng và đánh địa chỉ byte mong muốn trong thiết bị đó. Tín hiệu BHE sử dụng để kích hoạt băng lẻ (BHE là tín hiệu tổng hợp, phức tạp đưa ra từ 8086 trên 1 đường tín hiệu tại cùng thời điểm khi địa chỉ được gửi ra ngoài). Khi đọc 1 byte hoặc viết 1 byte với địa chỉ chẵn (0000H) A0 thấp, BHE cao. Băng thấp được kích hoạt và băng cao không được kích hoạt, khi đó dữ liệu được đi vào hoặc đi ra trên các đường D0 - D7. Nếu DS chứa 0000H khi sử dụng lệnh MOV AX, DS PTR[0000] để đọc 1 word từ ô nhớ vào thanh ghi AX. A0 , BHE thấp, cả 2 băng được kích hoạt, byte thấp của word được truyền từ địa chỉ 0000H tới 8086 trên D0 - D7, còn byte cao được truyền từ địa chỉ 0001H tới 8086 trên D8 - D15. Khi ta dùng lệnh MOV AL, DS : BYTE PTR[0001] để truy nhập 1 byte tại địa chỉ lẻ, A0 cao, BHE thấp, băng cao được kích hoạt, byte được truyền từ địa chỉ 0001H trong băng cao tới 8086 trên D8 - D15. Khi đọc hoặc viết 1 word với địa chỉ lẻ. VD MOV AX, DS : WORD PTR[0001], copy byte thấp của word từ địa chỉ 0001H tới AL và byte cao từ địa chỉ 0002H tới AH. Trong trường hợp này 8086 yêu cầu 2 chu kỳ máy. Chu kỳ thứ nhất 8086 đưa ra ngoài địa chỉ 0001H xác lập BHE thấp, A0 cao, byte từ 0001H được đọc vào 8086 trên D8 - D15 và đặt vào AL. Chu kỳ thứ 2, 8086 gửi ra ngoài địa chỉ 0002H xác lập A0 thấp, BHE cao, dữ liệu được đọc vào 8086 trên D0 - D7 và đặt vào AH. Sự phân chia ra 2 chu kỳ này có tác dụng ngăn ngừa việc ghi dữ liệu không mong muốn vào vị trí bộ nhớ tiếp theo khi 8086 ghi 1 byte vào bộ nhớ. Sheet 1 of 9 của 7-8.TRANG 176 Hình trên trình bày mạch điện kết nối cho EPROM và EPROM giải mã. Các EPROM 2716 là các thiết bị 2Kx8. 2 EPROM A27, A36 có 8 đầu ra được nối tới 8 đường dữ liệu thấp của hệ thống D0 - D7. 2 ROM này đưa ra 4KB trong băng địa chỉ thấp. 2ROM A30, A37 có 8 đầu ra nối với 8 đường dữ liệu cao của hệ thống A8 - A15 đưa ra 4KB trong băng địa chỉ cao. 11 đường địa chỉ cần để đánh 2Kbyte địa chỉ trong mỗi EPROM. Do đó địa chỉ hệ thống A1 - A11 được nối tới tất cả các ROM. (A0 được dùng kể kích hoạt hoặc vô hiệu hoá hoạt động của băng địa chỉ thấp.) Mỗi EPROM 2716 có 2 đầu vào kích hoạt là CE và OE. Do đó để A2716 hoạt động thì cả 2 đầu vào này là thấp. Ðầu vào của 2 EPROM trong băng thấp được nối với A0 do 3 vậy đẻ CE của 2 ROM này thấp thì A0 phải thấp. Ðầu vào CE của 2 EPROM trong băng cao được nối với BHE. Do đó để CE của 2 EPROM này thấp thì BHE phải thấp. Xét A26 3625 : Ðây là PROM 1K x 4, có tác dụng giải mã địa chỉ. 4 đầu ra O1, O2, O3, O4 được nối với nguồn 5V qua 4 điện trở và được nối tới các thiết bị để kích hoạt chúng. Ðặc điểm của 3625 là có thể lập trình được, do đó ta có thể chuyển các thiết bị nhớ tới các địa chỉ mới trong bộ nhớ bằng cách lập trình 1 ROM mới. * Các tín hiệu kích hoạt bộ giải mã : - Ðầu vào kích hoạt CS1 được nối với đất do đó luôn thấp. - Ðầu vào kích hoạt CS2 được nối với tín hiệu RD của 8086 do đó bộ giải mã chỉ được kích hoạt khi 8086 thực hiện thao tác đọc dữ liệu. Từ bảng 7-14(TRANG 191) thấy rằng đầu ra O1 của 3625 được xác lập thấp, M/IO cao do đó thiết bị bộ nhớ được kích hoạt (thiết bị cảng không được kích hoạt). A12- A19 cao (=1) để đầu ra O1 thấp. Ðịa chỉ thấp nhất mà nó chọn là FF000H. O1 được nối tới đầu vào kích hoạt OE của 2 EPROM 2716 đó là A27 và A30. Do đó các đầu vào OE này được kích hoạc khi 8086 gửi ra ngoài 1 địa chỉ trong dải FF000H - FFFFFH. - Ðầu vào CE của A27 được nối với A0, thiết bị này được kích hoạt khi 8086 đọc 1 địa chỉ chắn trong dải FF000H - FFFFFH. - Ðầu vào CE của A30 nối với đường BHE . BHE xác lập thấp khi 8086 truy nhập 1 byte tại 1 địa chỉ lẻ hoặc 1 word tại địa chỉ chẵn. Do đó A30 được kích hoạt khi 8086 đọc 1 byte từ 1 địa chỉ lẻ trong dải FF000 - FFFFF. A30 cũng có thể được kích hoạt khi 8086 xác lập khi cả 2 tín hiệu A0 và BHE thấp để đọc 1 word tại địa chỉ chẵn. * Ðầu ra O2 của 3625 được xác nhận cho dải địa chỉ FE000H - FEFFFH. Tín hiệu này là 1 trong những tín hiệu dùng để kích hoạt A36 và A37. 2 ROM này hoạt động tương tự như A27 và A30. * Ðầu ra O3 và O4 của bộ giải mã 3625 chưa được sử dụng, ta có thể sử dụng để kích hoạt các EPROM khác mà ta muốn thêm vào. (Thêm : Các EPROM được đặt ở địa chỉ cao trong bộ bớ trên board 8086. Vì sau khi RESET, 8086 sẽ nhảy đến địa chỉ FFFF0H để thực hiện lệnh đầu tiên. Do đó ta có thể đặt 1 chương trình tại địa chỉ này để 8086 thực hiện kho có tín hiệu RESET. RAM ADDRESS DECODING ON THE SDK - 86 Sheet 6 of 9(TRANG181) Trước hết trong sơ đồ ta thấy có RAM hệ thống và RAM giải mã. Ta thấy trên mỗi RAM tĩnh có 4 đường dữ liệu I/O do đó thiết bị có thể chứa word 4 bit. Mỗi RAM có 10 đường địa chỉ đầu vào A0 - A9 do đó nó có thể chứa 210 = 1024 của word 4 bit. Ðể tích trữ các byte 2 RAM được kích hoạt song song. Ví dụ A38 và A41 cùng 4 được kích hoạt để chứa các byte từ 8 đường dữ liệu thấp. A43 và A45 cùng được kích hoạt để chứa byte từ 8 đường dữ liệu cao. Các tín hiệu điều khiển RD, WR, M/IO được nối tới tất cả các RAM. RD nối với chân OD (output disable). Khi RD cao hoặc thiết bị không được kích hoạt các đầu ra sẽ không có hiệu lực. Trong 1 thao tác đọc RD thấp, nếu 2142 được kích hoạt và OD thấp do đó dữ liệu được đưa ra trên bus dữ liệu. WR từ 8086 được nối với đầu vào WE (write enable) trên các RAM 2142. Nếu 2142 được kích hoạt, dữ liệu trên bus dữ liệu được viết vào vị trí địa chỉ trong RAM khi 8086 xác lập WR thấp. Các RAM 2142 có 2 đầu vào kích hoạt, CS1 và CS2. Tín hiệu M/IO từ 8086 được nối tới CS2 được tích cực cao khi 8086 làm việc với bộ nhớ. Ðầu vào CS1 của các 2142 được nối với các đầu ra O1, O2, O3, O4 của bộ giải mã 3625. Xét bộ giải mã A29 3625. - Ðầu vào kích hoạt CS2 của 3625 PROM được nối với đất do đó nó luôn thấp. - Ðầu vào kích hoạt CS1 được xác lập khi A19 thấp. - A0 và BHE được nối tới 2 đầu vào địa chỉ trên 3625. Từ bảng 7-15(TRANG 193) Dòng 3 : O1 thấp khi nếu A12 - A18 thấp, A11 thấp, A0 thấp và BHE cao. O1 sẽ xác định địa chỉ chẵn bắt đầu với 00000H. Khi đó nó kích hoạt A38 và A41, các đầu ra của A38 và A41 được nối với nửa thấp của bus dữ liệu (A38 và A41 là bộ phận của băng thấp của RAM). Dòng 2 : O2 thấp khi A12 - A18 thấp, A11 thấp BHE thấp, A0 cao. O2 xác định địa chỉ lẻ bắt đầu 0001H. Khi đó A43, A45 dược kích hoạt. A43 và A45 được nối với nửa cao của bus dữ liệu (chúng là bộ phận của băng cao của RAM). (Muốn viết 1 word 16 bit tới 1 địa chỉ chẵn 0-07FF thì cả 2 băng thấp và cao phải được kích hoạt do đó O1và O2 thấp, BHE thấp, A0 thấp // BHE thấp và A0 thấp khi ta muốn đọc/ghi 1 word tới địa chỉ chắn ). PORT ADDRESSING AND PORT DECODING Trong hệ thống với bản đề bộ nhớ vào ra (Memỏy mapped I/O) các thiết bị cảng được đánh địa chỉ và được chọn bởi các bộ giải mã khi chúng là thiết bị bộ nhớ. Lợi ích chính của Memory mapped I/O là bất kỳ các lệnh nào mà đề cập tới bộ nhớ có thể về mặt lý thuyết mà nói (theoretically) được sử dụng để đọc, viết với cảng. Lệnh đơn giản ADD BH, DX : BYTE PTR[437A] có thể sử dụng để đọc 1 byte từ memory mapped port và cộng nó với thanh ghi BH. Sự bất lợi của memory mapped I/O là các cảng chiếm giữ (occupy) một 5 phần không gian bộ nhớ hệ thống. Không gian này sau đó không được sử dụng cho việc chứa dữ liệu hoặc lệnh. Ðể tránh (avoid) phải sử dụng một phần không gian bộ nhớ hệ thống cho các cảng, họ vi xử lý 8086 có 1 không gian địa chỉ riêng biệt cho các cảng gọi là direct I/O vì không gian địa chỉ này được truy nhập trực tiếp với lệnh IN và OUT. VD IN AL, 38H nó copy 1 byte từ cảng 38H tới thanh ghi AL. Với thao tác vào, ra với cảng có thể thay đổi được, địa chỉ cảng 16 bit trước hết được nạp vào thanh ghi DX với lệnh MOV DX, 0FFF8H. Lệnh IN AL, DX sau đó sẽ copy 1 byte từ cảng FFF8H tới thanh ghi AL. Khi 8086 thực hiện lệnh IN or OUT để truy nhập 1 cảng, không có thanh ghi segment nào bị dính líu trong việc sinh ra địa chỉ vật lý được gửi ra ngoài bởi 8086. Ðịa cảng được gửi ra ngoài trực tiếp từ 8086 trên đường AD0-AD15 và 0 là đầu ra trên các đường A16-A19. Trong 1 hệ thống 8086 sử dụng direct I/O tín hiệu M/IO sử dụng để kích hoạt bộ giải mã bộ nhớ hoặc bộ giải mã cảng. Khi M/IO cao nó sẽ là 1 trong những điều kiện để kích hoạt bộ giải mã ROM và RAM. Khi M/IO thấp nó sẽ kích hoạt một bộ giải mã cảng. Trong khi thực hiện lệnh IN, tín hiệu RD từ 8086 thấp. Khi nó thực hiện lệnh OUT thì tín hiệu WR từ 8086 là thấp. Khi đó đầu ra của 8086 là 16 bit địa chỉ cho direct I/O, do đó nó có thể có 216 hay 65.535 cho địa chỉ cảng vào ra. ________________________________________________________________________ Hình (7-16)(TRANG 194) Ðể O1 thấp thì A5 - A15 cao, A4 thấp, A3 cao, BHE có thể thấp hoặc cao. Do chỉ có 8 đường dữ liệu thấp D0 - D7 được nối tới 8279A31. Do đó dữ liệu được gửi tới hoặc đọc ra từ 8279 tại 1 byte địa chỉ chẵn. Ðịa chỉ cơ sở hệ thống cho thiết bị này là FFE8H. Ðường địa chỉ hệ thống A1 được nối tới 8279 để chọn 1 trong 2 địa chỉ bên trong của thiết bị. A1 thấp đưa ra địa chỉ FFE8H, A1 cao chọn 1 địa chỉ bên trong khác và đưa ra địa chỉ FFEAH. Theo bảng sự thật 7-16 để O2 thấp thì A4 - A15 cao, A3 thấp, BHE thấp hoặc cao. Chỉ có 8 đường địa chỉ thấp được nối với 8251 USART (sheet 9 of 9), dữ liệu phải được gửi tới hoặc đọc ra thiết bị là 1 byte tại địa chỉ chắn. Ðường địa chỉ hệ thống A1 sử dụng để chọn 1 trong 2 địa chỉ bên trong của 8251A (FFF0H, FFF2H). _____________________________________________________________________ Sheet 5 of 9 (TRANG 180): * 2 đầu ra O3, O4 của bộ giải mã PROM được nối tới 2 thiết bị cảng 8255A để kích hoạt chúng. Các thiết bị này chứa đựng 3 cảng song song 8bit và 1 thanh ghi điều khiển. Ðường A1 và A2 sử dụng để đánh địa chỉ thanh ghi hoặc cảng mong muốn trong thiết bị. 8 đường dữ liệu thấp D0 - D7 được nỗi tới thiết bị A40, 8 đường dữ liệu cao (D8-D15) được nối tới thiết bị A35. Ta cũng có thể đọc, ghi 1 Word (16 bit) với cảng 16 bit tạo bởi 2 cảng 8 bit là A40 và A35. Ðể nhập vào hoặc xuất ra 1 word thì A40 và A35 phải cùng được kích hoạt. 6 - A40 được kích hoạt bởi đầu ra O3 (LOW PORT SEL) của bộ giả mã PROM 3625 nếu các đường địa chỉ A3 - A15 cao, A0 thấp, A1 và A2 sử dụng để chọn cổng bên trong 8255A. 2 bit này thấp sẽ cho địa chỉ ddaafu tiên trong thiết bị. Ðể chọn cảng A trong A40 8255 thì A1 và A2 phải thấp. Ðịa chỉ hệ thống sẽ kích hoạt thiết bị này và chọn cảng A có địa chỉ FFF8H. Giá trị khác của A1 và A2 sẽ chọn các cảng khác hoặc thanh ghi điều khiển trong thiết bị. Các cảng trong A40 là 2A, 2B, 2C chúng đều có địa chỉ chẵn. - A35 8255A chứa các cảng 1A, 1B, 1C được kích hoạt bởi O4 (đầu ra của bộ giải mã 3625). Nếu A3 - A15 cao và BHE thấp. Nếu 8255A được kích hoạt cho đọc hoặc viết thì A0 cao. A1 = 1, A2 = 0 sẽ chọn cảng 1A trong 8255A có địa chỉ FFF9H cổng 1B có địa chỉ FFFBH, 1C là FFFDH và thanh ghi điều khiển bên trong FFFFH. Khi 8086 nhận một giá trị 16 bit (trong 1 thao tác) như MOV DX, FFF8H và IN AX, DX thì A0 và BHE thấp, đầu ra của 3625 O3 và O4 thấp nó sẽ kích hoạt cả 2 thiết bị A40 và A35. Byte dữ liệu trên cảng 2A đi vào 8086 trên các đường dữ liệu thấp, dữ liệu trên cảng 1A đi vào 8086 trên đường dữ liệu cao. _____________________________________________________________________ Chương 8 8086 Interrupts and Interrupt Application Chúng ta khai báo 1 segment tên DATA cho dữ liệu chương trình sử dụng. Từ 'WORD' trong câu khai báo bảo cho vị trí liên kết tới vị trí của segment này trên địa chỉ chẵn đầu tiên có thể dùng được. 'PUBLIC' trong câu khai báo cho linker biết rằng segment này có thể là được kết nối cùng nhau với segment của tên tương tự từ module khác. Giá trị đầu vào là Word, vì vậy chúng ta sử dụng chỉ thị DW để khai báo 4 giá trị. Giá trị Scale sẽ là kiểu byte vì vậy sử dụng chỉ thị DB để đặt riêng r 4 vị trí cho chúng. Như chương trình thực hiện kết quả sẽ được viết vào các vị trí này. SCALE_FACTOR DB 09H đặt riêng 1 vị trí byte cho con số mà chúng ta muốn chia. Phần của phản ứng (đáp ứng, phục vụ) interrupt 8086 là cần thiết gọi xa tới thủ tục phục vụ ngắt. Trong tất cả các chương trình mà gọi 1 thủ tục, chúng ta phải đặt 1 STACK để nắm giữ địa chỉ trả về và tham số truyền tới và từ thủ tục. Phần tiếp theo của chương trình khai báo 1 STACK SEGMENT gọi là STACK_SEGMENT. Nó cũng thiếp lập 1 con trỏ trỏ tới vị tiếp theo bên trên stack với câu lệnh TOP_STACK LABEL WORD. Hai phần tiếp theo của chương trình là cần thiết bởi vì chúng ta viết 1 chương trình chính và thủ tục phục vụ ngắt như là 2 module riêng biết. Khi ASSEMBLER đọc qua 1 chương trình nguồn. Nó làm 1 bảng ký hiệu mà chứa đựng SEGMENT và OFFSET của mỗi ký tự của tên và nhãn sử dụng trong chương trình. Câu lệnh PUBLIC BAD_DIV_FLAG bảo cho ASSEMBLER nhận biết tên BAD_DIV_FLAG như dùng 7 chung. Nghĩa ở đây là khi module đối tượng của chương trình này được két nối với 1 vài module khác mà câu lệnh khai báo BAD_DIV_FLAG kahi báo là EXTRN, chương trình linker sẽ cho phép để làm kết nối. Câu lệnh INT_PROC SEGMENT WORD PUBLIC và INT_PROC ENDS bảo cho ASSEMBLER biết BAD_DIV được định nghĩa trong 1 SEGMENT tên INT_PROC khi ASSEMBLER đọc những câu lệnh này, nó sẽ làm 1 lối vào trong như bảng ký hiệu cho BAD_DIV và nhận diện 1 nó như bên ngoài. Khi module đối tượng cho chương trình được link với module đối tượng cho chương trình nới có BAD_DIV được định nghĩa, linker sẽ lấp đầy giá trị cho CS và IP của BAD_DIV. Lệnh thực tế của chương trình chính : Chúng ta khai báo 1 CODE SEGMENT WORD PUBLIC. Tại phần đầu của CODE SEGMENT chúng ta sử dụng câu khai báo ASSUME để bảo cho ASSEMBLER phân đoạn logic gì (What logical segment) để sử dụng cho mã, cho dữ liệu, và cho stack. Sau đó khởi tạo giá trị cho thanh ghi SS, SP, DS. 4 lệnh tiếp theo nạp địa chỉ của thủ tục phục vụ ngắt BAD_DIV trong vị trí kiểu 0 của bảng vecter ngắt. Chúng ta nạp ES với 0000 vì vậy chúng ta có thể sử dụng nó như 1 segment tưởng tượng tại địa chỉ 00000H. Sau đó chúng ta sử dụng câu lệnh MOV WORD PTR ES:0000, OFFSET BAD_DIV để nạp OFFSET của thủ tục phục vụ ngắt trong bộ nhớ tại 00000H và 00001H. Câu lệnh MOV WORD PTR ES:0002H, SEG BAD_DIV sử dụng để nạp địa chỉ cơ sở SEGMENT của BAD_DIV vào bộ nhớ tại 00002H và 00003H. Nó cần thiết lập để nạp địa chỉ thủ tục ngắt trong trường hợp này. MOV SI, OFFSET INPUT_VALUES : Chúng ta khởi tạo SI như là 1 con trỏ trỏ tới giá trị vào đầu tiên và MOV BX, OFFSET SCALES_VALUES khởi tạo BX như 1 con trỏ tới đầu tiên của vị trí. Chúng ta đặt riêng ra cho kết quả SCALE 8 bit. CX khởi tạo biến đếm. Cuối cùng câu lệnh MOV AX, [SI] copy giá trị đầu vào từ bộ nhớ tới thanh ghi AX nơi nó thực hiện phép chia. DIV SCALE_FACTOR sẽ thực hiện phép chia số trong AX bởi 09H. 8bit thương của phép chia này được đặt trong AL và 8 bit còn lại được đặt trong AH. Nếu thương này quá lớn để thích hợp trong AL thì 8086 sẽ tự động thực hiện 1 ngắt 0. Chương trình chúng ta ở đây 8086 push cờ vào stack, đặt lại IF và TF và đẩy địa chỉ trở về trên stack. Nó sẽ nhảy tới địa chỉ 00000H và 00002H để nhận giá trị IP và CS cho bắt đầu của BAD_DIV. Thủ tục của chúng ta sẽ viết để phục vụ ngắt 0. Nó sẽ thực hiện thủ tục BAD_DIV. Thủ tục BAD_DIV làm như thế nào. Thủ tục BAD_DIV đắt đàu bằng cho phép MASM biết rằng tên BAD_DIV_FLAG mô tả biến của kiểu byte và biến là được định nghĩa trong SEGMENT gọi là DATA trong module ASM khác. 8 Tiếp theo chúng ta khai báo phân đoạn logic gọi là INT_PROC. Chúng ta có thể đặt thủ tục này trong phân đoạn CODE với chương trình chính. Tuy nhiên trong chương trình chính hệ thống nơi có nhiều thủ tục phục vụ ngắt, một phân đoạn tách biệt thường đặt ro ràng cho chúng. Câu lệnh BAD_DIV PROC FAR nhận biết bắt đầu thực tế của thủ tục và bảo ASM cả 2 giá trị CS và IP cho thủ tục này cất giữ. Bây giờ bước thực hiện quan trọng để làm tại điểm bắt đầu của bất kỳ thủ tục phục vụ ngắt nào là đẩy vào stack tất cả các thanh ghi được sử dụng trong thủ tục. Bạn có thể hồi phục các thanh ghi này bằng các POP chúng ra khỏi stack trước khi chúng quay về chương trình gọi ngắt. Chương trình gọi ngắt sẽ lấy lại các thanh ghi. Chúng ta lưu AX và DS, khi đó chúng ta sử dụng tương tự phân đoạn dữ liệu DATA. Trong chương trình chính và trong thủ tục ta có thể hỏi tại sao chúng tại lại ghi DS. Con trỏ mà 1 thủ tục phục vụ ngắt nên được viết viết vì vậy nó có thể sử dụng tại bất kỳ điểm nào trong 1 chương trình. Bằng cách lưu giá trị DS cho chương trình ngắt, thủ tục phục vụ ngắt này có thể được sử dung phần chương trình mà không sử dụng DATA như phân đoạn DATA. Câu lệnh ASSUME bảo cho ASM tên của phân đoạn để sử dụng như phân đoạn dữ liệu, nhưng nhớ rằng nó không nạp thanh ghi DS với 1 giá trị cho sự bắt đầu của phân đoạn. Lệnh MOV AX, DATA và MOV DS, AX làm việc này trong thủ của chúng ta. Cuối cùng chúng ta nhận đầy đủ con trỏ của thủ tục này với lệnh MOV BAD_DIV_FLAG, 01. Trong lệnh đơn giản này bit cuổi cùng quan trọng của vị trí bộ nhớ, chúng ta đặt rõ ràng với chỉ thị DB tại đầu chương trình chính. Chú ý rằng trong thủ tục để truy nhập biến này bằng tên ta phải cho ASM biết rằng nó là ở bên ngoài và bạn phải làm cho chắc chắn rằng thanh ghi DS chứa đựng phân đoạn cơ sở cho segment trong vị trí BAD_DIV_FLAG được đặt. Ðể hoàn thành thủ tục chúng ta lấy các thanh ghi được lưu trong STACK và trở về chương trình gọi ngắt. Câu lệnh IRET lấy ra các thanh ghi cờ và quay về địa chỉ của stack. Chú ý trong chương trình mà chỉ thị phải được đóng lại với ENDP và phân đoạn phải như được đóng thường xuyên với 1 chỉ thị ENDS. Bây giờ xem lại trong chương trình chính để. Ngay sau lệnh DIV, chương trình sẽ kiểm tra xem nếu BAG_DIV_FLAG là đặt bởi so sánh với 01. Nếu BAD_DIV_FLAG không được đặt bởi thủ tục (tức là không xảy ra ngắt 0), sau đó 1 lệnh nhảy tới lệnh MOV [BX], AL. Lệnh này copy kết quả của phép chia trong AL tới vị trí bộ nhớ trong SCALED_VALUES được trỏ bởi BX. Nếu BAD_DIV_FLAG được đặt bởi ngắt 0 thì 0 sẽ được đặt vào vị trí bộ nhớ trong SCALE_VALUES và 1 lệnh nhảy tới lệnh MOV BAD_DIV_FLAG, 00 sẽ đặt lại BAD_DIV_FLAG. Ngắt 8086 có thể tới bằng 3 nguồn. 9 - Thứ nhất : Là một tín hiệu bên ngoài tới chân Nonmaskable Interrupt (NMI) hoặc Interrupt (INTR) chúng được gọi là ngắt cứng. - Thứ 2 : Sự thực hiện của một lệnh Interrupt như INT. Ðược gọi là ngắt mềm. - Thứ 3 : Một vài lỗi điều kiện sản sinh bởi 8086 bằng việc thực thi một lệnh. Ví dụ lỗi chia không divide-by-zero. Nếu bạn thứ chia 1 số cho 0 8086 sẽ tự động ngắt sự thực thi chương trình hiện thời. Khi một ngắt xảy ra 8086 sẽ thực hiện các bước sau : 1- Nó giảm con trỏ stack đi 2 và push thanh ghi cờ vào stack 2- Nó vô hiệu hoá đầu vào INTR của 8086 bằng cách xoá cờ ngắt (IF) trong thanh ghi cờ. 3- Nó đặt lại cờ bẫy (TF) trong thanh ghi cờ 4- Nó giảm con trỏ stack đi 2 và đẩy nội dung thanh ghi mã (CS) hiện thời vào vào stack. 5- Nó giảm con trỏ stack đi 2 và đẩy nội dung thanh ghi con trỏ lệnh (IP) hiện thời vào stack. 6- Nó thực hiện nhay tới bắt đầu của thủ tục phục vụ ngắt. 10 . (NHỮNG HÌNH NÀY Ở TRONG SÁCH GIÁO KHOA. CHỈ CÓ Ở CHƯƠNG 7) Chương 7 8086 System Connections. Timing, and Troubleshooting Hình 7-1a.TRANG 164 Hình trên trình bày một sơ đồ khối đơn giản. cao. _____________________________________________________________________ Chương 8 8086 Interrupts and Interrupt Application Chúng ta khai báo 1 segment tên DATA cho dữ liệu chương trình sử dụng. Từ 'WORD' trong câu khai báo bảo cho vị trí liên kết tới. cho CS và IP của BAD_DIV. Lệnh thực tế của chương trình chính : Chúng ta khai báo 1 CODE SEGMENT WORD PUBLIC. Tại phần đầu của CODE SEGMENT chúng ta sử dụng câu khai báo ASSUME để bảo cho ASSEMBLER