Showing posts with label Pascal. Show all posts
Showing posts with label Pascal. Show all posts

Thursday, October 29, 2009

Ngôn ngữ lập trình Pascal

Pascal là một ngôn ngữ lập trình cho máy tính thuộc dạng mệnh lệnh, được Niklaus Wirth phát triển vào năm 1970 là ngôn ngữ đặc biệt thích hợp cho kiểu lập trình có cấu trúc.

Pascal dựa trên ngôn ngữ lập trình Algol và được đặt tên theo nhà toán học và triết học Blaise Pascal. Wirth đồng thời cũng xây dựng Modula-2 và Oberon, là những ngôn ngữ tương đồng với Pascal. Oberon cũng hỗ trợ kiểu lập trình hướng đối tượng.

Ban đầu, Pascal là một ngôn ngữ được hướng để dùng trong giảng dạy về lập trình có cấu trúc, và nhiều thế hệ sinh viên đã "vào đời" thông qua việc học Pascal như ngôn ngữ vỡ lòng trong các chương trình học đại cương. Nhiều biến thể của Pascal ngày nay vẫn còn được sử dụng khá phổ biến, cả trong giảng dạy lẫn trong công nghiệp phát triển phần mềm.

Phần lớn hệ điều hành Macintosh được viết bằng Pascal. Hệ sắp chữ TeX phổ biến được viết bằng một ngôn ngữ tên là Web là ngôn ngữ mà Donald Knuth đã vay mượn khá nhiều yếu tố từ Pascal.


Thực tế sử dụng
Trình biên dịch Pascal đầu tiên được thiết kế tại Zurich cho dòng máy tính CDC 6000, được viết và xây dựng tại Đại học Illinois dưới sự chỉ đạo của Donald B. Gillies cho loại máy tính PDP-11 và ngay từ lúc này đã có thể sinh ra mã máy trực tiếp.

Để nhanh chóng phổ biến rộng rãi ngôn ngữ này, một bộ công cụ chuyển mã được viết tại Zurich bao gồm một trình biên dịch sang "mã máy ảo" (hay dễ hiểu hơn, mã trung gian giữa mã máy và mã nguồn), và bộ giả lập cho loại mã này. Bộ công cụ này sau đó trở thành hệ thống giả (P-system). Mặc dù hệ thống này được phát triển nhằm tạo ra các trình biên dịch sinh mã máy trên ít nhất một hệ thống, nhưng kết quả đáng kể nhất chỉ là trình thông dịch cho hệ thống giả UCSD. Các trình thông dịch này được ký hiệu P1-P4, với P1 là phiên bản đầu tiên còn P4 là phiên bản cuối cùng.

IP Pascal là trình biên dịch của ngôn ngữ lập trình Pascal cho hệ điều hành Micropolis DOS nhưng ngay sau đó đã chuyển sang CP/M để chạy trên dòng máy Z80.

Đầu thập niên 1980, UCSD Pascal đã có phiên bản dành cho các máy Apple II và Apple III để có các phiên bản tương ứng thay thế trình thông dịch BASIC đi kèm với các loại máy này trong thời gian trước đó.

Trong những năm 1980, Anders Hejlsberg đã viết trình biên dịch Blue Label Pascal dành cho dòng máy tính Nascom-2. Sau đó ông chuyển sang làm việc cho hãng Borland và viết lại hoàn toàn trình biên dịch này để rồi trở thành Turbo Pascal cho máy tính IBM-PC. Trình biên dịch mới này bán với giá chỉ có $49.95, rẻ hơn nhiều so với giá Hejlsberg trước đây rao bán sản phẩm Blue Label Pascal.

Trình biên dịch giá rẻ của Borland đã gây ra ảnh hưởng lớn đến cộng đồng lập trình viên Pascal, họ hầu như tập trung hết vào lập trình cho máy IBM-PC trong những năm cuối thập niên 1980. Rất nhiều người cũng đã sử dụng sản phẩm này thay cho BASIC.

Super Pascal là một biến thể của Pascal, bổ sung nhãn không có số, trả lại biểu thức hay mệnh đề là tên của kiểu dữ liệu.

Trong phiên bản 5.5, Borland đã bổ sung phần lập trình hướng đối tượng vào Turbo Pascal.

Tuy nhiên sau đó Borland đã quyết định cần phải có nhiều tính năng hướng đối tượng tinh vi và phức tạp hơn, và đã bắt đầu sản phẩm Delphi, sử dụng sơ đồ thiết kế của Object Pascal do Apple đưa ra làm cơ sở. (Sơ đồ của Apple vẫn chưa phải là chuẩn.) Borland cũng gọi đây là Object Pascal trong phiên bản Delphi đầu tiên nhưng đổi tên thành Delphi trong các phiên bản sau đó. Các bổ sung chính so với các phần mở rộng lập trình hướng đối tượng trước là mô hình đối tượng, các hàm dựng và hàm hủy ảo, các thuộc tính đều mang tính tham chiếu. Có một vài trình biên dịch khác cũng hỗ trợ các tính năng này. Xem thêm: Delphi (ngôn ngữ lập trình).

Turbo Pascal và các sản phẩm tương tự, bằng các khái niệm đơn vị (unit) hay mô-đun (module) hình thành nên các ngôn ngữ lập trình cấu trúc. Turbo Pascal lấy các khái niệm này từ chuẩn của Extended Pascal hay từ người kế vị Modula-2. Mặc dù vậy nó vẫn không cung cấp khái niệm các mô-đun lồng nhau hay các kí hiệu rõ ràng về hàm nhập và hàm xuất.

Chuẩn hóa
Ngôn ngữ này được chuẩn hóa vào năm 1983 trong chuẩn ISO/IEC 7185, một vài chuẩn quốc gia cụ thể cũng được đưa ra bao gồm cả chuẩn ANSI/IEEE770X3.97-1983 của Mỹ. Năm 1990 chuẩn Pascal mở rộng được đưa ra với tên gọi ISO/IEC 10206.

Chuẩn ISO 7185 được phát triển với mục đích là sự chọn lọc của ngôn ngữ 1974 của Writh, được đề cập chi tiết trong cuốn "Hướng dẫn sử dụng và Báo cáo của Jensen và Wirth", bổ sung đáng kể nhất là "Các tham số mảng phù hợp" được coi là mức 1 của tiêu chuẩn, mức 0 là Pascal không có mảng phù hợp.

Trên các máy tính lớn mà Pascal xuất phát (mainframe và minicomputer), các tiêu chuẩn này thường được tuân theo. Tuy vậy trên IBM-PC thì ngược lại. Trên các máy tính IBM-PC, chuẩn của Turbo Pascal và Delphi của của Borland có lượng người dùng nhiều nhất. Do vậy, biết liệu một phiên bản riêng biệt tương ứng với ngôn ngữ Pascal ban đầu, hay ngôn ngữ riêng của Borland là khá quan trọng.

Các trình biên dịch phổ biến
Có vài trình biên dịch Pascal được đưa ra cho sử dụng công khai:

