---
# System prepended metadata

title: 'DEADLINE 2: DUE DATE 2 WEEKS'

---

# 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 
![Screenshot 2024-01-19 151602](https://hackmd.io/_uploads/H1Lke2wF6.png)

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ờ 
![Screenshot 2024-01-19 152619](https://hackmd.io/_uploads/rJSrfhDFa.png)

* 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
![Screenshot 2024-01-23 200817](https://hackmd.io/_uploads/SkRIcN6Fa.png)

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ố

![Screenshot from 2024-01-23 08-16-41](https://hackmd.io/_uploads/S1hY3VpK6.png)

### 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.

![Screenshot from 2024-01-24 03-18-36](https://hackmd.io/_uploads/ryuzdB0ta.png)
