# DEADLINE 2: DUE DATE 29/1/2024
> Tìm hiểu về ngôn ngữ assembly, viết báo cáo chi tiết hết về những gì mà bản thân tìm hiểu được.(Ít nhất phải đủ để code được 2 chương trình bên dưới, thiếu có thể bổ sung tiếp trong task sau) Có thể tham khảo nguồn dưới đâu hoặc bất kì nguồn nào khác tìm được
Tài liệu: https://www.tutorialspoint.com/assembly_programming/assembly_tutorial.pdf
Code 2 chương trình sau:
-Fibonacci
-Selection Sort
Vẽ graph mô tả code asm của 2 bài, comment giải thích những đoạn chính
Deadline: 11:59 24/1/2024
## TÌM HIỂU VỀ ASM P2
### I. Các câu lệnh điều kiện (Conditional Command)
#### 1. Lệnh CMP
* Lệnh CMP so sánh hai toán hạng thường được sử dụng trong thực thi có điều kiện. Lệnh này về cơ bản trừ một toán hạng với toán hạng kia để so sánh xem các toán hạng có bằng nhau hay không.
* CMP so sánh hai trường dữ liệu số. Toán hạng đích có thể nằm trong thanh ghi hoặc trong bộ nhớ. Toán hạng nguồn có thể là dữ liệu, thanh ghi hoặc bộ nhớ không đổi (tức thời). **Ví dụ :**
```
CMP DX, 00 ; So sánh DX với giá trị 00
JE Equal ; Nếu bằng thì jump tới Equal
```
#### 2. Lệnh nhảy vô điều kiện (Unconditional Jump)
* Được thực hiện bởi lệnh `JMP`. Thực thi có điều kiện thường liên quan đến việc chuyển quyền điều khiển đến địa chỉ của lệnh không tuân theo lệnh hiện đang thực thi. Việc chuyển giao quyền điều khiển có thể tiến tới để thực hiện một tập lệnh mới hoặc lùi lại để thực hiện lại các bước tương tự.
#### 3. Lệnh nhảy có điều kiện (Conditional Jump)
* Nếu một số điều kiện xác định được thỏa mãn trong bước nhảy có điều kiện, luồng điều khiển sẽ được chuyển sang lệnh đích. Có rất nhiều lệnh nhảy có điều kiện tùy thuộc vào điều kiện và dữ liệu.
Sau đây là các lệnh nhảy có điều kiện được sử dụng trên dữ liệu đã ký được sử dụng cho các phép tính số học

1. JE/JZ : Nhảy bằng hoặc nhảy bằng 0
2. JNE/JNZ : Nhảy ko bằng hoặc nhảy khác 0
3. JG/JNLE : Nhảy lớn hơn hoặc nhảy không ít hơn/bằng
4. JGE/JNL : Nhảy lớn hơn/bằng hoặc nhảy không ít hơn
5. JL/JNGE : Nhảy ít hơn hoặc nhảy không lớn hơn/bằng
6. JLE/JNG : Nhảy ít hơn/bằng hoặc nhảy không lớn hơn
Còn bảng này sẽ là các lệnh nhảy có điều kiện sử dụng đặc biệt và kiểm tra giá trị của cờ

* JXCZ : Nhảy nếu CX bằng 0
* JC : Nhảy nếu cờ CF được set
* JNC : Nhảy nếu cờ CF không được set
* JO : Nhảy nếu tràn
* JNO : Nhảy nếu không tràn
* JP/JPE : Nhảy nếu chẵn
* JNP/JPO : Nhảy nếu không chẵn hoặc nhảy nếu lẻ
* JS : Nhảy nếu có dấu(Giá trị âm)
* JNS : Nhảy không dấu(Giá trị dương)
### II. Vòng lặp
* Các lệnh jump có thể được sử dụng để thực hiện vòng lặp như jmp, je, jne, jl, jg, jle, jge, và các cấu trúc điều khiển khác để tạo vòng lặp.
Chương trình dưới đây là lệnh in chuỗi 'Nguyen Minh Triet' 10 lần
```
section .data
msg db 'Nguyen Minh Triet', 0xa
len equ $ - msg
section .text
global _start:
_start:
mov edi, 10
L1:
mov eax, 4
mov ebx, 1
mov ecx, msg
mov edx, len
int 0x80
DEC edi
JNZ L1
mov eax, 1
int 0x80
```
### III. Array
* Mảng là một tập hợp các giá trị được lưu trữ liên tiếp trong bộ nhớ. Mảng thường được sử dụng để lưu trữ và xử lý nhiều dữ liệu cùng loại.
* Để khai báo một mảng trong NASM, sử dụng các instruction db (define byte) hoặc dw (define word) để xác định kích thước của mỗi phần tử trong mảng.
* Ví dụ, đoạn mã sau khai báo một mảng có 5 phần tử kiểu word (2 byte) và khởi tạo giá trị ban đầu là 1, 2, 3, 4, 5:
```
array dw 1, 2, 3, 4, 5
```
### SYSCALL
* Trong NASM, syscall là một lệnh được sử dụng để gọi các hệ thống gọi (system call) trong hệ điều hành. Lệnh syscall cho phép chương trình ASM tương tác với các dịch vụ hệ thống như đọc/ghi tệp, nhập/xuất trên màn hình, cấp phát bộ nhớ, và nhiều hoạt động hệ thống khác.
* Trước khi thực hiện lệnh syscall, các tham số của hệ thống gọi được truyền vào các thanh ghi chứa các giá trị thích hợp. Sau khi lệnh syscall được gọi, kết quả của hệ thống gọi có thể được trả về qua các thanh ghi khác, chẳng hạn như thanh ghi eax
Đây là bảng 4 syscall thường được dùng nhất khi lập trình NASM

