# Tìm hiểu về ngôn ngữ Assembly ## Tổng quan về ASM - Assembly là gì? Theo như em tìm hiểu thì Assembly là một ngôn ngữ lập trình bậc thấp được sử dụng cho các bộ vi xử lý hoặc các thiết bị có lập trình thông qua các câu lệnh mà vi xử lý có thể hiểu được. - Để tạo ra ngôn ngữ Assembly, các lập trình viên sẽ sử dụng cách biên dịch mã nguồn từ một ngôn ngữ lập trình cấp cao hơn. Giả sử như từ C++ -> C -> Assembly. - Assembly được chuyển đổi thành mã máy có thể thực thi được (excutable machine code) bằng một chương trình tiện ích được gọi là trình biên dịch mã như NASM, MASM,... ## Lợi ích khi học Assembly - ### Hiểu biết về Asembly giúp nhận thức được : - Cách các chương trình giao tiếp với hệ điều hành, bộ vi xử lý và BIOS. - Cách mà dữ liệu được thể hiện trong bộ nhớ và các thiết bị bên ngoài khác. - Cách mà bộ xử lý truy cập và thi hành lệnh. - Cách hướng dẫn truy cập và xử lý dữ liệu. - Cách mà một chương trình truy cập vào thiết bị bên ngoài. - ### Các ưu điểm khác trong việc sử dụng Assembly là : - Yêu cầu ít bộ nhớ và thời gian thực hiện hơn. - Cho phép các công việc phức tạp dành riêng cho phần cứng một cách dễ dàng hơn. - Phù hợp cho các công việc quan trọng về thời gian. - Phù hợp nhất để viết các chương trình dịch vụ ngắt và các chương trình lưu trữ trong bộ nhớ khác. # Cấu trúc của 1 chương trình ASM - Một chương trình hợp ngữ có thể được chia thành ba phần : `section .data` `section .bss` `section .text` ### Data section - Dùng để khai báo dữ liệu hoặc hằng số khởi tạo. - Dữ liệu này không thay đổi trong thời gian chạy. - Các giá trị trong phần này sẽ là không đổi. ### Bss Section - Được sử dụng để khai báo các biến. ### Text Section - Được sử dụng để giữ code thực tế. - Phần này phải bắt đầu bằng khai báo `global _start`, thông báo cho kernel biết nơi bắt đầu thực hiện chương trình. ``` section .text global _start _start: ``` ### Comments - Chúng ta cũng có thể sử dụng dấu `;` để ghi chú hoặc nhận xét. - VD : `;Tên tôi là gì ?` # Thanh ghi - Thanh ghi là một thành phần của CPU, là thành phần lưu trữ tốc độ cao với dung lượng lưu trữ hạn chế, được sử dụng để lưu trữ tạm thời các lệnh, dữ liệu và địa chỉ. - Các thanh ghi lưu trữ các phần tử dữ liệu để xử lý mà không cần phải truy cập vào bộ nhớ. - Có 4 thanh ghi dữ liệu 32-bit được dùng cho số học,logic,và hoạt động khác. Những thanh ghi này được dùng theo 3 cách : - *Là các thanh ghi dữ liệu 32 bit hoàn chỉnh: EAX, EBX, ECX, EDX.* - *Nửa dưới của thanh ghi 32 bit có thể được sử dụng làm bốn thanh ghi dữ liệu 16 bit: AX, BX, CX và DX.* - *Nửa dưới và nửa trên của bốn thanh ghi 16 bit nêu trên có thể được sử dụng làm tám thanh ghi dữ liệu 8 bit: AH, AL, BH, BL, CH, CL, DH và DL.* - Các thanh ghi được chia thành 3 loại : - **Thanh ghi đa năng** - **Thanh ghi đoạn** - **Thanh ghi điều khiển** ## 1.Thanh ghi đa năng - Các thanh ghi đa năng được chia thành 3 loại : ### Thanh ghi data - EAX : Thanh ghi chính được sử dụng trong tính toán số học chứa kết quả của các phép tính số học và giá trị trả về của hàm. - EBX : Thanh ghi cơ sở được sử dụng để lưu trữ địa chỉ cơ sở của chương trình. - ECX : Thanh ghi bộ đếm thường được sử dụng để giữ giá trị biểu thị số lần một quá trình được lặp lại. Được sử dụng cho các hoạt động vòng lặp và chuỗi. - EDX : được dùng tương tự như EAX ngoài ra sẽ mở rộng EAX lên 64-bit. ### Thanh ghi con trỏ - EIP : Lưu trữ địa chỉ của lệnh tiếp theo sẽ được thực thi. - EBP : Con trỏ cơ sở trỏ đến cuối khung ngăn xếp hiện tại. Nó được sử dụng để tham chiếu các biến cục bộ. - ESP : Con trỏ ngăn xếp . Nó trỏ đến đầu khung ngăn xếp hiện tại. Nó được sử dụng để tham chiếu các biến cục bộ. ### Thanh ghi chỉ thị - ESI : Thanh ghi chỉ mục nguồn được sử dụng làm địa chỉ nguồn cho các phép toán với xâu. - EDI : Thanh ghi được sử dụng làm địa chỉ đích cho các phép toán với xâu. ## 2.Thanh ghi đoạn - CS : Thanh ghi đoạn mã lưu trữ vị trí cơ sở của phần mã (section .text) được sử dụng để truy cập dữ liệu. - DS : Thanh ghi phân đoạn dữ liệu lưu trữ vị trí mặc định cho các biến (phần .data) được sử dụng để truy cập dữ liệu. - SS: chứa dữ liệu và địa chỉ trả về của các chương trình con. - ES : Thanh ghi phân đoạn bổ sung được sử dụng trong các hoạt động chuỗi. - FS : Thanh ghi phân đoạn bổ sung. - GS : Thanh ghi phân đoạn bổ sung. ## 3.Thanh ghi điều khiển - Thanh ghi con trỏ lệnh 32 bit và thanh ghi cờ 32 bit kết hợp được coi là thanh ghi điều khiển. Có các thanh ghi cờ như sau: - CF : Mang cờ - PF : Cờ chẵn lẻ - AF : Cờ điều chỉnh - ZF : Cờ không - SF : Cờ hiệu - OF : Cờ tràn ## Một số lệnh phổ biến thường được dùng - `mov` : Dùng để gán giá trị. - `add, sub` : Tính tổng, hiệu. - `inc` : Tăng giá trị lên 1. - `dec` : Giảm giá trị đi 1. - `add` : Thêm nội dung của biến này vào biến kia. - `cmp` : So sánh hai giá trị với nhau. - `push` : Đẩy giá trị vào. - `pop` : Lấy giá trị ra. ## Cách biên dịch và liên kết một chương trình Assembly trong NASM - Đầu tiên tạo 1 file có đuôi là `.asm`, ví dụ là `hello.asm` ![Screenshot 2024-02-29 000253](https://hackmd.io/_uploads/r1sID1Tnp.png) - Sau đó gõ `nasm -f elf32 -o hello.o hello.asm` để tạo ra 1 file object ![Screenshot 2024-02-29 003506](https://hackmd.io/_uploads/Byp00JTha.png) - Để liên kết tệp đối tượng và tạo tệp thực thi có tên hello, hãy nhập `ld -m elf_i386 -o hello hello.o` ![Screenshot 2024-02-29 003735](https://hackmd.io/_uploads/HJqOJepnT.png) - Thực thi chương trình bằng cách gõ `./hello` # Task 1 ## Chương trình in ra `Hello, world!` ``` section .data text db "Hello, world!", 0xa len equ $ - text section .text global _start _start: mov eax, 4 mov ebx, 1 mov ecx, text mov edx, len int 0x80 mov eax, 1 int 0x80 ``` - Ở phần `section .data` khai báo biến có tên là `text` với kiểu dữ liệu là byte `db` (define bytes) và `0xa` là kí tự xuống dòng. - `len equ $ - text` ở đây chính là độ dài của biến text. - `_start` cho biết điểm vào của trình liên kết. - `int 0x80` ở đây là lệnh gọi hệ thống. - `mov eax, 1` là lệnh gọi hàm ngắt để ngắt chương trình. - Và đây là kết quả : ![Screenshot 2024-02-29 010837](https://hackmd.io/_uploads/HJr0LgT26.png) ## Chương trình nhập vào một chuỗi và in ra từng kí tự - Demo : ![Screenshot 2024-03-13 202402](https://hackmd.io/_uploads/SJbdYmJRp.png) - Bài này cách làm của em là nhập vào 1 chuỗi sau đó kiểm tra xem từng kí tự trong chuỗi có thuộc khoảng từ A - Z và a - z hay không. Nếu thỏa mãn thì in ra còn không thỏa mãn thì bỏ qua kí tự đó và chuyển đến kí tự tiếp theo. - Code: ``` section .data msg1 db "Input: ", 0xa len1 equ $ - msg1 msg2 db "Output: ", 0xa len2 equ $ - msg2 newline db 10 section .bss string resb 255 section .text global _start _start: ; In ra "Input:" mov eax, 4 mov ebx, 1 mov ecx, msg1 mov edx, len1 int 0x80 ; Nhập chuỗi từ bàn phím mov eax, 3 mov ebx, 0 mov ecx, string mov edx, 255 int 0x80 ; In ra "Output: " mov eax, 4 mov ebx, 1 mov ecx, msg2 mov edx, len2 int 0x80 mov esi, string ; Dùng thanh ghi ESI để trỏ vào đầu chuỗi loop: mov al, [esi] ; Đọc kí tự từ chuỗi cmp al, 0 ; Kiểm tra xem kí tự kết thúc chuỗi je end ; Nếu là kí tự kết thúc thì thoát khỏi vòng lặp và kết thúc chuỗi ; Kiểm tra xem kí tự có là chữ cái hay không cmp al, "A" jl not_char cmp al, "Z" jle print_char cmp al, "a" jl not_char cmp al, "z" jle print_char print_char: mov eax ,4 mov ebx, 1 mov ecx, esi mov edx, 1 int 0x80 inc esi jmp loop ; Bỏ qua kí tự không phải là chữ cái not_char: inc esi jmp loop end: mov eax, 4 mov ebx, 1 mov ecx, newline mov edx, 1 int 0x80 mov eax, 1 mov ebx, 0 int 0x80 ``` - Ở phần `section .bss` khai báo biến string dùng để lưu chuỗi đã được nhập vào với độ dài tối đa là 255 kí tự. - Ở phần kiểm tra kí tự ví dụ ở đoạn này : ``` cmp al, "A" jl not_char cmp al, "Z" jle print_char ``` - So sánh kí tự của chuỗi với "A", jl ở đây có nghĩa là jump less tức là nếu nhỏ hơn "A" thì sẽ không phải là kí tự và nhảy đến not_char. not_char sẽ bỏ qua kí tự không thuộc A-Z và a-z sau đó tăng esi lên 1 đơn vị để chuyển qua kí tự tiếp theo của chuỗi và bắt đầu lại vòng lặp. Tương tự so sánh với "Z", jle tức là nếu nhỏ hơn hoặc bằng "Z" thì là kí tự và nhảy đến print_char. print_char sẽ in ra kí tự thỏa mãn và chuyển đến kí tự tiếp theo để so sánh tiếp. - Ở phần end thì chỉ in ra kí tự xuống dòng sau đó exit và ngắt hệ thống là xong. # Task 2 ## SelectionSort -