Assembly là gì, công dụng của Assembly và có nên học Assembly không ?

18574
Assembly Language (ASM), tiếng Việt là hợp ngữ. Mục đích của mình học ASM chỉ cơ bản là muốn hiểu thêm về người bạn thân thiết nhất của mình, cái máy tính mà suốt ngày mình ngồi trước nó. Mình chỉ thật sự muốn biết là đằng sau những dòng lệnh mình code thường ngày thì bên dưới nó làm cái gì ?!. Thật tiếc là sau khi đã tìm hiểu được một số khái niệm về kiến trúc CPU, các loại Registers (thanh ghi), Data Segments, Data Moving thì mình buộc phải bỏ cuộc ở Control Flow.
Lý do đầu tiên là … do mình dở, mình thấy nó thật sự quá khó với mình, vốn là dân code ứng dụng với ngôn ngữ bậc cao (high level language) và chưa biết gì về Computer Scientic. Thứ hai là cách tiếp cận bottom-up (từ lý thuyết lên) này cũng không tốt. Mình nghĩ là trong tương lai nếu có dự án nào cần tới ASM thì mình sẽ có thể vừa học và practice tốt hơn (hướng tiếp cận top-down hay còn gọi là end to end).

Vậy Assemly Language là gì ?

Assembly Language (hay viết tắt là ASM) là ngôn ngữ bậc thấp, chính xác nó là ngôn ngữ thuộc thế hệ thứ 2 (2nd generation). ASM sử dụng các từ gợi nhớ (mnemonics) để viết các chỉ thị (instructions) lập trình cho máy tính thay vì bằng những dãy 01.
Các ASM sẽ cần một chương trình Assembler phù hợp (NASM, AS, DASM) để dịch chúng thành những file binary và một trình linker để link các thành phần lại và chỉ định nơi bắt đầu của chương trình và đây là việc bắt buộc.
VD: Hàm main trong C mặc định là nơi chương trình khởi chạy. Lệnh dịch source C ra binary trên thực tế nó đã làm 2 bước trên: dịch và link (xác định luôn nơi khởi chạy chương trình là main).
Một trong các đặc tính của chương trình viết trực tiếp bằng ASM là: chúng có tốc độ thực thi cao và tiêu tốn bộ nhớ ít hơn các chường viết bởi các ngôn ngữ lập trình bậc cao.
Việc học ASM cũng sẽ giúp chúng ta hiểu thêm về kiến trúc phần cứng máy tính, cách chúng hoạt động và tương tác với nhau. VD như các thành phần cơ bản trong máy tính, cách chúng truyền thông tin cho nhau:
ASM có thể tương tác rất sâu dưới hệ thống, chúng có thể giao tiếp trực tiếp với các phần cứng và bắt chúng hoạt động theo ý người lập trình. Vì thế mà chúng ta có hẳn một ngành mang tên là “lập trình nhúng”.

Cái khó của việc học ASM

Thông thường khi học một ngôn ngữ lập trình chúng ta chỉ đơn giản là cài đặt môi trường lập trình, công cụ biên dịch và sử dụng các editor hoặc IDE nếu có thể học lập trình. Viết một chương trình đơn giản rồi biên dịch và chạy thử trên các ngôn ngữ bậc cao (C, C++, Java) là rất dễ dàng. Nhưng với ASM thì bạn sẽ dễ bị “nản” vì không thể dịch và chạy code ASM đúng như hướng dẫn.
Lý do là ASM lập trình các chỉ thị cho phần cứng tuy nhiên chúng lại lệ thuộc vào kiến trúc CPU (ARM, x86-32, x86-64), hệ điều hành (Linux, Windows, Mac) và các tập chỉ thị mà nhà sản xuất phần cứng đưa ra. Đa số các hướng dẫn, sách vở được viết cho kiến trúc iA-32. Một số hướng dẫn mới gần đây hơn thì viết cho kiến trúc x86-64 trên Linux, sử dụng Assembler của GNU.
Khác với ngôn ngữ C, về lý thuyết chúng ta có thể dịch lại mà không cần đổi source code ban đầu. Tuy nhiên thực tế thì điều này khó xảy ra vì chúng ta chỉ có thể làm được điều trên nếu không gọi tới các API của hệ điều hành. Nói tới đây lại thấy yêu Java hơn, Java thật sự là cuộc cách mạng viết một lần, chạy mọi nơi và cũng chẳng cần phải dịch lại. Mọi thứ đã có máy ảo Java lo.
Thêm một khó khăn nữa cho những người học ASM trên máy Mac như mình. Apple chỉ định riêng bộ linker (Match-O) cho ASM, chúng sử dụng một số chỉ thị riêng, padding memory riêng (có 4 lớp padding). Việc viết ASM cho máy Mac thật sự có rất ít bài viết hướng dẫn, doc của Apple thì như kinh thánh … Việc nhớ các thanh ghi, các chỉ thị thôi đã đuối lắm rồi, thêm Apple hành nữa thật là khó càng thêm khó !!! Chi tiết Apple OS X Assembler Reference.
VD: Một chương trình in ra “Hello World” viết bằng ASM trên Mac OS như sau:
Sử dụng GNU Assembler, linker và chạy thử:

