Mục lục bài họcĐang ở d03-b2
← IGCSE Computer Science
0/18 bài đã học xong
Chương 3 · Software · Bài 2/2 của chương · bài 6/18 của IGCSE Computer Science

Programming languages and translators

Ngôn ngữ lập trình và trình dịch
← Mục lục bài học
Lý thuyết · English

High-level and low-level languages

high-levelclose to human language; one statement does a lot; portable between different processors
low-levelclose to the machine; assembly language uses mnemonics like $\text{LDA}$ and $\text{ADD}$; machine code is pure binary

High-level languages are easier and faster to write, easier to read and debug, and the same program runs on different machines after re-translation.

Low-level languages give direct control of the hardware and can produce faster, smaller code — but they are hard to write, easy to get wrong, and specific to one processor, so the program will not run on a different type of machine.

Note that high-level is not simply better. It is the right choice for almost all programs, but device drivers and embedded systems still use low-level code where every byte and every cycle matters.

Assembly language and the assembler

Assembly language replaces binary instructions with short mnemonics, so $\text{ADD}$ is far easier to read than a string of bits. Each mnemonic corresponds to one machine-code instruction.

An assembler translates assembly language into machine code.

Compiler and interpreter

Both translate high-level code into machine code, but they work completely differently.

compilerinterpreter
how it translatesthe whole program at onceone line at a time, executing each as it goes
outputproduces an executable fileproduces no file — it must run every time
errorsreports all errors together at the endstops at the first error it meets
speed of runningfaster — already translatedslower — translating while running
source codeuser does not need ituser needs it and the interpreter

The consequence the exam asks about: an interpreter is better for developing and debugging, because it stops exactly at the offending line so the programmer sees immediately where the problem is. A compiler is better for the finished program, because it runs faster and the source code stays private.

Note what "stops at the first error" really means: the interpreter finds errors one at a time, so a program with ten errors must be run ten times. The compiler lists all ten at once — but gives nothing runnable until they are all fixed.

Integrated Development Environments

An IDE brings the tools a programmer needs into one program:

  • code editor with line numbering, colour-coded syntax highlighting and auto-completion;
  • error diagnostics — underlining mistakes as you type and explaining them;
  • a translator — compiler or interpreter, built in;
  • a run-time environment to execute the program without leaving the IDE;
  • debugging tools — breakpoints to pause execution, and variable watches to see values change.

The benefit is that writing, translating, running and fixing all happen in one place, which makes development far faster than using separate tools.

Giải thích tiếng Việt

Ngôn ngữ bậc cao và bậc thấp.

  • Bậc cao — gần với ngôn ngữ con người; một câu lệnh làm được nhiều việc; khả chuyển giữa các bộ xử lý khác nhau;
  • Bậc thấp — gần với máy; hợp ngữ dùng các từ gợi nhớ như $\text{LDA}$ và $\text{ADD}$; mã máy là nhị phân thuần tuý.

Ngôn ngữ bậc cao dễ và nhanh viết hơn, dễ đọc và dễ gỡ lỗi hơn, và cùng một chương trình chạy được trên nhiều máy khác nhau sau khi dịch lại.

Ngôn ngữ bậc thấp cho quyền điều khiển phần cứng trực tiếp và sinh ra mã nhanh hơn, gọn hơn — nhưng khó viết, dễ sai, và chỉ dùng được cho một loại bộ xử lý, nên chương trình không chạy được trên máy khác loại.

Chú ý bậc cao không đơn giản là tốt hơn. Nó là lựa chọn đúng cho gần như mọi chương trình, nhưng trình điều khiển thiết bị và hệ thống nhúng vẫn dùng mã bậc thấp ở những nơi từng byte và từng chu kỳ đều quan trọng.

Hợp ngữ và trình hợp dịch. Hợp ngữ thay các lệnh nhị phân bằng những từ gợi nhớ ngắn, nên $\text{ADD}$ dễ đọc hơn hẳn một chuỗi bit. Mỗi từ gợi nhớ ứng với một lệnh mã máy.

Trình hợp dịch dịch hợp ngữ thành mã máy.

Trình biên dịch và trình thông dịch. Cả hai đều dịch mã bậc cao thành mã máy, nhưng cách làm hoàn toàn khác nhau.

  • Trình biên dịch dịch toàn bộ chương trình một lần, tạo ra một tệp chạy được. Nó báo mọi lỗi cùng lúc ở cuối. Chương trình chạy nhanh hơn vì đã dịch xong, và người dùng không cần mã nguồn;
  • Trình thông dịch dịch từng dòng một và chạy ngay dòng đó. Nó không tạo tệp nào, nên phải dịch lại mỗi lần chạy. Nó dừng ngay ở dòng lỗi đầu tiên. Chương trình chạy chậm hơn, và người dùng cần cả mã nguồn lẫn trình thông dịch.