1. exit: Lệnh này được sử dụng để thoát khỏi chương trình và trả về giá trị thoát. Tham số truyền vào thông qua thanh ghi ebx để chỉ định mã thoát.
2. write: Lệnh này được sử dụng để ghi dữ liệu từ một bộ đệm (buffer) lên một file hoặc STDOUT (màn hình). Tham số truyền vào thông qua các thanh ghi ebx, ecx, edx để chỉ định file descriptor, địa chỉ bộ đệm và số lượng byte cần ghi.
3. read: Lệnh này được sử dụng để đọc dữ liệu từ một file hoặc STDIN (bàn phím) vào một bộ đệm. Tham số truyền vào thông qua các thanh ghi ebx, ecx, edx để chỉ định file descriptor, địa chỉ bộ đệm và số lượng byte cần đọc.
4. open: Lệnh này được sử dụng để mở một file và trả về file descriptor tương ứng. Tham số truyền vào thông qua các thanh ghi ebx, ecx, edx để chỉ định đường dẫn file, flags và mode.
5. close: Lệnh này được sử dụng để đóng một file descriptor đã mở trước đó. Tham số truyền vào thông qua thanh ghi ebx để chỉ định file descriptor cần đóng.
## CODING
### Code Selection Sort
```
section .text
global _start
_start:
mov eax, 0x4
mov ebx, 0x1
mov ecx, msg1
mov edx, len1
int 0x80
mov eax, 0x3
mov ebx, 0
mov ecx, quant
mov edx, 0xa
int 0x80
dec eax
mov ebx, ecx
mov ecx, eax
call _converstring
mov dword [Numberscount], eax
mov ecx, eax
xor edi, edi
call _ArrayIn
call _selectionSort
mov eax, 0x4
mov ebx, 0x1
mov ecx, msg4
mov edx, len4
int 0x80
mov ecx, dword [Numberscount]
call _ArrayOut
mov eax, 0x1
int 0x80
_selectionSort:
xor eax, eax
xor ebx, ebx
xor ecx, ecx
xor edx, edx
xor edi, edi
xor esi, esi
ForI:
mov edx, esi
mov edi, esi
ForJ:
mov eax, dword [arr + 4 * edx]
mov ecx, dword [arr + 4 * edi]
cmp eax, ecx
jl continue
mov edx, edi
continue:
inc edi
cmp edi, [Numberscount]
jne ForJ
mov eax, dword [arr + 4 * edx]
mov ecx, dword [arr + 4 * esi]
mov dword [arr + 4 * edx], ecx
mov dword [arr + 4 * esi], eax
inc esi
cmp esi, [Numberscount]
jne ForI
ret
_converstring:
xor edx, edx
xor eax, eax
xor esi, esi
stringToNum:
mov edx, 10
mul edx
mov dl, [ebx + esi]
sub edx, 0x30
add eax, edx
inc esi
loop stringToNum
ret
_convertnum:
mov ecx, 0
mov [F], ecx
cmp eax, 2147483648
jna c0nt1nu3
inc ecx
mov edx, 0x1
mov [F], edx
mov edx, 0xffffffff
sub edx, eax
mov eax, edx
c0nt1nu3:
execute:
xor edx, edx
mov ebx, 10
div ebx
add edx, 0x30
push edx
inc ecx
cmp eax, 0
jne execute
mov edx, 0x1
cmp [F], edx
jne Cont1nue
push edx
Cont1nue:
mov ebp, 0
L00P:
pop edx
mov [num + ebp], edx
inc ebp
loop L00P
ret
_ArrayIn:
mov [counti], ecx
loop:
xor eax, eax
mov eax, edi
call _convertnum
mov eax, 0x3
mov ebx, 0x0
mov ecx, A
mov edx, 0xa
int 0x80
dec eax
mov ebx, ecx
mov ecx, eax
call _converstring
mov dword [arr + 4 * edi], eax
inc edi
cmp edi, [Numberscount]
jne loop
ret
_ArrayOut:
mov esi, 0
outloop:
mov eax, dword [arr + 4 * esi]
call _convertnum
mov eax, 0x4
mov ebx, 0x1
mov ecx, num
mov edx, ebp
int 0x80
mov eax, 0x4
mov ebx, 0x1
mov ecx, 0x20
mov edx, 0x1
int 0x80
inc esi
cmp esi, [Numberscount]
jne outloop
mov eax, 0x4
mov ebx, 0x1
mov ecx, 0xa
mov edx, 0x1
int 0x80
ret
section .data
msg1 db 'Enter the number of the array '
len1 equ $-msg1
msg4 db 'The array after sorting is: '
len4 equ $-msg4
num times 35 db ''
numLen equ $ - num
quant db '0'
arr times 512 dd 0
A times 20 db 0
counti dd 0
Numberscount dd 0
F db 0
```
1. Label `_ArrayIn`: Đây là một subroutine để đọc mảng từ đầu vào. Nó được gọi từ `_start` để đọc các phần tử của mảng từ người dùng.
2. Label `_selectionSort`: Đây là một subroutine để triển khai thuật toán sắp xếp chọn trên mảng. Nó được gọi từ `_start` để sắp xếp các phần tử của mảng.
3. Label `_ArrayOut`: Đây là một subroutine để in ra mảng đã được sắp xếp. Nó được gọi từ `_start` để in ra màn hình các phần tử của mảng.
4. Label `_convertNum`: Chuyển đổi số thành chuỗi.
5. Label `_convertString`: chuyển đổi chuỗi thành số