* Trình biên dịch P4, cơ sở cho rất nhiều trình biên dịch Pascal-được-viết-bằng-Pascal sau đó, bao gồm cả UCSD p-System.
* Free Pascal được viết bằng Pascal (sao cho nó có thể biên dịch được chính nó), được phát triển với mục tiêu là cung cấp một trình biên dịch mạnh mẽ và thuận tiện, có khả năng biên dịch cả các ứng dụng cũ lẫn phát triển ứng dụng mới. Được phân phối miễn phí dưới giấy phép GNU. Có khả năng trộn lẫn cả mã của Turbo Pascal và mã Delphi, hỗ trợ nhiều nền tảng lẫn nhiều hệ điều hành.
* Turbo Pascal là trình biên dịch Pascal thống trị cho PC vào thập niên 1980 và đầu thập niên 1990. Nó phổ biến vì các mở rộng mạnh mẽ và đặc biệt là thời gian biên dịch cực kì ngắn. Trong thời điểm hiện tại, các phiên bản cũ của Turbo Pascal (tới 5.5) có thể tải xuống miễn phí tại trang web của Borland (tuy nhiên vẫn cần phải đăng ký).
* Chrome là thế hệ Object Pascal tiếp theo cho nền tảng .NET và nền tảng Mono, được RemObjects Software cung cấp.
* GNU Pascal Compiler (GPC) là trình biên dịch Pascal của Bộ biên dịch GNU (GCC). Trình biên dịch này được viết bằng C, thư viện chạy hầu hết viết bằng Pascal. Được phân phối miễn phí dưới giấy phép GNU, có thể chạy trên rất nhiều nền tảng và hệ điều hành khác nhau. Nó còn hỗ trợ chuẩn ngôn ngữ ANSI/ISO và tương thích với ngôn ngữ Borland/Turbo Pascal. Việc hỗ trợ cho Borland Delphi và một vài biến thể khác vẫn còn khá hạn chế.
* Delphi là sản phẩm RAD (Rapid Application Development-phát triển ứng dụng tức thời) của Borland. Nó sử dụng Delphi, tiền thân từ Pascal, để tạo các chương trình ứng dụng cho nền Windows. Phiên bản mới nhất còn hỗ trợ cả việc biên dịch cho nền Microsoft .NET.
* Kylix là một nhánh sản phẩm khác kế thừa từ Pascal của Borland, tiền thân từ Delphi, hỗ trợ hệ điều hành Linux và một thư viện đối tượng đã được bổ sung. Trình biên dịch và môi trường phát triển (IDE) có thể được cung cấp cho việc sử dụng phi lợi nhuận. Trình biên dịch (không bao gồm thư viện hay IDE) được cho là trở thành phần mềm Mã nguồn mở trong thời gian tới.
* Dr. Pascal là một trình thông dịch chạy Standard Pascal. Bổ sung đáng kể nhất là chế độ "thực thi nhìn thấy được" cho phép hiển thị chương trình đang chạy cùng với các biến của nó, và cả quá trình kiểm tra lỗi khi thực thi (runtime error checking). Trình thông dịch này không tạo ra được file thực thi nhị phân riêng rẽ, chạy trên nền MS-DOS, hoặc cửa sổ DOS trong nền Windows, và cả trên dòng máy Macintosh cũ.
* Virtual Pascal được Vitaly Miryanov sáng tạo như một trình biên dịch dành cho OS/2 tương thích với cú pháp của Borland Pascal. Sau đó nó được fPrint phát triển thành sản phẩm thương mại, hỗ trợ thêm Win32, và đến năm 2000 trở thành phần mềm miễn phí. Ngày nay nó có thể biên dịch cho Win32, OS/2 và cả Linux, và gần như hoàn toàn tương thích với Borland Pascal và Delphi.
* IP Pascal ban đầu là ngôn ngữ Pascal dành cho Z80/CP/M, rồi được chuyển sang và viết lại cho Intel 80386/PC. IP Pascal có một thư viện khả chuyển (portability library). Ví dụ, một chương trình hiển thị văn bản viết bằng Pascal chuẩn từ thập niên 1970 có thể được biên dịch lại để làm việc trong một cửa sổ và thậm chí có cả việc tạo dựng đồ họa. IP Pascal hỗ trợ chuẩn ISO 7185 và nâng cấp ngôn ngữ một cách logic. Ví dụ, Pascal chuẩn hỗ trợ các xâu ký tự được "căn lề phải" và sau đó còn hỗ trợ xâu ký tự động. Mảng tĩnh của Pascal chuẩn được nâng thành mảng động nhưng vẫn hoàn toàn tương thích ngược với mảng tĩnh, v.v.
* Pocket Studio là một tập nhỏ các trình biên dịch Pascal và RAD hướng tới Palm/MC68xxx với một số mở rộng hỗ trợ giao tiếp với API (Application Programming Interface-giao tiếp lập trình ứng dụng) của hệ điều hành Palm OS.
* Lazarus là môi trường phát triển tức thời trực quan đa nền tảng. Lazarus sử dụng trình biên dịch Free Pascal.

Bạn có thể tìm thấy một danh sách lớn nữa tại Pascaland. Trang web này viết bằng tiếng Pháp, nhưng về cơ bản chỉ là một danh sách gồm các địa chỉ mạng (URL) tới các trình biên dịch, do vậy không ảnh hưởng nhiều. Bạn cũng có thể ghé thăm Pascal Central, một trang web chính về thông tin và hỗ trợ cho Pascal dành cho máy Mac, với rất nhiều bộ sưu tập về các bài báo, cộng với liên kết tới rất nhiều trình biên dịch và hướng dẫn khác.

Nguồn wikipedia

Lập trình Pascal
Mọi chương trình Pascal bắt đầu bằng từ khóa "Program", cùng với một danh sách tùy chọn các phần mô tả các tập tin ngoài và sau đó là một khối các dòng lệnh nằm giữa các từ khóa "Begin" và "End". Dấu chấm phẩy dùng để tách các dòng lệnh khác nhau, và dấu chấm để báo hiệu kết thúc chương trình (hay đơn vị). Trong mã nguồn Pascal, không phân biệt chữ viết hoa.
  1. program ChaoThegioi(output);
  2. begin
  3. writeln('Chao The gioi!')
  4. end.
Pascal, nguyên thể đơn thuần là ngôn ngữ dạng thủ tục với một loạt các từ khóa chuẩn if, while, for, và các thành phần khác.
Pascal cũng là một ngôn ngữ lập trình có cấu trúc, nghĩa là chuỗi điều khiển được cấu trúc thành các câu lệnh chuẩn, hạn chế tối đa các lệnh 'go to' chuyển hướng lung tung trong cấu trúc chương trình.
  1. while a <> b do WriteLn('Xin cho*`');
  2. if a > b then
  3. writeln('Tho?a man~ ddie^`u kie^.n')
  4. else
  5. writeln('Kho^ng tho?a man~ ddie^`u kie^.n');
  6. for i := 1 to 10 do writeln('La(.p: ', i:1);
  7. repeat a := a + 1 until a = 10;
Pascal cấu trúc các chương trình thành các thủ tục và hàm.
  1. program mine(output);
  2. procedure print(var i: integer);
  3. function next(i: integer): integer;
  4. begin
  5. next := i + 1
  6. end;
  7. begin
  8. writeln('To^?ng la`: ', i);
  9. i := next(i)
  10. end;
  11. begin
  12. i := 1;
  13. while i <= 10 do print(i)
  14. end.
Các thủ tục và hàm có thể lồng vào nhau theo nhiều cấp, và từ 'program' là khối cấu trúc ngoài cùng nhất.
Mỗi khối có thể có có khai báo các nhãn goto, hằng, kiểu, biến, cùng với các thủ tục và hàm riêng, tất cả phải tuân theo trình tự đó.
Pascal có các kiểu đơn như interger (số nguyên), character (ký tự), và boolean (lô gích), v.v. và enumerations (liệt kê), là kiểu mới được cho vào Pascal sau này.
  1. program myprog;
  2. var
  3. a: integer;
  4. b: char;
  5. c: boolean;
  6. d: (mot, hai, ba, bon, nam);
Có thể tạo ra bất kỳ "kiểu con" nào từ các kiểu trên.
  1. var
  2. x: 1..10;
  3. y: 'a'..'z';
  4. z: hai..bon;
Các kiểu có thể được tạo ra từ các kiểu khác bằng cách khai báo kiểu.
  1. program myotherprog;
  2. type
  3. x = integer;
  4. y = x;
  5. ...
Hơn thế nữa, các kiểu phức có thể được xây dựng từ các kiểu đơn:
  1. type
  2. a = array [1..10] of integer;
  3. b = record
  4. a: integer;
  5. b: char
  6. end;
  7. c = file of a;
Các chuỗi ký tự là các dãy kết hợp bắt đầu bằng một chỉ số nguyên là 1.
  1. Pascal cũng hỗ trợ dùng [[con trỏ]]:
  2. type
  3. a = ^b;
  4. b = record
  5. a: integer;
  6. b: char;
  7. c: a
  8. end;
  9. var
  10. pb : a
Ở đây biến pb là một con trỏ đến kiểu dữ liệu b, là một record. Để tạo record mới và gán các giá trị 10A vào các trường ab trong record, có thể dùng các câu lệnh sau:
  1. new(pb);
  2. pb^.a := 10;
  3. pb^.b := 'A';
  4. pb^.c := nil;
  5. ...
Danh sách liên kết cũng có thể được tạo ra bằng cách cho một trường kiểu con trỏ (c) vào trong record

Blaise Pascal (1623 - 1662) thần đồng Toán học

Blaise Pascal sinh tại Clermont Ferrand, miền Auvergne nước Pháp, ngày 19 tháng 6 năm 1623. Cha của Pascal, ông Etienne, trước kia là một luật gia tại thành phố Paris và vào lúc Pascal chào đời, ông là chánh án tòa Hộ tại Clermont. Khi Pascal lên 3 tuổi, bà mẹ Antoinnette Bégan từ trần, để lại cho chồng 3 người con là Gilberte, Blaise và Jacqueline lúc đó đều còn quá nhỏ.
Ngay từ khi mới tập nói, Pascal đã tỏ ra là một đứa trẻ có năng khiếu khác thường. Lớn lên, Pascal thường hỏi người lớn những câu hỏi hắc búa và cậu cũng trả lời được những câu hỏi thật khó giải đáp. Những điều này làm cho ông Etienne tin tưởng rằng con của ông là một thiên tài, vì vậy ông quyết định lấy cách giáo dục con. Nguyên tắc của ông là luôn luôn khiến cho đứa trẻ làm các việc khó khăn hơn, tiến bộ hơn.

Vào năm 1631, ông Etienne nhường chức vụ của mình cho người khác rồi dọn nhà lên thành phố Paris để chăm sóc sự học vấn của con. Ông tự đảm trách việc giáo huấn và vì vậy, Pascal không có thầy giáo nào khác ngoài người cha thân yêu tài ba. Cậu được dạy cách quan sát, suy tưởng và thường học được những kiến thức qua các cuộc đàm luận với cha. Khởi đầu, ông Etienne quyết định dạy con tiếng La Tinh và Hy Lạp cho đến năm 12 tuổi, tuy nhiên trong các thời giờ nhàn rỗi, ông Etienne cũng kể cho con trai nghe các câu chuyện về Khoa Học nhưng những điều này không bao giờ làm cho Pascal thỏa mãn, cậu luôn luôn khao khát những lý lẽ cuối cùng của sự vật.
Máy tính Pascaline, 6 số
Vì muốn con chuyên tâm về tiếng La Tinh và Hy Lạp là hai ngôn ngữ rất khó học, nên ông Etienne đã cất dấu tất cả những sách về Khoa Học và Toán Học. Nhưng rồi một hôm, khi bước vào phòng, ông thấy con trai đang loay hoay dùng phấn chứng minh trên nền nhà định luật thứ nhất trong 32 định luật của Euclide. Sau khi nghe con thuật lại cách chứng minh, ông Etienne đã phải bỏ nhà, chạy sang nhà ông hàng xóm Le Pailleur để "khóc lên vì sung sướng".

Xưa nay, ông Etienne chưa từng dạy cho con học Toán bao giờ, vả lại định luật của Euclide đó là một bài toán rất khó đối với người lớn, không phải dành cho trẻ em 12 tuổi. Pascal đã chứng minh được rằng tổng số các góc trong một tam giác bằng hai góc vuông, đúng như Euclide đã từng phát biểu. Cũng vì chưa từng học Hình Học, Pascal đã gọi đường tròn là "cái tròn" (un rond), đường thẳng là "cái thước kẻ" (une barre). Từ đây, Pascal mới được cha cho phép đọc các cuốn khái luận của Euclide. Do trí thông minh sẵn có, Pascal đọc tới đâu, hiểu tới đó mà không cần một ai giảng giải. Cậu còn giải được nhiều bài toán khó. Sự tự tìm hiểu do ý thích đã khiến Pascal chẳng bao lâu trở thành một nhà toán học có hạng.
Thời bấy giờ, ông Etienne thường gặp gỡ nhiều nhân vật danh tiếng về Khoa Học nên Pascal cũng được tham dự vào các buổi hội thảo, cậu được làm quen với Cha Mersenne là một nhà bác học thời đó, cũng như với những nhà khoa học danh tiếng khác, chẳng hạn như Desargues, Fermat, Roberval. Tại các buổi họp này, Pascal đã góp ý kiến về các tư tưởng, các lý luận, các lời phê phán những tác phẩm của các nhà bác học đương thời. Cậu cũng trình bày những điều do mình khám phá.

Theo phương pháp Hình Học của Desargues, Pascal đã hoàn thành cuốn "Khảo Sát về Thiết Diện Côníc" (Traité des sections coniques, 1640) khi chưa tới 16 tuổi. Tác phẩm này bao gồm các công trình của Apollonius, nhưng đã được Pascal tự tìm ra và lại chứng minh bằng một phương pháp luận lý vừa đơn giản hơn, vừa tổng quát hơn. Tác phẩm của Pascal đã khiến rất nhiều nhà toán học tài ba đương thời phải khâm phục, kể cả Cha Mersenne và Descartes, và ai cũng đồng ý rằng cuốn sách đó xứng đáng là công trình của một bậc thầy chứ không phải là của một thiếu niên chưa đủ 16 tuổi. Nhiều người đã thúc dục Pascal đưa in tác phẩm nhưng do lòng khiêm tốn, cậu đã từ chối vì vậy ngày ngay người ta chỉ còn lưu giữ được hai cuốn sách đầu tay của nhà thiên tài toán học Pascal.

Năm 1638, khi chính phủ Pháp ra lệnh giảm bớt lợi tức của Tòa Đô Chính Paris, một nhóm người đã đứng lên phản đối trong đó có người cha của Pascal. Vì vậy ông Etienne bị Thủ Tướng Richelieu cho người theo dõi và phải trốn về miền Auvergne. Lúc bấy giờ, Pascal 15 tuổi và cô em gái Jacqueline 13. Giống như anh trai, Jacqueline cũng nổi tiếng là một thần đồng về thơ văn. Khi lên 11 tuổi, Jacqueline đã sáng tác được một kịch thơ 5 hồi và tác phẩm thơ này đã được giới văn nghệ Paris ưa chuộng. Rất nhiều người và ngay cả Thi Hào Corneille đều ưa thích đọc thơ của Jacqueline.