Hệ quả mà đề thi hỏi: trình thông dịch tốt hơn khi đang phát triển và gỡ lỗi, vì nó dừng đúng tại dòng có vấn đề nên lập trình viên thấy ngay lỗi ở đâu. Trình biên dịch tốt hơn cho sản phẩm hoàn chỉnh, vì chương trình chạy nhanh hơn và mã nguồn được giữ kín.

Chú ý ý nghĩa thật của câu “dừng ở lỗi đầu tiên”: trình thông dịch tìm lỗi từng cái một, nên một chương trình có mười lỗi phải chạy mười lần. Trình biên dịch liệt kê cả mười cùng lúc — nhưng không cho gì chạy được cho tới khi sửa hết.

Môi trường phát triển tích hợp. Nó gom các công cụ lập trình viên cần vào một chương trình:

  • trình soạn mã có đánh số dòng, tô màu cú pháp và gợi ý hoàn thành lệnh;
  • chẩn đoán lỗi — gạch chân lỗi ngay khi gõ và giải thích lỗi;
  • trình dịch — biên dịch hoặc thông dịch, tích hợp sẵn;
  • môi trường chạy thử để chạy chương trình mà không phải rời khỏi phần mềm;
  • công cụ gỡ lỗi — điểm dừng để tạm ngưng chương trình, và cửa sổ theo dõi biến để thấy giá trị thay đổi.

Lợi ích là việc viết, dịch, chạy và sửa đều diễn ra ở cùng một chỗ, nên phát triển nhanh hơn hẳn so với dùng các công cụ rời rạc.

Khác biệt quyết định: báo lỗi TẤT CẢ hay dừng ở lỗi ĐẦU TIÊN TRÌNH BIÊN DỊCH — dịch TOÀN BỘ một lần mã nguồn (cả tệp) biên dịch TỆP CHẠY ĐƯỢC chạy nhanh, không cần mã nguồn báo MỌI LỖI cùng lúc ở cuối — nhưng chưa sửa hết thì chưa có gì chạy được TRÌNH THÔNG DỊCH — dịch và chạy TỪNG DÒNG dòng 1 → dịch → chạy ✓ dòng 2 → dịch → chạy ✓ dòng 3 → LỖI → DỪNG dòng 4 chưa chạy tới ✓ thấy NGAY lỗi ở dòng nào → tốt khi đang GỠ LỖI ✗ mười lỗi thì phải chạy mười lần
Hai cách báo lỗi dẫn tới hai công dụng khác nhau: thông dịch hợp lúc đang viết, biên dịch hợp cho bản hoàn chỉnh giao cho người dùng.
Ví dụ — chọn trình biên dịch hay trình thông dịch

Một lập trình viên đang viết dở một chương trình lớn và sẽ phát hành nó cho khách hàng khi xong. Nêu nên dùng trình thông dịch hay trình biên dịch ở mỗi giai đoạn, và giải thích.

Giải.

Giai đoạn đang viết và gỡ lỗi → dùng TRÌNH THÔNG DỊCH.

Lý do một — thấy ngay lỗi ở đâu. Trình thông dịch dịch và chạy từng dòng một, và nó dừng đúng tại dòng có lỗi. Lập trình viên biết ngay vấn đề nằm ở đâu mà không phải dò tìm.

Lý do hai — thử nhanh từng đoạn. Không phải dịch lại cả chương trình sau mỗi lần sửa một chữ. Sửa xong là chạy được ngay, nên vòng lặp sửa – thử – sửa rất nhanh.

Lý do ba — chạy được chương trình còn dở. Trình thông dịch chạy tới đâu hay tới đó, nên lập trình viên thử được phần đã viết xong dù phần sau chưa hoàn thiện.

Nhược điểm chấp nhận được ở giai đoạn này: chương trình chạy chậm hơn, nhưng lúc đang phát triển thì tốc độ chạy không quan trọng bằng tốc độ tìm ra lỗi.

Giai đoạn phát hành cho khách → dùng TRÌNH BIÊN DỊCH.

Lý do một — chạy nhanh hơn. Chương trình đã được dịch sẵn thành mã máy, nên khi khách chạy nó không mất thời gian dịch nữa.

Lý do hai — khách không cần mã nguồn. Trình biên dịch tạo ra một tệp chạy được độc lập. Khách chỉ nhận tệp đó và chạy được ngay, không cần cài trình dịch gì cả.

Lý do ba — bảo vệ mã nguồn. Vì khách chỉ nhận tệp đã dịch, họ không đọc được mã nguồn. Điều này bảo vệ công sức và bí quyết của lập trình viên.

Với trình thông dịch thì ngược lại: khách bắt buộc phải có cả mã nguồn lẫn trình thông dịch mới chạy được.

Kết luận. Hai công cụ không thay thế nhau mà phục vụ hai giai đoạn khác nhau: thông dịch để viết và sửa, biên dịch để giao hàng.

Trong thực tế nhiều môi trường lập trình cung cấp cả hai, đúng vì lý do này.

Ví dụ — khi nào vẫn phải dùng ngôn ngữ bậc thấp

Ngôn ngữ bậc cao dễ viết hơn nhiều. Giải thích vì sao ngôn ngữ bậc thấp vẫn được dùng trong một số trường hợp, và nêu cái giá phải trả.

Giải.

Ưu điểm của ngôn ngữ bậc thấp.

Điều khiển phần cứng trực tiếp. Ngôn ngữ bậc thấp cho lập trình viên can thiệp thẳng vào từng thanh ghi, từng ô nhớ và từng chân của bộ xử lý.

Có những việc chỉ làm được như vậy: viết trình điều khiển thiết bị, lập trình vi điều khiển, hay viết phần lõi của hệ điều hành.

Mã nhanh hơn và gọn hơn. Trình biên dịch của ngôn ngữ bậc cao sinh ra mã máy khá tốt nhưng không tối ưu tuyệt đối. Một lập trình viên giỏi viết hợp ngữ tay có thể tạo ra mã nhanh hơn và chiếm ít bộ nhớ hơn.

Điều này quan trọng ở hệ thống nhúng — máy giặt, thiết bị y tế, cảm biến — nơi bộ nhớ chỉ vài ki-lô-byte và từng byte đều quan trọng.

Cái giá phải trả.

Khó viết và dễ sai. Một việc mà ngôn ngữ bậc cao làm trong một dòng có thể cần hàng chục lệnh hợp ngữ. Chương trình dài hơn nhiều nên cơ hội mắc lỗi cũng lớn hơn nhiều.

Khó đọc và khó bảo trì. Mã hợp ngữ rất khó hiểu với người khác — hoặc với chính tác giả sau vài tháng. Việc sửa đổi về sau vì thế tốn kém.

Không khả chuyển. Đây là hạn chế nặng nhất. Ngôn ngữ bậc thấp gắn với một loại bộ xử lý cụ thể. Muốn chạy trên loại máy khác thì phải viết lại gần như từ đầu.

Ngôn ngữ bậc cao chỉ cần dịch lại bằng một trình biên dịch khác là chạy được.

Kết luận. Ngôn ngữ bậc cao không đơn giản là tốt hơn — nó là lựa chọn đúng cho gần như mọi chương trình thông thường.

Ngôn ngữ bậc thấp chỉ đáng dùng ở những nơi hiệu năng hoặc quyền điều khiển phần cứng quan trọng hơn chi phí phát triển: trình điều khiển thiết bị, hệ thống nhúng, và những đoạn mã then chốt về tốc độ.

Bẫy hay mất điểm — Nói trình thông dịch báo cho lập trình viên tất cả các lỗi. Ngược lại mới đúng: trình thông dịch dừng ngay ở lỗi đầu tiên nó gặp và không đi tiếp, nên nó tìm lỗi từng cái một — chương trình có mười lỗi thì phải chạy mười lần. Chính trình biên dịch mới liệt kê tất cả các lỗi cùng lúc, vì nó quét toàn bộ chương trình trước khi tạo ra tệp chạy. Đừng nhầm điều đó với “biên dịch tiện hơn”: bù lại, trình biên dịch không cho ra thứ gì chạy được cho tới khi mọi lỗi được sửa xong, trong khi trình thông dịch chạy được phần đã đúng và dừng đúng tại dòng có vấn đề — đó là lý do nó tiện hơn khi đang phát triển. Bẫy thứ hai: nghĩ ngôn ngữ bậc cao luôn tốt hơn. Nó dễ viết và khả chuyển, nhưng mã máy do trình biên dịch sinh ra không tối ưu tuyệt đối. Trình điều khiển thiết bị và hệ thống nhúng vẫn dùng bậc thấp, vì ở đó từng byte và từng chu kỳ đều quan trọng.
Phải nhớ — Bậc cao dễ viết và khả chuyển; bậc thấp cho điều khiển phần cứng trực tiếp và mã gọn hơn nhưng chỉ chạy trên một loại bộ xử lý. Trình biên dịch dịch toàn bộ một lần, tạo tệp chạy được, báo mọi lỗi cùng lúc, chạy nhanh và giấu được mã nguồn. Trình thông dịch dịch từng dòng, dừng ở lỗi đầu tiên, chạy chậm hơn và đòi người dùng có mã nguồn. Vì thế: thông dịch để phát triển, biên dịch để giao hàng. Môi trường phát triển tích hợp gom soạn thảo, dịch, chạy và gỡ lỗi vào một chỗ.

Đọc xong rồi — làm thử ngay

Bài tập của chương Software gồm 14 câu trắc nghiệm và 5 đề tự luận. Đáp án hiện ngay khi chọn, miễn phí.

Làm bài tập chương →