ALIEN Language(Assembly x86) Part 1

Suốt quá trình phát triển của khoa học máy tính thì con người chúng ta luôn tìm cách để “bắt” máy tính hiểu những yêu cầu của mình. Nhưng bạn biết không thực ra máy tính chỉ có thể hiểu một ngôn ngữ duy nhất là machine code(mã máy). Trong khi chúng ta diễn giải những yêu cầu bằng các ngôn ngữ bậc cao như Java, C++, Python,…. thì máy tình không thể hiểu được.

Để nó có thể hiểu được thì phải trải qua các bước biên dịch phức tạp. Nhưng có câu “tam sao thất bản” mà dù biên dịch tốt thì máy tính cũng không thể hiểu được 100% yêu cầu của chúng ta. Mà coi như máy tính đã hiểu đi, vậy bao giờ chúng ta mới thực sự hiểu máy tính?

Chính vì lí do trên, Assembly ra đời – nó là một ngôn ngữ mà cả người và máy đều có thể hiểu được, nói vậy thôi chứ chúng để học nó cũng không hề đơn giản 😀 .

Assembly rất gần với mã máy nên cú pháp của nó cũng có phần khó hiểu hơn so với cú pháp của các ngôn ngữ bậc cao. Trong khi các ngôn ngữ bậc cao khác sử dụng biến để biểu diễn dữ liệu thì Assembly sử dụng các thanh ghi, bộ nhớ để làm việc đó. Bản chất ngôn ngữ Assembly là lập trình các chỉ thị để điều khiển phần cứng, chính vì vậy lập trình Assembly sẽ phụ thuộc vào việc bạn đang sử dụng kiến trúc vi xử lý (16 bit, 32 bit, ARM,…), hệ điều hành nào (Windows, Linux, MacOS,…) nên bạn cần phải có kiến thức về kiến trúc vi xử lý và hệ điều hành,..Ngoài ra bạn cần phải có kiến thức cơ bản về các hệ số nhị phận, thập lục phân, các cách biểu diễn dấu. Nhưng không sao đừng lo chỉ với kiến thức về hệ số là chúng ta có thể bắt đầu rồi.

I.Các phương pháp biểu diễn dấu

1.Phương pháp dấu lượng

Các số thập phân chúng ta thường dùng hàng ngày như là 9 ,10,.. còn có các số âm của nó là -9,-10,… Vậy số nhị phân thì sao? Làm sao để biểu diễn một số âm đây?

Chúng ta sẽ sử dụng bit đầu tiên bên trái hay chữ số đầu tiên bên trái của số nhị phân để biểu diễn dấu. Nếu là số dương thì bit(chữ số) này = 0, số âm thì = 1.

Ví dụ: 9 -> 00001001. Vậy -9 thì sao, đơn giản chúng ta chỉ cần đổi bit dầu tiên thành 1 => -9 -> 10001001.

2.Phương pháp bù 1

Phương pháp bù 1 tương tự phương pháp dấu lượng, chỉ khác ở cách biểu diễn độ lớn của số:

  • Nếu là số dương thì bit dấu = 0
  • Nếu là số âm thì đảo các bit giá trị, bit dấu = 1

VD:

  • Số 5 trong hệ nhị phân: 00000101
  • Số -5 trong hệ nhị phân: 11111010

Ví dụ nữa là số +0 là (00000) , -0 là (11111111)

Tuy nhiên phương pháp này vẫn có điều bất tiện đó là: hãy tưởng tượn nếu chúng ta cộng bit 1 vào -0(1111….) thì sao ta sẽ phải liên tiếp nhớ 1. Như vậy rất bất tiện, bì thế phương pháp bù 2 ra đời

3.Phương pháp bù 2

Phương pháp bù 2 đã có sự cải tiến nhằm thuận tiện hơn trong việc tính toán với số nhị phân, cụ thể:

  • Nếu là số dương thì bit dấu = 0
  • Nếu là số âm thì bit dấu = 1, đảo các bit giá trị sau đó cộng thêm 1 vào kết quả.

Ví dụ: số 5->00000101, sau khi bù 2 => -5 -> 11111011

Cách biểu diễn bù 2 ra đời nhằm khắc phục 2 vấn đề của phương pháp dấu lượng và phương pháp bù 1:

  • Số 0 có 2 cách biểu diễn
  • Bit nhớ phát sinh sau khi đã thực hiện phép tính phải được cộng tiếp vào kết quả

Việc đổi dấu 1 số từ âm <==> dương đều được thực hiện theo 1 cách duy nhất: đảo tất cả các bit và cộng thêm 1.
Khi thực hiện phép cộng với số bù 2, nếu phát sinh bit nhớ ở bit dấu, ta có thể bỏ nó đi.

Hiện nay các máy tính hiện đại sử dụng phương pháp bù 2.

II.Kích thước lưu trữ trong máy tính

Ở các ngôn ngữ bậc cao chúng ta lưu trữ thông tin ở các kiểu dữ liệu như integer,float,char,…. Nhưng máy tính thì khác nó có đơn vị lưu trữ riêng.

Đơn vị lưu trữ dữ liệu cơ bản của các máy tính 32bit là byte có kích thước 8bit. Trên byte còn có word (2 bytes), doubleword (4 bytes) và quadword (8 bytes).

Khoảng biểu diễn dữ liệu của chúng như sau:

III.Biểu diễn xâu