Nhờ tài năng về Thơ Phú, Jacqueline được phép đóng kịch trước Hồng Y Giáo Chủ Richelieu. Vị Thủ Tướng này đã không tiếc lời khen ngợi cô bé và hỏi thăm về gia cảnh. Nhân lúc này, Jacqueline liền ngâm một bài thơ xin ân xá cho cha và Thủ Tướng đã nhận lời. Ông Etienne nhờ vậy được phép trở lại Paris và lại được cử giữ chức vụ Giám Đốc Thuế Vụ miền Rouen. Nhưng trách nhiệm này làm ông Etienne mệt mỏi vì sổ sách kế toán quá nhiều. Để giúp đỡ cha, Pascal đã sáng chế ra một chiếc máy tính mà nguyên tắc của nó còn được áp dụng cho các loại máy tính tối tân ngày nay. Phát minh này đã làm dang tiếng của Pascal vang lừng.

Vào các năm trước, gia đình Pascal tuy ngoan đạo nhưng tôn giáo chưa được coi là quan trọng cho tới năm 1646, dòng tu khổ hạnh (Jansenism) của Cơ Đốc Giáo đã ảnh hưởng tới vùng Pascal cư ngụ. Đây là nhóm tôn giáo chủ trương do ông Cornelis Jansen, một giáo sư thần học gốc Hòa Lan, sống tại Louvain. Các niềm tin của giáo phái này khác hẳn với các lời rao giảng của các giáo sĩ Dòng Tên (the Jesuites). Ông Etienne Pascal, do không ưa thích tôn giáo, nên đã mang gia đình dọn lên thành phố Paris. Tới khi ông Etienne qua đời vào năm 1651, cô em gái Jacqueline của Pascal liền vào nhà tu tại Port Royal. Do ảnh hưởng này, Pascal đã để tâm tới tôn giáo cũng như tới các vấn đề thần học.

Cũng vào năm biết tới dòng tu Khổ Hạnh, Pascal đã thực hiện lại các thí nghiệm của Torricelli và phổ biến các điều khám phá của mình trong tác phẩm "Các thí nghiệm mới liên quan tới khoảng chân không" (Nouvelles expériences touchant le vide, 1647). Pascal đã dựa vào thí nghiệm rồi dùng lý luận, đánh đổ các quan niệm cổ xưa của Aristotle về chân không và ông cũng đưa ra những khám phá mới về áp suất không khí. Pascal đã tìm thấy kết luận rằng càng lên cao, áp suất của không khí càng giảm đi. Để kiểm chứng điều này, Pascal đã nhờ người anh rể là Florin Perier lên ngọn núi Puy-de-Dome thực hiện nhiều thí nghiệm cần thiết. Các kết quả của Perier đã xác nhận lời tiên đoán của Pascal. Do khám phá này của Pascal, các nhà khoa học đã chế tạo được các phong vũ biểu và các cao độ kế.

Trong khi nghiên cứu các thí nghiệm của Torricelli, Pascal còn tìm cách tổng quát hóa những ý niệm về chất lỏng. Ông đã thiết lập nhiều định luật về áp suất của chất lỏng để rồi phổ biến qua tác phẩm :"Khảo sát sự cân bằng chất lỏng" (Traité de l 'équilibre des liqueurs). Cuốn sách này được hoàn thành vào năm 1651 nhưng mãi tới năm 1663 mới được xuất bản và căn cứ vào đó, nhiều nhà khoa học đã coi Pascal là một trong những người sáng lập ra môn Thủy Động Học (Hydrodynamics).

Sau khi người cha thân yêu qua đời, Pascal không chuyên tâm nhiều vào việc khảo cứu khoa học. Ông thường giao du với nhiều người, nhất là Hầu Tước trẻ tuổi De Roannez và Hiệp Sĩ De Mere. Chính trong thời kỳ này, ông đã chuyên đọc về Epictète và Montaigne. Do sự đi lại với De Mere, Pascal đã lưu tâm tới lý thuyết toán học của cách đánh bài. Ông bắt đầu nghiên cứu phép tính Sác Xuất (Probability) rồi vào năm 1654, đã phổ biến các kết quả qua các bức thư viết cho Fermat và qua cuốn "Khảo Sát về Tam Giác Số Học" (Traité du triangle arithmétique).

Cũng vào năm 1654, Pascal tới Port Royal thăm cô em gái Jacqueline đang sống trong tu viện. Cuộc đi thăm này khiến cho Pascal cảm thấy "ghê tởm cực độ các sự giả dối của đời người". Sự bất toại nguyện càng tăng thêm cho tới khi "đêm lửa" xẩy đến, làm thay đổi hẳn cuộc sống cũ của Pascal. Chính vào đêm 23 tháng 11 năm 1654 đó, trong khi đang khảo cứu Toán Học, Pascal cảm thấy như được đối thoại cùng Thượng Đế trong hai tiếng đồng hồ. Pascal thấy mình đã nhận lãnh một chức vụ thiêng liêng, rồi vì quá xúc động, ông nguyện hiến cả đời mình cho Thượng Đế và quyết tâm làm tỏ đức tin nơi Đấng Chí Tôn.

Vào năm 1655, Antoine Arnauld, nhà thần học chính thức của Port Royal bị các nhà thần học Sorbone kết án, nhất là về lối tu khổ hạnh (Jansenism) đối với Chúa Cứu Thế. Có lẽ do chính Arnauld khuyến dụ, Pascal đã viết ra các bức thư Provinciales. Lối hành văn cũng như cách tranh luận của Pascal qua tác phẩm này đã quyến rũ được dân chúng Paris, nhất là trong khoảng thời gian từ tháng Giêng năm 1656 tới tháng 4 năm 1657. Khi sống tại Port Royal, Pascal được mời viết cho nhà trường các bài giảng về Hình Học, có lẽ vì lý do này, Pascal đã viết nên cuốn "Phương Pháp chứng minh Hình Học" (On Geometrial Demonstrations).

Thời còn thơ ấu, thể chất của Pascal rất mỏng manh, nên khi lớn lên, tình trạng sức khỏe của ông cũng không được khá. Vào năm 1658, Pascal lại bị chứng đau răng hành hạ và vì muốn tìm quên nỗi đau nhức, Pascal quay ra làm Toán. Ông nghiên cứu hình học Cycloide, là thứ hình học đang được Roberval và các nhà toán học đương thời khảo sát. Pascal đã tìm ra được nhiều tính chất quan trọng nhưng vì muốn chứng tỏ các điều khám phá của mình có thể giải đáp được nhiều bài toán hắc búa, Pascal đề nghị một cuộc thách đố vói các nhà toán học. Nhiều người đã nhận lời trong đó có Wallis và Laouère, nhưng rồi chỉ có Pascal cho ra các kết quả hoàn toàn.

Càng về cuối đời, Pascal càng sống khổ hạnh. Sau khi đứa cháu của ông được cứu khỏi tại Port Royal và được mọi người coi là một sự huyền diệu, Pascal chuyên tâm đọc sách và kiếm tài liệu để viết nên cuốn sách "Biện hộ cho Thiên Chúa Giáo" (Apology for the Christian Religion) mà sau này, tác phẩm đó được phổ biến sau khi ông qua đời dưới tên là "Tư Tưởng" (Pensées).

Tháng 6 năm 1662, Pascal đem nốt căn nhà ở tặng cho một gia đình nghèo đang mắc bệnh đậu mùa. Ông dọn tới ở nhờ người chị gái Gilberte. Tại nơi này, Pascal bị ốm nặng và cơn bệnh còn hành hạ ông trong hai tháng. Pascal qua đời vào ngày 19 tháng 8 năm đó, hưởng thọ 39 tuổi.

Năm 1962, cả nước Pháp đã làm lễ kỷ niệm 300 năm ngày húy kỵ của Blaise Pascal, nhà bác học kiêm triết gia kiêm văn sĩ. Để ghi nhớ bậc Vĩ Nhân Khoa Học này, người ta đã phát hành tem thư, tổ chức các buổi thuyết trình về Triết Học, Toán Học và Văn Chương. Nhiều phòng triển lãm đã trưng bày các tác phẩm của Pascal cùng chiếc máy tính, phát minh lừng danh của ông. Qua các bài diễn văn, các Viện Sĩ Louis de Broglie, Francois Mauriac. đã ca ngợi Blaise Pascal là một thiên tài của Nhân Loại, đã mang cả cuộc đời phụng sự cho Khoa Học và Triết Học.

Nguồn (http://vietsciences.free.fr)

Tuesday, October 27, 2009

Đưa biểu tượng chương trình vào Systray Bằng Delphi

Bài viết này sẽ hướng dẫn bạn cách dùng hàm API để đưa biểu tượng chương trình vào systray (khay hệ thống nơi chứa chiếc đồng hồ trên thanh Taskbar). Chương trình viết bằng Delphi 6.0, có mã nguồn đi kèm

1. Tạo giao diện

- Bạn mở 1 Project mới, và thiết kế 1 Form như hình dưới đây

- Bạn thiết kế PopupMenu1 như hình dưới đây

2. Viết Code

- Bạn mở cửa sổ Code ra (bấm F12) trong phần Uses của Unit1 bạn khai báo thêm 2 Units sau:

uses Registry, ShellAPI.

- Trong phần Type bạn khai báo thêm 1 kiểu dữ liệu kiểu bản ghi như sau:

type
//Cấu trúc NOTIFYICONDATA
NOTIFYICONDATA = record
cbSize:WORD;
hWnd:HWND;
uID,uFlags,uCallbackMessage: UINT;
hIcon:HICON;
szTip:array[0..63]of char;
end;

- Trong phần Var khai báo thêm 2 biến như sau:

var
//Biến toàn cục kiểu NOTIFYICONDATA
pnid: NOTIFYICONDATA;
//Biến dùng để chứa vị trí Mouse
MousePos: TPoint;

- Trong phần Implementation khai báo hàm API như sau

implementation

{$R *.dfm}

//Hàm API phục vụ việc đưa biểu tượng chương trình vào systray
Function Shell_NotifyIconA (dwMessage:Longint;var pnid: NOTIFYICONDATA): Boolean;stdcall;External 'shell32';

- Bạn mở giao diện ra (bấm F12), click đúp vào khoảng trống của Form1, khi đó cửa sổ Code sẽ hiện ra và cho ta 1 thủ tục mẫu có dạng

procedure TForm1.FormCreate(Sender: TObject);

begin

end;

thủ tục này sẽ được thực thi khi Form được tạo ra (ngay khi chạy chương trình)

Bạn thay thế nó bằng đoạn Code dưới đây, để có được một thủ tục hoàn chỉnh như sau

procedure TForm1.FormCreate(Sender: TObject);
begin
//Khởi tạo các thông số cho cấu trúc NOTIFYICONDATA
//Kích thước cấu trúc NOTIFYICONDATA
pnid.cbSize :=sizeof(pnid);
pnid.uID := 1;
//Handle của icon cần hiển thị trên systray
pnid.hIcon := image1.Picture.Icon.Handle;
//Handle của cửa sổ mà hệ thống sẽ gửi các thông báo hệ thống (Message)
//thông qua icon trên systray
pnid.hWnd := form1.Handle;
//Thông báo (Mesage) mà hệ thống sẽ gửi cho cửa sổ chính
//thong qua icon trong systray, (sự kiện Mouse)
pnid.uCallbackMessage := WM_MOUSEMOVE;
pnid.uFlags :=NIF_ICON Or NIF_TIP Or NIF_MESSAGE;
//Dòng chữ hiện ra khi bạn di chuột vào icon trên systray
pnid.szTip := 'Friends2002';
end;

- Bạn lần lượt Click đúp vào các Button và nhập mã như sau

procedure TForm1.Button1Click(Sender: TObject);
begin
//Thực hiện đưa biểu tượng vào systray
Shell_NotifyIconA(NIM_ADD, pnid);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
//Xoá biểu tượng khỏi systray
Shell_NotifyIconA(NIM_DELETE, pnid);
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
//Thay đổi nội dung cấu trúc NOTIFYICONDATA
pnid.cbSize :=sizeof(pnid);
pnid.uID := 1;
//Thay đổi icon khác
pnid.hIcon := image2.Picture.Icon.Handle;
pnid.hWnd := form1.Handle;
pnid.uCallbackMessage := WM_MOUSEMOVE;
pnid.uFlags :=NIF_ICON Or NIF_TIP Or NIF_MESSAGE;
//Thay đổi Tip khác
pnid.szTip := 'Friends2002 (c) 2002 by Tran Trung';

//Thực hiện thay đổi biểu tượng trong systray và Tip
Shell_NotifyIconA(NIM_MODIFY, pnid);
end;

- Bạn chọn Form1 trong Commobox phía trên của cửa sổ ObjectInspector, sau đó chọn Tab Events, rồi click đúp vào cột bên phải của dòng OnClose, khi đó thủ tục sau sẽ tự động được tạo ra

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin

end;

Bạn nhập đoạn mã vào giữa cặp Begin .. end; để thủ tục đó như sau

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
//Xoá biểu tượng khỏi systray
Shell_NotifyIconA(NIM_DELETE, pnid);
end;

- Tiếp theo là thủ tục rất quan trọng, nó cho phép bạn gọi đến một thủ tục khác hoặc thi hành lệnh khi bạn click lên biểu tượng trên Systray

Bạn lại chọn Form1 trong Commobox phía trên của cửa sổ ObjectInspector, sau đó chọn Tab Events, rồi click đúp vào cột bên phải của dòng OnMouseMove, khi đó thủ tục đáp ứng sự kiện chuột di chuyển trên Form tự động được tạo ra, bạn nhập thêm mã vào giữa cặp Begin .. end; để nó có dạng như sau.

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,Y: Integer);
var Msg:Longint;
begin
msg:=X;
case Msg of
WM_RBUTTONUP: //Khi nút chuột phải nhả ra
begin
GetCursorPos(MousePos); //Lấy vị trí hiện tại của Mouse
popupmenu1.Popup(MousePos.X,MousePos.Y); //Mở menu popup
end;
WM_LBUTTONUP: //Khi nút chuột trái nhả ra
begin
if form1.Visible = false then form1.Show else form1.Hide ;
end;
end;

end;

- Bạn click đúp vào PopupMenu1 nằm trên cửa sổ giao diện, khi đó cửa sổ sau sẽ hiện ra

Bạn click đúp vào About, thủ tục đáp ứng sự kiện khi bạn chọn menu này sẽ hiện ra, bạn nhập mã như sau

procedure TForm1.About1Click(Sender: TObject);
begin
showmessage('Chuong trinh dua bieu tuong vao systray'+chr(13)+'(c)2002 by Tran Trung'+chr(13)+'E-mail: trantrung22@yahoo.com');
end;

Tương tự click đúp vào Exit và nhập mã như sau

procedure TForm1.Exit1Click(Sender: TObject);
begin
close;
end;

Monday, October 26, 2009

Lỗi Runtime error 200 trong Turbo Pascal 7.0

Như một số bạn sử dụng Borland Pascal 7.0 đã nhận xét trong số báo PCWorld tháng 3 năm 1999, với các bộ xử lý Intel Pentium Celeron, một số chương trình Pascal sau khi dịch và cho thực thi thì nhận được thông báo lỗi: Error 200: division by zero. Nếu đem đúng chương trình source cho dịch lại với Turbo Pascal 5.5 thì lại không có vấn đề gì xảy ra.

Điều khá đau lòng cho chúng ta là Borland, công ty tạo ra trình biên dịch nổi tiếng Turbo Pascal, sau một thời gian hoạt động thua lỗ đã quyết định đổi tên thành Inprise Inc. và bỏ rơi một số phần mềm của mình trong đó có Turbo Pascal. Version cuối cùng của Pascal do Borland đưa ra là 7.0. Việc cập nhật lên version mới hơn là điều không thực hiện được.

Là sinh viên của giai đoạn đầu thập kỷ 90, tôi đã khá viết khá nhiều chương trình bằng Turbo Pascal. Cách đây vài tháng, khi nâng cấp máy tính của mình lên Pentium Celeron 333, tôi đã nhận được thông báo lỗi tương tự như trên. Với một số bạn, nếu Turbo Pascal từ chối chạy với Celeron, viết lại chương trình bằng một ngôn ngữ khác có lẽ cũng chẳng thành vấn đề. Tuy nhiên, trong trường hợp của tôi, thời gian để dịch số source đã viết sang một ngôn ngữ khác như C hay C++ sẽ rất lớn. Chính vì vậy, tôi quyết định tìm hiểu nguyên nhân và cách khắc phục vấn đề trên. Trong bài viết này, xin chia sẻ kinh nghiệm của tôi cùng các bạn. Nếu không quan tâm tới nguyên nhân xâu xa của thông báo lỗi trên, bạn có thể bỏ qua mục Nguyên Nhân và đi thẳng tới phần Cách giải quyết.

Trái lại, nếu là người yêu thích ngôn ngữ Pascal và muốn đi sâu vào ngôn ngữ này, xin bỏ một chút thời gian cho mục Nguyên nhân, nơi mọi nguyên căn của vấn đề trên được trình bày.

Nguyên nhân

Trước hết, để có thể tìm được vị trí gây nên lỗi, chúng ta hãy dùng đoạn chương trình đơn giản sau:

Program Test;
Uses Crt;
Begin
Writeln('Hello');
End.

Rõ ràng, chương trình này chỉ viết chữ Hello lên màn hình. Khi các bạn chạy chương trình sẽ nhận được thông báo lỗi: Runtime error 200 at XXXX:0091. XXXX là địa chỉ segment gây lỗi, có thể khác với mỗi máy tùy theo các chương trình đã nạp trong bộ nhớ. 0091 là offset của đoạn mã lệnh gây nên lỗi.

Nếu bạn bỏ dòng thứ 2: Uses Crt thì chương trình lại chạy một cách "ngon lành". Sở dĩ chúng ta có thể bỏ dòng này là vì hàm writeln duy nhất dùng trong chương trình vừa thuộc unit SYSTEM ngầm định, vừa thuộc unit CRT. Trong trường hợp dùng lệnh Uses CRT, CRT.Writeln sẽ được gọi. Trái lại, SYSTEM.Writeln sẽ được sử dụng nếu bạn không viết Uses CRT. Vậy, lỗi có liên quan tới unit CRT.

Giữ nguyên dòng Uses CRT, và thêm dòng:

SYSTEM.writeln('System Hello')

vào trước dòng writeln('Hello'). Khi chạy chương trình, bạn cũng sẽ chẳng thấy dòng System Hello hiện ra, mà hệ thống vẫn đưa ra câu báo lỗi tương tự. Như vậy, phần mã gây lỗi nằm trước mã lệnh SYSTEM.Writeln(System Hello).

Từ 2 nhận xét trên, có thể phán đoán ngay phần mã gây lỗi là phần khởi động của unit CRT-phần được thực hiện đầu tiên khi chương trình Test được nạp vào bộ nhớ.

Nếu bạn dịch chương trình Test ra file EXE rồi tiến hành thi hành ngoài DOS thì sẽ nhận được thêm một chút thông tin về địa chỉ gây lỗi: Runtime error 200 at XXXX:0091. Error 200 theo Borland Pascal Help là lỗi Divide by zero (chia cho 0). Chương trình của chúng ta có cộng trừ nhân chia gì đâu mà gây nên lỗi này?

Như các bạn cũng biết, nếu dùng một unit nào đó, khi bắt đầu chạy chương trình, phần mã khởi động của Unit sẽ được thực hiện. Bằng cách sử dụng Turbo Debugger (tại dấu nhắc của Dos, nhập TD TEST), bạn có thể quan sát dễ dàng quan sát được các mã khởi động của unit SYSTEM và CRT vào đầu chương trình dưới dạng các lệnh Call Far:

CALL XXXX:0000 ; Khởi động unit system
CALL YYYY:000D ; Khởi động unit Crt

Trong Turbo Debugger, ấn F8 (Step Over) để thực hiện 1 lần lệnh thứ nhất và F7 (Trace) để bước vào chạy từng bước lệnh CALL thứ hai-lệnh khởi động CRT. Sau đó, chọn mục Run / Execute To, nhập offset địa chỉ cần tới là 0091 (hex), bấm Enter. Con trỏ sẽ hiện lên ở ngay trước vị trí đoạn mã lệnh gây lỗi( XXXX:0091). Nếu nhấn F8 1 lần nữa, Deburger sẽ hiện ra thông báo: Terminated, exit code 200. Để tiện theo dõi, tôi xin trích ra một phần các lệnh có liên quan phía trước và sau lệnh gây lỗi:

CRT_Initialize:
...............................
XXXX:0071: MOV ES,Seg0040
XXXX:0075: MOV DI,OFFSET Timer
XXXX:0078: MOV BL,ES:[DI] ; ES = 0040h, DI = 006Ch
XXXX:007b: @@2: CMP BL,ES:[DI] ; ES:DI = System clocktick
XXXX:007e:JE @@2
XXXX:0080: MOV BL,ES:[DI]
XXXX:0083: MOV AX,-28
XXXX:0086: CWD ; DX = FFFFh, AX = FFE4h
XXXX:0087: CALL DelayLoop
XXXX:008a: NOT AX
XXXX:008c: NOT DX
XXXX:008e: MOV CX,55
XXXX:0091: DIV CX ; Nỳi gờy lửợi
XXXX:0093: MOV DelayCount,AX
DelayLoop:
XXXX:02c6: @@1: SUB AX,1
XXXX:02c9: SBB DX,0
XXXX:02cc: JC @@2
XXXX:02ce: CMP BL,ES:[DI]
XXXX:02d1: JE @@1
XXXX:02d3: @@2: RET

Tôi không muốn bạn "sa lầy" vào hợp ngữ, xin giải thích ý chính của đoạn chương trình này như sau:

Khi phần khởi động của CRT chạy, chương trình sẽ khởi tạo một biến gọi là DelayCount (dạng word 2- byte). Biến này chứa số lần thực hiện các lệnh trong vòng lặp DelayLoop để làm chậm 1 mili giây. Nếu bạn cần delay N mili giây, hệ thống sẽ thực hiện N lần vòng DelayLoop.

Cách xác định DelayCount sẽ dựa vào giá trị xung đếm hệ thống (clocktick) tại địa chỉ 0040:006C (4 byte). Mỗi giây, nhờ kích hoạt của interrupt 08, giá trị tại địa chỉ này sẽ tăng lên 18.2 lần.

Trình biên dịch sẽ đặt vào DX:AX một giá trị cố định và gọi vòng lặp DelayLoop. Trong vòng lặp này, giá trị DX:AX sẽ được thay đổi cho tới khi clocktick của hệ thống thay đổi.

Đó là độ thay đổi của DX:AX trong 1 clocktick (1/18.2s). Để có giá trị này cho 1 mili giây, giá trị DX:AX sẽ được chia cho 55 (xin để ý: 18.2 * 55 = 1000ms=1second).

Đoạn lệnh gây lỗi trong chương trình chính là đoạn chia DX:AX cho CX. Về mặt nguyên tắc, thương số sẽ được chứa trong AX và số dư trong DX. Tuy nhiên, do DX:AX quá lớn, giá trị DX:AX chia cho CX sẽ vượt qua giá trị tối đa của 1 word (FFFFh) và hệ thống phát sinh thông báo lỗi.

Với máy Celeron 333 của tôi, giá trị nhận được khi chạy tới lệnh tại địa chỉ xxxx:008E là DX= 0045h, AX=4EEAh. Do đó, phép chia DX:AX (00454EEAh) cho CX(55=37h) sẽ làm tràn số và gây ra lỗi runtime. Nguyên nhân của vấn đề lỗi rõ ràng có liên quan tới tốc độ CPU. Do CPU chạy quá nhanh, độ biến đổi DX:AX là rất lớn và phép chia DX:AX cho CX bị tràn. CPU trong tầm 200Aạ266MHz có lẽ nằm ở ngưỡng của "vực thẳm" vì DX = 045h (giá trị ứng với Celeron 333MHz) * 266/333 = 37h = 55 (Phép chia DX:AX cho CX sẽ cho ra một giá trị xấp xỉ FFFFh. Do đó, với các hệ thống 200 - 266 MHz nhanh, lỗi trên có thể xuất hiện và với các hệ thống chậm, các bạn có thể chạy Turbo Pascal một cách yên ả). Như bạn có thể thấy, CPU tốc độ 300MHz, 333MHz hoặc cao hơn sẽ gây lỗi (do giá trị DX lớn hơn nhiều so với CX, dẫn tới DX:AX chia CX bị tràn). Như vậy, cách giải quyết của chúng ta sẽ xoay quanh việc làm giảm độ biến đổi DX:AX xuống. Điều này có thể thực hiện bằng cách làm chậm vòng DelayLoop xuống. Bạn có thể thêm 1 vài lệnh làm tiêu tốn CPU clock vào vòng lặp này như tôi thực hiện ở phần sau. Mọi thông báo sẽ chấm dứt và chương trình Pascal của bạn sẽ chạy một cách êm ả.

Cách giải quyết

  • Mọi vấn đề "đau đầu" nói trên sẽ được giải quyết bằng cách thay đổi nội dung tập tin CRT.TPU. Thông thường, khi bạn khởi động TURBO PASCAL (TP) hay BORLAND PASCAL (BP), CRT.TPU sẽ được hệ thống tự động nạp khi đọc TURBO.TPL (TPL=Turbo Pascal Library). Nhiệm vụ của chúng ta là thay đổi unit CRT trong TURBO.TPL.
  • Đơn giản nhất, bạn có thể chép tập tin TURBO.TPL từ tòa soạn về và ghi đè lên tập tin TURBO.TPL trong thư mục \BP\BIN (xem như \BP là thư mục Pascal của bạn). Tập tin TURBO.TPL mới chứa mọi thay đổi cần thiết giúp bạn có thể chạy BORLAND PASCAL với bộ xử lý Intel Pentium Celeron (và hy vọng mọi bộ xử lý khác "có vấn đề").
  • Nếu bạn không thể ghé tòa soạn và có thể truy xuất Internet hay e-mail, xin gửi e-mail cho namthang72@hotmail.com,, tôi sẽ gửi file TURBO.TPL lại cho bạn theo dạng attachment.
  • Và cuối cùng, nếu bạn không thể chép tập tin từ tòa soạn và cũng không có điều kiện sử dụng Internet, nếu cho mình là một lập trình viên Pro, hãy làm như sau:

Trước khi tiến hành các bước sau, hãy lưu lại tập tin TURBO.TPL trong \BP\BIN để đề phòng mọi bất trắc.

Bước 1: Sửa lại nội dung unit CRT

Với một bản cài đầy đủ của Borland Pascal 7.0, bạn sẽ có thư mục \BP\CRT, trong đó có 2 tập tin CRT.ASM và CRT.PAS. Đầu tiên, hãy thay đổi nội dung CRT.ASM như sau (hãy bấm Ctrl Q-L và tìm từ DelayLoop và phần mã sau):

; Delay one timer tick or by CX iterationsDelayLoop:
@@1:
SUB AX,1
SBB DX,0
JC @@2
CMP BL,ES:[DI]
JE @@1
@@2: RET

trở thành:

; Delay one timer tick or by CX iterations
DelayLoop:
@@1:
push ax ; bắt đầu các hàng chèn thêm
push cx push dx
mov ax,0
mov cx,1
mov dx,0
div cx ;với 10 lệnh div cx, DelayCount = 5F0h div cx; đủ cho bạn chạy với CPU có tốc độ <>
div cx ; về mặt lý thuyết.
div cx
div cx
div cx
div cx
div cx
div cx
div cx
pop dx
pop cx
pop ax ; kết thúc các hàng chèn thêm
SUB AX,1
SBB DX,0
JC @@2
CMP BL,ES:[DI]
JE @@1
@@2: RET

Như tôi có trình bày ở phần trên, các dòng chèn thêm không thực hiện bất cứ một lệnh gì mà chỉ đơn thuần là làm chậm vòng DelayLoop lại. Điều này không có nghĩa là đồng hồ hệ thống sẽ chậm lại mà chỉ đơn thuần làm chậm vòng DelayLoop và giảm số lần lặp xuống.

Lệnh nguyên thủy SUB và SBB của vòng lặp được giữ nguyên, các lệnh DIV (sau khi lưu nội dung thanh ghi AX, CX, DX bằng loạt lệnh PUSH) nhằm làm chậm hơn vòng lặp. Sở dĩ tôi chọn các lệnh này là vì DIV là lệnh tiêu tốn nhiều clock của CPU (lệnh mất nhiều thời gian thực hiện). Bạn có thể thêm số lần DIV nếu cảm thấy cần thiết. Cuối cùng, loạt lệnh POP hoàn trả lại nội dung các thanh ghi.

Bước 2. Chép tập tin SE.ASM từ thư mục \BP\SYS vào thư mục \BP\CRT. Tập tin SE.ASM chứa một số định nghĩa cho quá trình dịch các Unit của Borland (hay Turbo) Pascal.

Bước 3. Tiến hành dịch CRT.ASM bằng lệnh:

\BP\BIN\TASM CRT.ASM

Máy sẽ phát ra một vài cảnh báo về cách sử dụng tên biến. Cứ "nhắm mắt làm ngơ", chẳng có gì nghiêm trọng đâu.

Bước 4. Chạy Borland Pascal và tiến hành dịch (bấm F9) \BP\CRT\CRT.PAS để tạo ra CRT.TPU. Chép CRT.TPU vào thư mục \BP\BIN.

Bước 5. Chuyển thư mục hiện thời qua \BP\BIN

Xóa unit CRT trong TURBO.TPL bằng lệnh:

TPUMOVER TURBO.TPL -CRT

Sau đó, đưa unit CRT mới sửa vào TURBO.TPL

TPUMOVER TURBO.TPL +CRT

TURBO.TPL đã sẵn sàng. Hãy khởi động lại Borland Pascal. Hy vọng rằng mọi hàm của bạn đều được thực hiện một cách chính xác và Turbo Pascal sẽ chẳng còn phát ra những thông báo lỗi khó chịu "Run time error 200" khi bạn sử dụng unit CRT nữa.

Giải pháp cho các chương trình Pascal đã biên dịch nhưng không còn source

Chắc rằng trong số các chương trình bạn đã biên dịch bằng Borland Pascal 7, một số chương trình sử dụng unit CRT cũng sẽ gặp phải lỗi Division Error kể trên. Nếu các bạn còn giữ source, biên dịch lại chương trình với unit TURBO.TPL đã hiệu chỉnh không phải là "chuyện lớn". Thế nhưng phải làm thế nào nếu bạn không còn hay không có source các chương trình trên.

Để ý rằng do chương trình EXE đã được dịch, việc thay đổi vòng lặp DelayLoop để không ảnh hưởng tới các phần khác của chương trình là không thực hiện được. Do đó, chúng ta cần thay đổi trực tiếp đoạn mã lệnh gây lỗi.

Giải pháp tôi xin đề cử tới các bạn là thay đoạn lệnh:

XXXX:008e: mov CX,55

XXXX:0091: div CX

bằng một lệnh đơn giản: mov AX,0FFFFh vì FFFFh là giá trị tối đa mà DelayCount (biến dạng word 2 byte) có thể nhận được. Tuy nhiên, để không làm biến đổi địa chỉ các phần khác, bạn nhớ đặt thêm 1 lệnh 2 byte trước lệnh move này (do 2 lệnh nguyên thủy chiếm 5 byte bộ nhớ còn lệnh mov AX,0FFFFh chỉ chiếm 3 byte. Giải pháp này dẫn tới việc nếu bạn dùng hàm delay, máy tính sẽ chờ ít hơn (nhanh hơn) so với thời gian bạn yêu cầu, tuy nhiên trong đa số các trường hợp, điều này không dẫn tới hậu quả gì nghiêm trọng. Để tránh sự phiền hà khi tìm kiếm và thay đổi phần mã gây lỗi, tôi có kèm thêm chương trình PATCH.EXE (có thể chép tại Tòa Soạn PCW). Chương trình này sẽ tự động thực hiện việc thay đổi đoạn mã kể trên. Chỉ có đôi điều bạn cần lưu ý:

1. Chỉ dùng PATCH với các chương trình phát sinh lỗi khi chạy như kể trên.

2. Hãy lưu file nguyên thủy trước khi thực hiện thay đổi.



Borland Turbo Pascal 7 là bộ biên dịch ngôn ngữ lập trình Pascal, nhưng đã nhiều năm, hãng Borland không cập nhật. Trong bộ biên dịch Pascal này có unit CRT mà hầu hết chương trình viết trên Pascal có sử dụng. Các chương trình được biên dịch bằng Borland Turbo Pascal 7 có sử dụng unit CRT sẽ bị kết thúc với thông báo lỗi "Runtime Error 200" trên các máy PC tốc độ cao, ví dụ như máy Pentium II 350MHz bus 100MHz (chúng tôi cũng đã thử nghiệm trên máy Pentium II 350MHz - bus 66MHz thì không thấy lỗi này).

Chương trình được biên dịch bằng Borland Pascal 6 không bị lỗi này, nhưng thời gian trì hoãn trong lệnh delay bị sai hoàn toàn khi chạy trên các máy PC nhanh.

Nguyên nhân

Lỗi xảy ra khi thi hành chương trình có sự khởi tạo unit Crt, trong đó thủ tục delay cũng được khởi tạo. Việc khởi tạo thủ tục delay không chỉ được gọi trong các chương trình có sử dụng thủ tục delay, mà nó còn được gọi trong tất cả các chương trình có sử dụng unit Crt.

Khi khởi tạo thủ tục delay, chương trình sẽ đếm số lần thực hiện một vòng lặp nhỏ trong khoảng thời gian 55 mili giây (thời gian được đo bằng cách đọc bộ đếm thời gian của BIOS ở địa chỉ 40:6C, bộ đếm này nhịp 18,2 lần mỗi giây, nghĩa là mỗi nhịp chiếm 55 mili giây).

Số đếm này được chia lại cho 55 để được số lần thực hiện vòng lặp trong một mili giây. Kết quả được ghi vào trong biến kiểu word (16 bit). Kết quả sẽ được sử dụng làm cơ sở để tính thời gian trì hoãn trong lệnh delay. Khi chạy chương trình trên các máy PC tốc độ cao, số lần lặp trong 55 mili giây quá lớn (hơn 65.535) làm biến này bị tràn (overflow) và gây ra lỗi (ý nghĩa của Runtime Error 200 là lỗi chia cho Zero, nhưng thật ra đó là lỗi tràn biến).

Giải pháp

Dưới đây là vài bộ chương trình có thể tìm trên Internet để khắc phục lỗi này cho những trường hợp tiêu biểu. Cũng cần lưu ý với các bạn rằng đây là những chương trình do người dùng viết, còn Borland cũng như Intel không đưa ra giải pháp nào!

Nếu bạn chỉ có tập tin đã dịch sang file .EXE mà không có chương trình nguồn:

Có thể dùng TpPatch.zip, bộ chương trình sửa trực tiếp trên tập tin thực thi (.EXE) được biên dịch từ Borland Pascal 7, chỉ nên sử dụng cho các chương trình không cần định thời chính xác. Bạn hãy giải nén tập tin này, sau đó thực hiện theo những hướng dẫn cụ thể trong đó.

Nếu bạn sử dụng Turbo Pascal 7.01 hoặc Borland Pascal 7.01 ở chế độ real mode :Trong trường hợp này, bạn có thể tải xuống ba tập tin sau và tùy chọn theo ý bạn.

T7TplFix.zip. Bộ chương trình nâng cấp cho tập tin thư viện Run Time Library (TURBO.TPL), bạn chỉ cần giải nén, chạy chương trình và nó sẽ tự động thực hiện công việc trên.

NewDelay.pas. Là một tập tin dạng Unit thay thế lệnh delay. Nếu dùng Unit này, phải khai báo nó trước Crt và tất cả các Unit khác có sử dụng Unit Crt trong chương trình nguồn.

Rdelay.zip. Giống như NewDelay, nó thay thế lệnh Delay.

Bộ chương trình bppatch. Đây là giải pháp theo chúng tôi thấy là tốt nhất khi tiến hành các thử nghiệm. Giải pháp này bao gồm chương trình nguồn Crt.asm và Crt.pas (mà chúng ta có thể học được nhiều điều nếu so sánh Crt.asm và Crt.pas với chương trình gốc của Borland) cùng các thư viện Turbo.tpl, Tpp.tpl, Tpw.tpl. Hoặc là bạn dịch lại toàn bộ thư viện RTL, hoặc đơn giản là bạn chỉ cần chép các file .TPL vào thư mục BIN và dịch lại các chương trình mà bạn đã viết.

Vài bộ chương trình khác như bp7patch, tp7p5fix, tpbug.

Sau khi tìm hiểu các giải pháp trên, nhiều người trong chúng ta có thể thấy rằng một giải pháp đầy đủ về nhiều mặt (nhất là vấn đề bản quyền) vẫn chưa có, trừ khi Borland (đã đổi tên thành Inprise) phát hành phiên bản mới.