### Code Fibonacci
```
section .text
global _start
_start:
mov eax, 0x4
mov ebx, 0x1
mov ecx, msg
mov edx, msgLen
int 0x80
mov eax, 0x3
mov ebx, 0x0
mov ecx, num1
mov edx, 0xe
int 0x80
dec eax
mov ecx, eax
mov ebx, num1
call _convertString
mov ecx, eax
call _Fibo
call _convertNum
mov eax, 0x4
mov ebx, 0x1
mov ecx, msg2
mov edx, msg2len
int 0x80
mov eax, 0x4
mov ebx, 0x1
mov ecx, num2
mov edx, ebp
int 0x80
mov eax, 0x1
int 0x80
_Fibo:
mov eax, 0x1
mov ebx, 0x0
xor esi, esi
cmp ecx, 0x2
jg Fib
ret
Fib:
mov esi, eax
add eax, ebx
mov ebx, esi
loop Fib
mov eax, ebx
ret
_convertNum:
mov ecx, 0
running:
xor edx, edx
mov ebx, 10
div ebx
add edx, 0x30
push edx
inc ecx
cmp eax, 0
jne running
mov ebp, 0
LOOP:
pop edx
mov [num2 + ebp], edx
inc ebp
loop LOOP
ret
_convertString:
xor edx, edx
xor eax, eax
xor esi, esi
stringToNum:
mov edx, 10
mul edx
mov dl, [ebx + esi]
sub edx, 0x30
add eax, edx
inc esi
loop stringToNum
ret
section .data
msg db 'Nhap n: '
msgLen equ $ - msg
msg2 db 'So Fibo la: '
msg2len equ $ - msg2
num1 times 100 db 0
num2 times 100 db ''
len db 0
```
* **Phần .data:**
1. msg là chuỗi "Nhap n: " để hiển thị thông báo nhập số n.
2. msgLen là kích thước của chuỗi msg.
3. msg2 là chuỗi "So Fibo la: " để hiển thị thông báo kết quả.
4. msg2len là kích thước của chuỗi msg2.
5. num1 là mảng 35 byte để lưu giá trị của số n nhập vào.
6. num2 là mảng 35 byte để lưu giá trị của số Fibonacci tính được.
7. len là biến 1 byte để lưu độ dài của số n nhập vào.
* **Phần .text:**
1. Gọi hàm hệ thống để hiển thị thông báo "Nhap n: ":
2. Đọc số n từ người dùng:
3. Chuyển đổi số n từ dạng chuỗi sang dạng số nguyên:
4. Tính số Fibonacci thứ n:
- Chương trình gọi hàm _Fibo để tính số Fibonacci thứ n.
- Đầu tiên, chương trình đặt giá trị 0 vào thanh ghi ebx và giá trị 1 vào thanh ghi eax.
- Bằng cách sử dụng vòng lặp loop, chương trình tính số Fibonacci bằng cách cộng giá trị của eax và ebx.
5. Chuyển đổi số Fibonacci từ dạng số nguyên sang dạng chuỗi:
- Sau khi tính được số Fibonacci, chương trình gọi hàm _convertNum để chuyển đổi giá trị số Fibonacci từ dạng số nguyên sang dạng chuỗi và lưu vào mảng num2.