Như các bạn đã thấy việc in một đoạn text ra màn hình với ASM khá phức tạp, đó là chưa kể ta phải viết đúng chỉ thị của OS và CPU hiện tại. Tất cả chỉ là các chỉ thị cho các thanh ghi chứ không có kiểu 1 lệnh in ra tất cả như C.

ASM khó vậy thì học để làm gì ?!?

ASM sẽ chẳng có ý nghĩa gì nếu chúng ta không thuộc tập sau đây:
  1. Những người cần lập trình phần cứng, mạch điện tử, các chip vi xử lý.
  2. Những người lập trình compiler, hệ điều hành. (Trong đó có anh Chris Lattner, tác giả của LLVMSwift mà mình rất ngưỡng mộ vì anh rất trẻ – SN 1978)
  3. Hacker chuyên nghiệp.
  4. Reverse Engineer: nếu dịch là kỹ sư đảo thì không hay và cũng ko đủ ý. RE là những kỹ sư chuyên phân tích, mổ xẻ các chương trình để hiểu rõ chi tiết bên trong nó thế nào, RE thường ứng dụng trong an ninh: phát hiện mã độc, đánh giá thuật toán mã hoá … và các lĩnh vực khác có liên quan.
Một số lợi ích khác của ASM là:
  1. Có thể dùng debug chương trình mà không cần source code.
  2. Có thể dùng để tối ưu hoá chương trình: một số dân code ASM chuyên nghiệp dùng C để code và dịch ra ASM rồi edit lại cho phù hợp với kiến trúc và các chỉ thị riêng và tối ưu của nhà sản xuất chip. Lý do là các compiler chỉ dịch ra ASM chung nhất cho các dòng chip.

Một số tài liệu liên quan tới ASM

Mình xin chia sẻ lại một số tài liệu mà trong thời gian qua mình có được, để ai đó có đang tìm hiểu ASM có thể tham khảo qua:
Ebook:
  1. Introduction to 64 Bit Assembly Programming for Linux: Quyển này tinh gọn, rất hay. Third edition có cho cả MacOS. Phiên bản này chỉ có cho Linux.
  2. Professional Assembly Language : Quyển này tác giả nói rất sâu về cơ chế, tất cả các thông số register, cơ chế vận hành phần cứng … Tiếc là tác giả viết cho kiến trúc IA-32 và phần code ASM cũng chỉ cho Linux x86-64 thôi.
  3. Hacking: The Art of Exploitation: Dành cho ai thích hack, cuốn này nói rất sâu về kỹ thuật hacking đặc biệt là sử dụng ASM để can thiệp hệ thống.
  4. Practical Reverse Engineering: x86, x64, ARM, Windows Kernel, Reversing Tools, and Obfuscation: Quyển này cho những ai yêu thích RE.
** Sách tiếng Việt mình thấy có vài cuốn nhưng mở vài trang đọc thật sự không hiểu gì !!!
Bài viết:
  1. Assembly “hello, world” for OS X: Bài này viết ASM với assembler NASM. NASM trên MacOS ko có sẵn, phải cài thêm thông qua brew.
  2. x86 Assembly Guide: bài này mình hay dùng để tra cứu nhanh các chỉ thị và thanh ghi (vì não cá vàng chưa thể nhớ nổi @@)
  3. OS X Assembler Reference: Guide về Assembler cho OS X của Apple, mình dùng doc này để convert code bên Linux qua. Cái này thật sự không giúp mình nhiều, chủ yếu coi phần Data Segment và memory padding để sử dụng thanh ghi EAX cho chính xác. Nếu không chương trình sẽ chạy ra lỗi bus error.
Mặc dù dừng lại khá sớm với việc học ASM nhưng mình cũng hài lòng với kết quả đạt được. Mình thu được một mớ kiến thức kha khá về CPU, cơ bản về việc các process cấp phát bộ nhớ. Và quan trọng là bây giờ khi cái màn hình debug trong XCode hiện lên 1 mớ ASM mình có thể hiểu được phần nào chứ không coi nó như thứ ngôn ngữ ngoài hành tinh nữa 😀.
Chúc các bạn học tốt.
Techtalk Via Fb VietTran