String trong máy tính được biểu diễn bằng 1 mảng các giá trị tương ứng với ký tự đó trong bảng ASCII. Thường thì sẽ viết dưới dạng Hex, ít người viết dưới dạng thập phân.
VD: xâu “ABC123” có thể hiển thị dưới dạng 41h, 42h, 43h, 31h, 32h, 33h.(Tra bảng cột Hex )

Khái niệm vô cùng quan trọng tiếp theo đó chính là Register.

IV.Thanh ghi(Register)

Các ngôn ngữ bậc cao chúng ta thường sử dụng thì có các khái niệm như biến, mảng, set, tuple, …. Nhưng máy tính said: “Noooooo! Tôi làm sao mà hiểu được đống khái niệm như vậy!”. Đúng thế, các khái niệm kia được định nghĩa chỉ để cho những người code như chúng ta dễ hình dung, dễ hiểu hơn về cách mà máy tính làm việc với dữ liệu. Thay vì là những khái niệm trên máy tính chỉ biết các thanh ghi và bộ nhớ của nó.

Giờ hãy bạn hãy thử suy nghĩ phép toán sau đây trong đầu nhé nhé

15 + 17 + 8 = ? .

Khi bạn thực hiện phép toán này có phải bạn sẽ thực hiện theo trình tự 15 + 17 = 32, sau đó lấy 32 + 8 = 40 đúng không? Có phải lúc tính xong 15 + 17 = 32 bạn đã nhớ số 32 lại rồi dùng nó để cộng tiếp với 8 không?

Hay một ví dụ khác khi mẹ bảo bạn đi chợ mua:” chuối, trứng, cà chua,sữa, bột mì” bạn sẽ nhẩm đi nhẩm lại các món đồ trên để cố nhớ nó, sau đó đến chỗ mua thì vì đã nhớ rồi nên chỉ việc mua món đồ mình cần thôi. Nhưng nếu đang đi mà quên mất thì Opps! :D.

Đúng vậy, để thuận tiện xử lí các công việc hàng ngày, tính toán,.. thì bộ não chúng có một thứ gọi là trí nhớ ngắn hạn để giữ những thông tin mà ta cần xử lí. Máy tính cũng vậy với bộ não CPU của nó, cũng cần một thứ để lưu trữ thông tin gần giống như trí nhớ ngắn hạn của con người, đó là thanh ghi.

Thông tin được lưu giữ bên trong CPU nằm ở các thanh ghi. Nhưng khác với trí nhớ ngắn hạn ở con người chúng ta CPU có nhiều kiểu thanh ghi. Và nó được chia làm 3 nhóm chính:

  • Nhóm thanh ghi dữ liệu
  • Nhóm thanh ghi con trỏ
  • Nhóm thanh ghi chỉ số

Thanh ghi dữ liệu:

Có 4 thanh ghi dữ liệu:

  • EAX: thanh ghi tích lũy. Thường được dùng trong nhập xuất và các lệnh tính toán số học như nhận, chia
  • EBX: Thanh ghi cơ sở. Thường được dùng để đánh dấu địa chỉ, lưu địa chỉ bắt đầu cảu 1 mảng.
  • EDX: thanh ghi dữ liệu. Thanh ghi này cũng thường được sử dụng trong nhập xuất như EAX.
  • ECX: Thanh ghi đếm. Thường được sử dụng trong vòng lặp, đếm số lần lặp.

Mỗi thanh ghi trên được chia thành các đoạn nhỏ hơn như sau:

  • Nhỏ nhất là hai thanh ghi 8 bit AH và AL
  • Hai thanh ghi AH và AL hợp lại thành thanh ghi 16 bit AX. Trong đó AH chứa phần bit cao và AL chứ phần bit thấp của thanh ghi AX.
  • Thanh ghi AX chứa phần bit thấp của thanh ghi 32bit EAX.

Cách chia nhỏ này tương tự với 3 thanh ghi còn lại.

Bit cao và bit thấp là sao? Ví dụ với thanh AX. Thanh ghi 16 bit AX gồm 2 phần:

  • 8 bit cao AH
  • 8 bit thấp AL

Việc thay đổi giá trị của 2 thanh ghi trên sẽ làm thay đổi giá trị của AX.

Giả sử ban đầu AX = 0 thì trong AX sẽ trông như này:00000000 00000000b

Nếu ta gán giá trị 5 cho AH thì lúc này giá trị của AX sẽ là 1280: 00000101 00000000b

Nếu ta gán cho cả AH và AL giá trị 5 thì lúc này AX sẽ mang giá trị 1285:

00000101 00000101b

Việc thay đổi giá trị của AX cũng sẽ làm EAX thay đổi theo. Tuy nhiên, chúng ta chỉ có thể trực tiếp thay đổi giá trị 16bit thấp của EAX(AX), muốn thay đổi giá trị 16 bit cao của EAX thì sẽ cần sử dụng các thủ thuật khác, ví dụ như dịch bit trái(<<)

Hết số hôm nay rồi, mọi người cố gắng nhớ các cách biểu diễn dấu, kích thước lưu trữ, khái niệm cơ bản của thanh ghithanh ghi dễ hiểu nhất là thanh ghi dữ liệu. Số sau chúng ta sẽ học về thanh ghi con trỏ và các loại cờ (Flag) trong Assembly nhé <3.

Còn nữa…

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: