Bài tập: nhập hai số nguyên, tính tổng và in ra màn hình.
Video 1: https://youtu.be/JJTuWwFW2nc
Video 2: https://youtu.be/rKNuJ7QJt4Q
Video 3: https://youtu.be/cdmgwjOI5Rc
MOV – Di chuyển dữ liệu
Sao chép giá trị từ nguồn sang đích mà không làm thay đổi giá trị nguồn.
Ví dụ: `mov rax, 1` gán giá trị 1 vào thanh ghi rax.
Lưu ý là chúng ta không thể thực hiện một lệnh mov từ bộ nhớ đến bộ nhớ, để làm vậy bạn cần hai lệnh mov riêng biệt và dùng một thanh ghi làm nơi chứa giá trị trung gian.
Không phải thanh ghi nào cũng có thể được thay đổi giá trị bằng lệnh mov.
SYSCALL – Gọi hệ thống
Thực hiện lời gọi hệ thống của Linux.
Lệnh syscall chuyển điều khiển cho hệ điều hành, đồng thời đưa CPU về kernel mode, bạn cần gán giá trị thanh ghi rax bằng mã chức năng mà bạn muốn gọi.
Xem chi tiết trong bài: https://youtu.be/gefL014dGz8
CALL – Gọi thủ tục
Nhảy đến một hàm (thủ tục) và lưu địa chỉ trả về (giá trị của thanh ghi RIP) vào stack.
Nói cách khác, CPU sẽ push giá trị của RIP vào stack, sau đó gán lại RIP = địa chỉ hàm.
RET – Trả về
Quay trở lại địa chỉ được lưu bởi lệnh `call`.
Lệnh này được thực hiện bằng cách “pop” giá trị trên đỉnh stack vào thanh ghi RIP, tương tự như pop RIP (tuy nhiên bạn không thể thực hiện lệnh pop hay gán giá trị vào RIP một cách trực tiếp).
ADD – Cộng
Thực hiện phép cộng hai toán hạng. Ví dụ: `add rax, r12` cộng r12 vào rax (rax = rax + r12, hoặc rax += r12).
SUB – Trừ
Thực hiện phép trừ. Ví dụ: `sub rax, r12` tương đương với rax = rax – r12
IMUL – Nhân có dấu
Nhân hai số có dấu.
DIV – Chia không dấu
Chia rdx:rax (kết hợp hai thanh ghi lại thành một giá trị 128 bit) cho toán hạng. Kết quả thương nằm trong rax, phần dư nằm trong rdx.
Ví dụ:
div rcx
Khi đó: rax = rdx:rax / rcx và rdx = rdx:rax % rcx.
Lưu ý: tùy thuộc vào độ lớn bit của toán tử mà các thanh ghi tương ứng sẽ được dùng, nếu toán tử 8 bit thì các thanh ghi tương ứng. (Tham khảo: https://www.felixcloutier.com/x86/div)
PUSH – Đẩy vào stack
Lưu giá trị vào stack.
Đẩy giá trị vào stack, làm giảm con trỏ stack (thanh ghi rsp)
POP – Lấy khỏi stack
Lấy giá trị từ đỉnh stack, tăng con trỏ rsp.
CMP – So sánh
So sánh hai toán hạng và đặt cờ điều kiện tương ứng.
Bản chất của việc so sánh này là lấy toán hạng 1 trừ toán hạng 2, dựng lên các cờ tương ứng mà không lưu lại giá trị.
Ví dụ:
cmp rax, rbx
Đồng nghĩa với việc CPU thực hiện temp = rax – rbx, các cờ như Zero, Carry… sẽ được bật hoặc tắt dựa trên kết quả (temp), tuy nhiên temp sẽ không được lưu lại trong bất kỳ thanh ghi nào.
Lệnh cmp thường được kết hợp với các nhảy có điều kiện (các lệnh j*, ngoại trừ jmp).
JE – Jump if Equal
Nhảy nếu kết quả so sánh bằng nhau (ZF=1).
JNE – Jump if Not Equal
Nhảy nếu kết quả so sánh không bằng nhau (ZF=0).
INC – Tăng
Tăng giá trị lên 1.
DEC – Giảm
Giảm giá trị đi 1.
XOR
Thực hiện phép XOR trên bit.
Ta hay dùng để đưa một thanh ghi về 0 nhanh chóng, ví dụ `xor rax, rax`, lệnh này hiệu quả hơn mov rax, 0.
TEST – Kiểm tra bit
Thực hiện phép AND nhưng không lưu kết quả, dùng để kiểm tra điều kiện.
Tương tự lệnh CMP nhưng dùng phép AND thay vì phép trừ, ta thường dùng để kiểm tra một bit nào đó đang bật hoặc tắt, hoặc cũng dùng để kiểm tra một thanh ghi có khác 0 hay không.
JNZ – Jump if Not Zero
Nhảy nếu kết quả khác 0 (ZF=0).