## :file_folder: Chapter :five: : THE BASIC CONCEPTS OF ASM LANGUAGE
### I. What is Assembly Language ?
<center>
<img src = https://cdn.educba.com/academy/wp-content/uploads/2019/10/Assembly-Language-vs-Machine-Language.jpg>
</center>
* **Introduction about Machine Language**
:::spoiler
* Là loại ngôn ngữ nhân tạo (ví dụ: C / C++) được cấu thành bởi hai yếu tố chính:
* Từ vựng: là các keywords (struct, enum, if, int, ...)
* Ngữ pháp: syntax (if(...){}else{}, do{}while()...)
* Ngôn ngữ lập trình giúp cho người sử dụng nó (gọi là lập trình viên) có thể diễn đạt và mô tả các hướng dẫn cho máy tính hoạt động theo ý muốn của mình.
* Độ phức tạp (trừu tượng) của các íntructions này quyết định thứ bậc của ngôn ngữ.
* Độ phức tạp càng cao thì bậc càng thấp
* Ví dụ: C sharp (C#) là ngôn ngữ bậc cao hơn C.
* Ngôn ngữ nào mà con người dễ hiểu nhất lại là ngôn ngữ máy tính "khó hiểu" nhất.
* Ngôn ngữ bậc càng cao thì con người càng dễ hiểu nhưng máy tính lại càng "khó hiểu".
* Nhưng máy tính lại là nơi chúng ta cần nó hiểu đúng và nhanh nhất để có thể thực thi những gì chúng ta muốn $\Rightarrow$ ==Ngôn ngữ máy (Machine Language)==
<center>
<img src = https://scontent.fsgn2-10.fna.fbcdn.net/v/t1.15752-9/403401957_3803337269977205_6020317758597267746_n.png?_nc_cat=109&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=JnSdq-oq7DMAX_CDUmX&_nc_ht=scontent.fsgn2-10.fna&oh=03_AdTL9fOT09aAaGshNgXE-sS-ByOGr-FVHNBIeQtHp1Y8vA&oe=65AB1DDF>
</center>
* Ngôn ngữ máy (machine language) cho phép người lập trình đưa ra các hướng dẫn đơn giản mà bộ vi xử lý (micro - processor in CPU) có thể thực hiện được ngay.
* Các hướng dẫn này được gọi là chỉ thị / lệnh (instruction) hoặc mã máy (machine code).
* Mỗi bộ vi xử lý (micro-processor in CPU) có 01 ngôn ngữ lập trình riêng, gọi là bộ lệnh (instruction set).
* Trong cùng một dòng vi xử lý (micro-processor family) bộ lệnh gần giống nhau.
<center>
<img src = https://scontent.fsgn2-4.fna.fbcdn.net/v/t1.15752-9/410470643_309650125387926_5064503553777882787_n.png?_nc_cat=101&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=MkIb7e3t8SwAX8qkyzD&_nc_ht=scontent.fsgn2-4.fna&oh=03_AdSM1Wegu8gS8pIGnitp-w1fSu_A0dX5mG9_cMYuPFl32Q&oe=65AB3DA6>
</center>
* Tuy nhiên, không phải ai cũng muốn / có thể lập trình ngôn ngữ máy vì nó quá khó hiểu so với ngôn ngữ bình thường của con người.
**$\Rightarrow$ Nhu cầu cần có ==bộ phận biên dịch (interpret)==**
<center>
<img src = https://scontent.fsgn2-10.fna.fbcdn.net/v/t1.15752-9/410701558_715253310546092_1188368784838424768_n.png?_nc_cat=109&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=DvfIrJ6v-voAX_mfgTG&_nc_ht=scontent.fsgn2-10.fna&oh=03_AdSFSOemoQ8zF-NdRdlry9aobga_DyZKP1CB7DXPXOG3Rw&oe=65AB52E2>
</center>
* Trong một số trường hợp, việc viết bằng ngôn ngữ "quá cao" trở nên chạy ==khá chậm== vì phải ==phiên dịch nhiều lần== để trở thành ngôn ngữ máy
$\Rightarrow$ ==**Hợp ngữ (Assembly Language)**==
<center>
<img src = https://scontent.fsgn2-3.fna.fbcdn.net/v/t1.15752-9/412114815_3637141419892883_4974201660529932067_n.png?_nc_cat=107&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=qRGQYCQ8eMIAX815Q5-&_nc_ht=scontent.fsgn2-3.fna&oh=03_AdTcikpr8qWHwpsyRQmB3IKrf36fTl1NCc5rk76V70m9Gg&oe=65AB2C86>
</center>
:::
* **ISA (Instruction Set Architecture)**
:::spoiler
* Tập lệnh dành cho những bộ vi xử lý có kiến trúc tương tự nhau.
* Một số ISA thông dụng:
* Dòng vi xử lý 80x86 (gọi tắt là x86) của Intel
* IA - 16 : Dòng xử lý 16 bit (Intel 8086, 80186, 80286)
* IA - 32 : Dòng xử lý 32 bit (Intel 80386 - i386, 80486 - i486, Pentium II, Pentium III, ...)
* IA - 64 : Dòng xử lý 64 bit (Intel x86-64 như Pentium D, ...)
* MIPS: Dùng rất nhiều trong hệ thống nhúng (embedded system)
* PowerPC của IBM
* Thiết kế ISA : CISC & RISC
* Có 02 trường phái thiết kế bộ lệnh:
* ==**Completed Instruction Set Computer (CISC)**== : bộ lệnh gồm rất nhiều lệnh, từ đơn giản đến phức tạp.
* ==**Reduced Instruction Set Computer (RISC)**== : bộ lệnh chỉ gồm các lệnh đơn giản.
:::
* **Introduction about Processor**
:::spoiler
* Each ==personal computer== has a ==micro-processor== that manages the computer's **arithmetical**, **logical**, and **control activities**.
* Each family of processors has its own set of instructions for handling various operations. They are called `machine language instructions (MLIs)`.
:::
* **Definition of Assembly Language**
:::spoiler
* In computer programming, assembly language (alternatively assembler language or symbolic machine code),often referred to simply as assembly and commonly abbreviated as ASM or asm, is any ==low-level programming language== with a very strong correspondence between the instructions in the language and the architecture's machine code instructions. Assembly language usually has one statement per machine instruction (1:1), but constants, comments, assembler directives, symbolic labels of, e.g., memory locations, registers, and macros are generally also supported.
:::spoiler
* Các mã máy chỉ là các con số (0 / 1)
* Trong ngôn ngữ máy không có khái niệm biến $\to$ thay vào đó là địa chỉ của ô nhớ, thanh ghi (lưu trữ mã lệnh, dữ liệu).
* Để dễ dàng lập trình hơn $\to$ dùng ký hiệu ==mã giả== (pseudo - code) thay cho các số biểu diễn địa chỉ ô nhớ, các tên (label, tên biến, tên chương trình).
* Hợp ngữ rất gần với ngôn ngữ máy nhưng lại đủ để con người hiểu và sử dụng tốt honw machine language (ngôn ngữ máy).
* ++Ví dụ:++ Ghi giá trị 5 vào thanh ghi $4
Ngôn ngữ máy : 00110100 00000100 00000000 00000101
Hợp ngữ : ori $4, $0, 5
* Lưu ý:
* Vì mỗi bộ vi xử lý có 1 cấu trúc thanh ghi và tập lệnh (ngôn ngữ) riêng nên khi lập trình hợp ngữ phải nói rõ là lập trình cho bộ vi xử lý nào, hay dòng (family) vi xử lý nào.
* ++Ví dụ:++
* Hợp ngữ cho MIPS
* Hợp ngữ cho dòng vi xử lý Intel 80x86
:::
:::
* **Why we use Assembly Language ?**
:::spoiler
* ++A processor understands only MLIs++, which are series of 1's and 0's. ML is too ==obscure== and ==complex== for programming. So, the assembly language (AL) is designed to ==make programmer's job easier==.
:::
* **What are mnemonics ?**
:::spoiler
* In Assembly Language, an instruction is an ==easy-to-remember form== called a ==mnemonic==.
* Mnemonics are the symbolic representation of machine-level instructions. Moreover, it is used by programmers so that they can remember machine level processes easily.
:::
* **Assembler :vs: Compiler :vs: Interpreter**
:::spoiler
<center>
<img src = https://scontent.fsgn8-4.fna.fbcdn.net/v/t1.15752-9/412645757_1066192774573896_4228155463660598822_n.png?_nc_cat=111&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=ohLblFvuZ8YAX-j1J2w&_nc_ht=scontent.fsgn8-4.fna&oh=03_AdQGetYdm1a4uKi2IRIxJryqj81ATaafd30hy97dV95bWw&oe=65AB6077>
</center>
* **What is Assembler ?**
:::spoiler
* Assembler is the software which translates **Assembly Language instructions** into **MLIs (Machine Language Instructions)**.
:::spoiler
* ==Trình biên dịch từ hợp ngữ (Assembly Language) $\to$ ngôn ngữ máy (Machine Language)==
* Một bộ vi xử lý (đi kèm một bộ lệnh xác định) có thể có nhiều Assembler của nhiều nhà cung cấp khác nhau chạy trên các OS khác nhau.
* ++Ví dụ:++ Cùng là kiến trúc x86, nhưng có thể dùng *A86*, *GAS*, *TASM*, *MASM*, *NASM*.
* Assembly program phụ thuộc vào Assembler mà nó sử dụng (do các mở rộng, đặc điểm khác nhau giữa các Assembler).
:::
* Types of Assembler : On the basic of a the number of phases used to convert to machine code, assemblers have two types:
:::spoiler
1. One - Pass Assemblers : perform the whole conversion of assembly code to machine code in one go.
2. Multi - Pass / Two - Pass Assemblers
* These assemblers first process the assembly code and store values in the ==**opcode table**== and ==**symbol table**==. And then in the second step, they generate the mcachine code using these tables.
* Pass 1
* Symbol tables and opcode tables are defined.
* Keep the record of the **location counter**
* Also, processes the pseudo instructions.
* Pass 2
* Finally, converts the opcode into the corresponding mumeric opcode.
* Generates machine code according to values of literals and symbols.
:::
* Some Important Terms
:::spoiler
* ==**Opcode Tables**== store the value of mnemonics and their corresponding numeric values.
* ==**Symbol Tables**== store the value of programming language symbols used by the programmers, and their corresponding numeric values.
* ==**Location Counter**== stores the address of the location where the current instruction will be stored.
:::
:::
* **What is Compiler ?**
:::spoiler
* A compiler is a ==software== that converts the source code to the object code. In other words, we can say that it converts the ==high-level language== to ==machine/binary language==. Moreover, it is necessary to perform this step to make the program executable. This is because the computer understands only binary language.
* Some compilers convert the high-level language to an assembly language as an intermediate step. Whereas some others convert it directly to machine code.
$\Rightarrow$ This process of converting the source code into machine code is called ==**compilation**==.
:::spoiler
* ==Trình biên dịch ngôn ngữ cấp cao $\to$ hợp ngữ==
* Compiler phụ thuộc vào:
* Ngôn ngữ cấp cap được biên dịch
* Kiến trúc hệ thống phần cứng bên dưới mà nó đang chạy
* ++Ví dụ:++
* Compiler cho C <> Compiler cho Java
* Compiler cho "C on Windows" <> "C on Linux"
:::
* Types of Compilers
1. Cross Compilers : produce an executable machine code for a flatform but, this platform is not on the one on which the compiler is running.
3. Bootstrap Compilers : are written in a programming language that they have to compile.
4. Source to Scource / Transcompilers convert the source code of one programming language to the source code of another programming language.
5. Decompiler : Basically, it is not a compiler. It is just the reverse of the compiler. It converts the machine code into the high-level language code.
* Features of a Compiler
* Compilation speed
* The correctness of machine code
* The meaning of code should not change
* Speed of machine code
* Good error detection
* Checking the code correctly according to grammar
* Uses / Applications of Compilers
* Helps to make the code independent of the platform
* Makes the code free of syntax and semantic errors
* Generate excutable files of code
* Translates the code from one language to another
:::
* **What is Interpreter ?**
:::spoiler
* An ==interpreter== is a program that directly executes the instructions in a high-level language, without converting it into machine code. In programming, we can execute a program in two ways. Firstly, through compilation and secondly through an interpreter. The common way is to use a compiler.
<center>
<img src = https://scontent.fsgn2-5.fna.fbcdn.net/v/t1.15752-9/412634604_1066918054434798_1004389718570323634_n.png?_nc_cat=104&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=SyViJ74J7VcAX8hPXaB&_nc_ht=scontent.fsgn2-5.fna&oh=03_AdTU9dAXHJ-qf753tldCxyGgBE5HmVuS3R8YEzpBi55Giw&oe=65ABC62A>
</center>
* Stragies of an Interpreter
* It can work i three ways:
* Execute the source code directly and produce the output.
* Translate the source code in some intermediate code and then execute this code.
* Using an internal compiler to produce a precompiled code. Then, execute this precompiled code.
* Types of Interpret in Programming
1. Bytecode Interpreters
- The source code is firstly converted to bytecode.
- Bytecode is a compressed and optimized representation of source code. But, it is not the machine code.
- The bytecode interpreters then execute this compiled code
- Compiler and interpreter both are used hence, the name ‘compreters’.
- Each instruction starts with a byte. Therefore, they have up to 256 instructions.
3. Threaded Code Interpreters
- Similar to bytecode interpreters but, they use pointers.
- Each instruction is a word acting as a pointer. This pointer points to a function or instruction sequence.
- There is no restriction on the number of instructions. Considering that, memory and address space is available.
5. Abstract Syntax Tree Interpreters
- It converts the source code to an abstract syntax tree (AST).
- Then it executes the program according to this tree.
- Each sentence is parsed just once.
- The program structure and the relation between statements remain the same.
- Provides better analysis during run time
7. Self Interpreters
- These are a special type of interpreters.
- They are ==programming language== interpreters written in a programming language that can interpret itself.
- An example can be a BASIC interpreter written in BASIC.
- Self interpreters are created in case if no compiler exists for a language.
- Their creation requires the implementation of that language in a host language. This host language can be another programming language.
* Advantages and Disadvantages of Interpreter
* Advantages
* Executes line by line. Hence, debugging is easy.
* No intermediate code hence uses the memory efficiently.
* Disadvantages
* Execution time is more.
:::
* **Differences Between Compiler and Assembler**
:::spoiler
| ==Compiler== | ==Assembler== |
|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------:|
| Compilers converts the high-level language source code into assembly level language code or machine/binary level language code. | An assembler converts the assembly level language code into the machine level language code. |
| The input of a compiler is high-level language source code. | Where as, its input is low level assembly code. |
| Compiler converts the whole source code to machine code at once. | Assembler does not convert the code in one go. |
| It has the following phases: lexical analysis, syntax analysis, semantic analysis, intermediate code generation, code optimization, code generation and error handling. | An assembler completes the task in two passes. |
| It produces a machine code in form of mnemonics. | It produces binary code in form of 0s and 1s. |
| Examples are Java, C, C++ etc. compilers. | Examples of assemblers are GAS, GNU etc. |
:::
* **Differences between Compiler and Interpreter**
:::spoiler
| ==Compilers== | ==Interpreters== |
|:---------------------------------------------------------------------------------------------------------------------------------:|:-----------------------------------------------------------------------------------------------------------------------------------------------:|
| It converts the whole program into machine code at once | It translates only one statement at a time. |
| It takes more time to analyze the source code. In other words, compile time is more. However, the overall execution time is less. | It comparatively takes less time to analyze the source code. In other words, compile time is less. However, The overall execution time is more. |
| It generates an intermediate object code. Therefore, more memory is used. | It does not generate any intermediate object code. Hence it is memory efficient. |
| The whole program is compiled and then it shows all the errors together. Therefore, debugging is difficult. | It stops the compilation if any error occurs. Hence, debugging is easier. |
| Programming languages like C, C++, Java, etc use compiler. | Programming languages like Python, Ruby, PHP, etc. use an interpreter. These interpreted languages are also called **scripting languages**. |
:::
:::
* **What is Linkers & Loaders ?**
:::spoiler
<center>
<img src = https://scontent.fsgn2-9.fna.fbcdn.net/v/t1.15752-9/410486317_941496864201357_4456230525301376108_n.png?_nc_cat=103&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=_hPZt4E8cQkAX_300iF&_nc_ht=scontent.fsgn2-9.fna&oh=03_AdQe42_aJv9GJiFtgM3iJYg20rNF84m3zStY9btv63qjJA&oe=65AB28AC>
</center>
* Warm-up questions
:::spoiler
:::info
* Bản thân Compiler cũng là chương trình, vậy nó được biên dịch bằng gì ?
:::spoiler
$\Rightarrow$ ==**Assembler**==
:::
* Sau khi biên dịch tập tin ãm nguồn ngôn ngữ cấp cao thành tập tin mã máy (machine language), làm sao để chạy được những tập tin này trreen máy tính ?
:::spoiler
$\Rightarrow$ ==**Linker & Loader**==
:::
:::
* Linkers
* Thực tế khi lập trình, ta sẽ dùng nhiều file (header/source) liên kết và kèm theo các thư viện có sẵn
$\to$ Cần chương trình ==Linker== để liên kết các file sau khi đãx biên dịch thành mã máy này (Object File)
$\to$ Tập tin thực thi (ví dụ: .exe, .bat, .sh)
* Quá trình tạo file thực thi
<center>
<img src = https://scontent.fsgn2-11.fna.fbcdn.net/v/t1.15752-9/410140599_336576712656526_6498790019364697141_n.png?_nc_cat=105&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=wP8S91X02PAAX-oPd9Q&_nc_ht=scontent.fsgn2-11.fna&oh=03_AdQoDQjqO308k4HcIbKugHvoL5avGdm7Xa1qgpexXvdT2A&oe=65ABCE55>
</center>
* Khi double click vào những tập tin thực thi, cần chương trình tính toán và tải vào memory để CPU xử lý $\to$ Loader
* Quá trình thực thi file trên máy
<center>
<img src = https://scontent.fsgn2-4.fna.fbcdn.net/v/t1.15752-9/411173746_326956050147469_7739359272685533246_n.png?_nc_cat=101&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=vtuegSSvsg0AX-v22fD&_nc_ht=scontent.fsgn2-4.fna&oh=03_AdRwVV6p0nekTqNJW-qYyMfSgr6ZhujmPPKHtg-rZ-jLSg&oe=65ABED6E>
</center>
* ++Ví dụ:++
<center>
<img src = https://scontent.fsgn2-9.fna.fbcdn.net/v/t1.15752-9/410816361_901668264662231_9151849146830733299_n.png?_nc_cat=106&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=D2Qiv_FqK84AX8A-rfA&_nc_ht=scontent.fsgn2-9.fna&oh=03_AdRxQ0xEBPmYuHlD45-47-Qr5qISaJpLElo4k6R2LMxyjg&oe=65ABDCC5>
</center>
* Mô hình thực tế
<center>
<img src = https://scontent.fsgn2-8.fna.fbcdn.net/v/t1.15752-9/410979054_2048569622166537_275459476089262528_n.png?_nc_cat=102&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=mYNb8ojWrZwAX8B7__B&_nc_ht=scontent.fsgn2-8.fna&oh=03_AdT74ZDKtNjHl4VKngEa0suqDbQUxYSyTDLEnPQNNP20tw&oe=65ABD0A0>
</center>
* Compiler và Assembler có thể được bỏ qua trong một số trường hợp cụ thể ...
* Trong thực tế, có một số compiler có thể tạo file thực thi ở nhiểu nền tảng kiến trúc bên dưới khác nhau, được gọi là ==cross-platform compiler==,
* Compiler cho Java
* Cygwin
* Code::Block Studio
* Quá trình thực thi file trên máy Java program
<center>
<img src = https://scontent.fsgn2-4.fna.fbcdn.net/v/t1.15752-9/386452183_1401091320491827_2022016664248938201_n.png?_nc_cat=101&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=MnrB1RHUqaUAX83GhJl&_nc_ht=scontent.fsgn2-4.fna&oh=03_AdRCt_w7B0EkACDFys9a_wo1OzVDxHXplvIhiY4u-BN6dQ&oe=65ABE141>
</center>
* Hoạt động của CPU khi xử lý lệnh
* CPU xử lý lệnh qua 2 bước, gọi là chu kỳ lệnh:
* Nạp lệnh (Fetch): Di chuyển lệnh từ memory vào thanh ghi (register) trong CPU
:::spoiler
Quá trình nạp lệnh (Fetch Cycle)
* MAR $\gets$ PC
* MBR $\gets$ Memory
* IR $\gets$ MBR
* PC $\gets$ PC + 1
<center>
<img src = https://scontent.fsgn2-7.fna.fbcdn.net/v/t1.15752-9/409700025_377951377958570_4370891780250970223_n.png?_nc_cat=108&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=jcFOYuhBgSoAX_gEzfE&_nc_ht=scontent.fsgn2-7.fna&oh=03_AdS9A7NA7x5qSQX-ozDh_6IeJUWMWKDmJAS3wzUvdfabaA&oe=65ABEBE7>
</center>
:::spoiler
* Control Unit di chuyển mã lệnh, có địa chỉ trong PC, vào thanh ghi IR.
* Mặc định, giá trị thanh ghi PC sẽ tăng 1 lượng = chiều dài của lệnh vừa được nạp.
:::
1. Thanh ghi PC (Program Counter) : lưu địa chỉ (address) của lệnh sắp được nạp.
2. Thanh ghi MAR (Memory Address Register) : Lưu địa chỉ (address) sẽ đưojc output ra Address hơn.
3. Thanh ghi MBR(Memory Buffer Register): Lưu giá trị (value) sẽ được input / output từ Data bus.
4. Thanh ghi IR (Instruction Register): Lưu mã lệnh sẽ đưojc xử lý tiếp.
++Ví dụ++
<center>
<img src = https://scontent.fsgn2-9.fna.fbcdn.net/v/t1.15752-9/386875221_1029396358250341_9156531011221398033_n.png?_nc_cat=106&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=g-mHSmDtrYgAX-Zgcfb&_nc_oc=AQnepdYT90dUyiEhi8PC-XDFoESiFPzIZvf3sOVymkSA08auOxvn1DL4kjKKZWW8VqU&_nc_ht=scontent.fsgn2-9.fna&oh=03_AdRMu-b8NEVAnY6mHK-u21FX0khoGgcyR0vmxY2QSGzMnA&oe=65AC6618>
</center>
:::
* Thực thi lệnh (Execute): Giải mã lệnh bà thực thi thao tác yêu cầu.
:::spoiler
Quy trình thực thi lệnh (Execute Cycle)
* Tính địa chỉ lệnh
* Nạp lệnh
* Giải mã lệnh
* Tính địa chỉ của toán hạng
* Nạp toán hạng
* Thực hiện lệnh
* Tính địa chỉ của toán hạng chứa kết quả
* Ghi kết quả
<center>
<img src = https://scontent.fsgn2-9.fna.fbcdn.net/v/t1.15752-9/371536579_929122482114718_1525252829690863290_n.png?_nc_cat=106&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=rMhP7bB2iIcAX_YBnYf&_nc_ht=scontent.fsgn2-9.fna&oh=03_AdQajia_TKfXEVQBTUGySSoZ8pWfs32qG1i6QaqrSKm-KA&oe=65AC7274>
</center>
* Các bước này đưojc lặp đi lặp lại cho tất cả các lệnh tiếp theo.
* Quy trình này được gọi là ==Instruction Cycle== - vòng lặp xử lý lệnh.
<center>
<img src = https://scontent.fsgn2-9.fna.fbcdn.net/v/t1.15752-9/410504485_1101253021303876_7668282813484272695_n.png?_nc_cat=106&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=tFUEAcEQZRUAX8h5qDs&_nc_ht=scontent.fsgn2-9.fna&oh=03_AdRaW8E5vS6Yp3AFdlQM1S0LFODjddt85JjB1ahF0mhgQQ&oe=65AC7B54>
</center>
:::
<center>
<img src = https://scontent.fsgn2-10.fna.fbcdn.net/v/t1.15752-9/409560657_1613848092483708_5833356851684688963_n.png?_nc_cat=109&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=edFd2uk6pr8AX_vHc5D&_nc_ht=scontent.fsgn2-10.fna&oh=03_AdTrzQmJAU36IMTcOoaBE1WL03wydzVEvg29S0QQ0ng-7A&oe=65ABFE79>
</center>
:::
* **Câu hỏi mở rộng**
:::spoiler
:::info
* Ngôn ngữ lập trình giống và khác ngôn ngữ tự nhiên của con người ở những điểm nào?
* Tại sao cần nhiều loại ngôn ngữ lập trình: C, C++, C#, VB, Java…?
* Một chương trình không khai báo biến nào cả thì có sử dụng bộ nhớ không?
* Chương trình được thực thi trong RAM hay CPU?
* Tại sao file .exe chỉ chạy được trên Windows mà không thể chạy trên Linux?
:::
### II. Advantages and Disadvantages of Assembly Language
* **Advantages of Assembly Language**
::: spoiler
* Having an understanding of AL makes one aware of
* How programs interface with OS, processor, and BIOS
* How data is represented in memory and other external devices
* How the processor accesses and executes instruction
* How instructions access and process data
* How a program accesses external devices
* Other advantages of using assembly language are
* It requires less memory and execution time $\to$ tối ưu hóa tốc độ thực hiện bởi vì Assembly cho chỉ sử dụng các phần mềm, tài nguyên cần sử dụng, hạn chế tối đa việc sử dụng các tài nguyên không cần thiết $\to$ tối ưu hóa thời gian chạy chương trình.
* It allows hardware specific complex jobs in an easier way $\to$ việc kiểm soát $\to$ thể hiện được độ mạnh của bộ vi xử lý
* It is suitable for small memories because it can create small programs that consume little memory space $\to$ the system's operation is very fast, with a speed suitable for applications that control hardware.
* It is suitable for time-critical job
* It can access the hardware's memory.
* It is not affected by Developer's compilation ability. Because the Assembly is automatically compiled, it can be optimized without involving the compiler.
* It is most suitable for writing interrupt service routines and other memory resident programs $\to$ có thể nhanh chóng sửa lỗi chương trình
:::
* **Disadvantages of Assembly Language**
:::spoiler
* Nếu muốn sử dụng ngôn ngữ Assembly, các developer cần có ++kiến thức++ về ==bộ vi xử lý (micro - processor)==
* Việc ++duy trì++ mã tương đối ==phức tạp==, đòi hỏi người dùng phải ==mất nhiều công sức==
* Tùy vào từng vi xử lý mà ngôn ngữ Assembly sẽ có sự thay đổi cho phù hợp. Vì thế, các chương trình cho vi xử lý khác nhau có thể sẽ ++không thể sử dụng cho nhau++. Vì thế đối với mỗi vi xử lý, bạn sẽ cần ==viết một chương trình khác nhau==
* Assembly thường ++khó lập trình hơn++ và cũng ++tốn nhiều thời gian++ hơn so với các ngôn ngữ khác như C hay C++
* ++Thiết kế thuật toán++ của Assembly vẫn bị ==giới hạn==
:::
### III. Basic Features of PC Hardware
* The main internal hardware of a PC consist of
* Processor
* Memory
* Registers
:::spoiler
* Registers are processor components that hold data and address. To execute a program, the system copies it from the external device into the internal memory. The processor executes the program instructions.
:::
* The fundamental unit of computer storage is ==bit== , it could be ==ON(1)== or ==OFF(0)==. A group of nine related bits makes a byte, out of which ==eight bits== are used for the ==data== and the ==last one== is used for ==parity==. According to the rule of parity, the number of bits that are ON(1) in each byte should always be odd.
* So the parity bit is used to make the number of bits in a byte odd. If the parity is even, the system assumes that there had been a parity error (through rate), which might have been caused due to hardware fault or electrical disturbance.
#### 1. Data Representation Basics
##### a. Bits and Bytes
<center>
<img src = https://www.computerhope.com/jargon/b/bit-byte.png>
</center>
* ==**Bits**== (**B**inary digi**t**) - **b**asic **i**nformation uni**t** (1/0)
:::spoiler
* All of the data stored and transmitted by digital devices is encoded as **++bits++**.
* It can be further abbreviated as a lowercase **b**.
* Use ==bits== for ==data rates==, such as Internet connection speeds, and movies download speeds.
* It cannot be subdivided into any smaller units of information. It is easily fabricated at low cost, it is very easy to manipulate with electronic circuits, that's why computer designers have decided to use the bit as the basis for all information stored in a computer since the very first days of this wonderful machine.
* The bit is a two-state element, it can have two values: 1 or 0. This may sound limiting, but it is not, because those two values can be interpreted in several different ways
* 1 / 0
* True / False
* Yes / No
* On / Off
* used in a two-state (Boolean) logic
* etc.
* The values of 0 and 1 that are assigned to the bit are implemented in the machine by means of two different voltages: a high voltage value (2, 3 or 5 V) in general means 1, and a low voltage value (0 V) in general means 0 **$\to$** hardware detail.
* Examples:
* 56 Kbps : Kilobit (Kb or Kbit) can be used for slow data rates, such as a 56 Kbps (kilobit per seconds) dial-up connection.
* 50 Mbps : Megabit (Mb or Mbit) is used for faster data rates, such as 50 Mbps (megabits per second) Internet connection.
* 100 Gb : Gigabit (Gb or Gbit) is used for really fast network speeds.
:::
* ==**Bytes**== - sequence of 8 bits
:::spoiler
* A group of eight bits is called a **++byte++** and is usually abbreviated as an uppercase **B**.
* A byte is the ==**basic unit**== of information stored and processed by the computer.
* Use ==bytes== for ==file sizes== and ==storage capacities==.
* 104 KB : Kilobyte (KB or Kbyte) is often used when referring to the size of small computer files.
* 3.2 MB : Megabyte (MB or MByte) is typically used when referring to the size of files containing photos and videos.
* 16 GB : Gigabyte (GB or GByte) is commonly used to refer to storage capacity.
* A byte has a low-order nibble (the least-significant part) and a high-order nibble (the most-significant part).
<center>
<img src = https://scontent.fsgn2-6.fna.fbcdn.net/v/t1.15752-9/410861736_3527360317477809_4536514045365047504_n.png?_nc_cat=110&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=x52-PtCwTfwAX_rSMaL&_nc_ht=scontent.fsgn2-6.fna&oh=03_AdRLFq8hInjIGSLUZZJhXiJ20QoFK-pwrPVOtjhGkGcK9A&oe=65A93BDC>
<img src = https://image.semiconductor.samsung.com/image/samsung/p6/semiconductor/suppport/toolsandresources/dictionary/bits-and-bytes-units-of-data_1_en.jpeg?$ORIGIN_JPG$>
</center>
:::
* ==**Word**== - a sequence of bits addressed as a **single entity** by the computer.
:::spoiler
* Bytes are often grouped together to make words, unfortunately in the world of Computer Science the term word is employed to mean many different things, and the number of bits in a word (the wordlength) is different from computer to computer.
* Typical wordlengths are 8-, 16-, 32- and 64-bits.
* a **nibble** is a group of 4 bits, or 1/2 of a byte
* a **byte** is a group of 8 bits, e.g. 01100101
* a **word** is a group of 2 bytes, or 16 bits, e.g. 1001110010011110
* a **longword** is a group of 4 bytes, or 32 bits
* a **quadword** is a group of 64 bits, or 2 longwords
<center>
<img src = https://scontent.fsgn2-8.fna.fbcdn.net/v/t1.15752-9/409540913_777782434124575_5166718035332013045_n.png?_nc_cat=102&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=g_vkAMjXXoQAX-YNMXK&_nc_ht=scontent.fsgn2-8.fna&oh=03_AdQz1I4KA9eAhbbtwEwLJY5efQhtEO9jlsAaVp1MwM04Gg&oe=65A93211>
<img src = https://plctech.com.vn/wp-content/uploads/2019/07/bc2862c0bd91d641d2126b1f72ab9ab0.jpg>
</center>
:::
* Terminology related to **bits** and **bytes** is extensively used to describe ==storage capacity== and ==network access speed==.
* **Digital Data Size**
* When reading about digital devices, you'll frequently encounter references such as 90 kilobits per second, 1.44 megabytes, 2.8 gigahertz, and 2 terabytes.
* **Kilo** , **Mega**, **Giaga**, **Tera** and similar terms are used to quantity digital data.
:::spoiler
::: info
==**Byte**== $\xrightarrow[times]{1024}$ ==**KiloByte**== $\xrightarrow[times]{1024}$ ==**MegaByte**== $\xrightarrow[times]{1024}$ ==**GigaByte**== $\xrightarrow[times]{1024}$ ==**TeraByte**== $\xrightarrow[times]{1024}$ ==**PetaByte**== $\xrightarrow[times]{1024}$ ==**ExaByte**== $\xrightarrow[times]{1024}$ ==**ZettaByte**== $\xrightarrow[times]{1024}$ ==**YottaByte**==
| ==Unit== | ==Definition== | ==Mutiples of Bytes (SI)== | ==Mutiples of Bytes (Binary)== | ==Storage Space Size== |
|:--------------------:|:------------------------------:|:--------------------------:|:------------------------------:|:--------------------------:|
| bit (**b**) | 0(**OFF**) or 1(**ON**) (1bit) | :x: | :x: |<ul><li>Yes / No</li><li>True / False</li><li>1 / 0</li><li>ON / OFF</li></ul> |
| 1 Byte (**B**) | 8 bit | :x: | :x: | Alphabets and one number |
| 1 kilobyte (**KB**) | 1024 Byte | $10^3$ | $2^{10}$ | A few paragraphs |
| 1 megabyte (**MB**) | 1024 KB | $10^6$ | $2^{20}$ | One minute - long MP3 song |
| 1 gigabyte (**GB**) | 1024 MB | $10^9$ | $2^{30}$ | 30 minute - long HD movie |
| 1 terabyte (**TB**) | 1024 GB | $10^{12}$ | $2^{40}$ | About 200 FHD movies |
| 1 petabyte (**PB**) | 1024 TB | $10^{15}$ | $2^{50}$ | :x: |
| 1 exabyte (**EB**) | 1024 PB | $10^{18}$ | $2^{60}$ | :x: |
| 1 zettabyte (**ZB**) | 1024 EB | $10^{21}$ | $2^{70}$ | :x: |
| 1 yottabyte (**YB**) | 1024 ZB | $10^{24}$ | $2^{80}$ | :x: |
:::
* ==**++Main memory++**== is an ==array of bytes==, addressed by 0 to $2^{31} - 1 = 0xFFFFFFFF$ (or to $2^{64} - 1$ in IA64
:::spoiler
* $2^{32}$ bytes $= 4 * 2^{10 * 3}$ bytes $= 4$ GBs
<center>
<img src = https://scontent.xx.fbcdn.net/v/t1.15752-9/411257934_888037865978886_7684012630218411227_n.png?stp=dst-png_p206x206&_nc_cat=104&ccb=1-7&_nc_sid=510075&_nc_ohc=932KqV31OKMAX8cLfAM&_nc_ad=z-m&_nc_cid=0&_nc_ht=scontent.xx&oh=03_AdTV-JQhO9A81L2Em32t6ueBojaJwDVI0wj29NNd2Z6kWQ&oe=65A95B83>
</center>
:::
#### 2. Registers in IA32 (32-bit)
<center>
<img src = https://www.edn.com/wp-content/uploads/media-1073597-assembly-language-for-ia-32-fig1t.jpg>
</center>
* **Data Registers**
:::spoiler
<center>
<img src = https://scontent.fsgn2-3.fna.fbcdn.net/v/t1.15752-9/410188340_7149007541809586_38847061586746962_n.png?_nc_cat=107&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=w0t_Au4F2qwAX_gtcQ_&_nc_ht=scontent.fsgn2-3.fna&oh=03_AdS8PbQnt3BvjmXOfFRtMo9OnCEZ8ebo4a3jB-5tQHvCBQ&oe=65A987CC>
</center>
* The IA-32 processors provides four 32-bits data registers, they can be used as:
* Four 32-bits registers: EAX (Accumulator), EBX(Base), ECX(Counter), EDX(Data)
* Four 16-bits registers:
* Register chứa AX (accumlator): chứa kết quả của các phép tính. Kết quả là 8 bit được chứa trong AL.
* Register cơ sở BX (Base) : chứa địa chỉ cơ sở, ví dụ của bảng dùng lệnh XLAT (Translate)
* Register đếm (Count) : dùng để chứa số lần lặp trong các lệnh lặp (loop). Register CL được dùng để chứa số lần dịch hoặc quay trong các lệnh dịch và quay thanh ghi.
* Register dữ liệu DX (Data) : cùng AX chứa dữ liệu trong các phép tính nhân chia số 16 bit. DX còn được dùng để chứa địa chỉ cổng trong các lệnh vào ra dữ liệu trực tiếp (IN / OUT).
* Eight 8-bits registers:
* Four registers have 8 high bit: AH, BH, CH, DH
* Four registers have 8 low bit: AL, BL, CL, DL
| 32-bits registers (31...0) | Bits 31...16 | Bits 15...8 | Bits 7...0 |
|:--------------------------:|:------------:|:-----------:|:----------:|
| EAX | | AH | AL |
| EBX | | BH | BL |
| ECX | | CH | CL |
| EDX | | DH | Dl |
* The data registers can be used in most arithmetic and logical instructions. But when executing some instructions, some registers have special purpose.
:::
* **Segment Registers**
:::spoiler
* Tổ chức của bộ nhớ 1Mbytes
* Đoạn bộ nhớ (segment):
* $2^{16}$ bytes $= 64$ KB
* Đoạn 1: địa chỉ đầu 0000**0** H
* Đoạn 2: địa chỉ đầu 0001**0** H
* Đoạn cuối cùng: FFFF**0** H
* Ô nhớ trong đoạn:
* Địa chỉ lệch: offset
* Ô 1: offset: 0000
* Ô cuối cùng: offset: FFFF
* Địa chỉ vật lý:
* Segment: offset
* Địa chỉ vật lý = Segment * 16 + offset
* Chế độ real mode
<center>
<img src = https://scontent.fsgn2-5.fna.fbcdn.net/v/t1.15752-9/400546969_728685939201607_6955561811667346889_n.png?_nc_cat=104&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=D6t2R3jk0UAAX-aqyZp&_nc_ht=scontent.fsgn2-5.fna&oh=03_AdRbvhQbu8AJ5mIgs3ILhbaUmDGY6UpS01JC3DME4hsy1A&oe=65A9D37E>
</center>
* Ví dụ 01: Địa chỉ vật lý 12345H
| Địa chỉ đoạn | Địa chỉ lệch |
|:------------:|:------------:|
| 1000H | 2345H |
| 1200H | 0345H |
| 1004H | 2305H |
| 0300H | 12045H |
* Ví dụ 02: Cho địa chỉ đầu của đoạn 49000H, xác định địa chỉ cuối.
$\to$ Địa chỉ cuối đoạn là FFFF0H.
* The Pentium processor has six 16-bits segment registers
* Các thanh ghi đoạn: chứa địa chỉ đoạn
* CS (code segment)
* DS (data segment)
* SS (stack segment)
* ES (extra data segment)
* FS (extra data segment)
* GS (extra data segment)
$\to$ Dùng để lưu trữ bộ chọn đoạn để quản lý bộ nhớ trong mô hình phẳng hoặc phân đoạn.
<center>
<img src = https://scontent.fsgn2-10.fna.fbcdn.net/v/t1.15752-9/410369784_258796286972790_8093286207734437873_n.png?_nc_cat=109&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=iNPT2KVfglcAX-z2Rnz&_nc_ht=scontent.fsgn2-10.fna&oh=03_AdT97e9pTIn1ggihdt9FwmPBahvZHZ1__CQkH8QUdG00KQ&oe=65A9F55D>
</center>
* Các đoạn chồng nhau
<center>
<img src = https://scontent.fsgn2-7.fna.fbcdn.net/v/t1.15752-9/403625902_904394480757807_5865210532056318244_n.png?_nc_cat=100&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=NAmoNZX1iCoAX8R3nwk&_nc_ht=scontent.fsgn2-7.fna&oh=03_AdRQKTYR-LxTCdQxX73yp_dwZBtrESd7leVX8F9fBoQ4_Q&oe=65A9FB6F>
</center>
* Modern applications and operating systems (including Windows 2000 and Linux) use the flat memory model (unsegmented memory model). In this model, all segment registers are loaded with the same segment selector. So all memory references are to a single linear-address space.
:::
* **Pointer & Index Registers**
:::spoiler
* The IA - 32 processors have four 32 - bits index and pointer registers (80386 trở lên 32 bits) which are:
* ESP (Stack Pointer - contains the address of last used dword in the stack)
* EBP (Base Pointer)
* ESI (Source Pointer)
* EDI (Destination Index)
* These registers can also be used as four 16-bits registers (SI, DI, SP, and EP).
* Usually ESI and EDI are used as regular data registers. But when using the string instructions they have special functions.
* ESP is the stack pointer, and EBP is the frame pointer. If you don't use stack frames, you can use EBP as a regular data register.
| 32 - bits registers (31...0) | Bits 31...16 | Bits 15...0 | Special function |
|:----------------------------:|:------------:|:-----------:|:----------------- |
| ESI | | SI | Source Index |
| EDI | | DI | Destination Index |
| ESP | | SP | Stack Pointer |
| EBP | | BP | Frame Pointer |
:::spoiler
* Registers chứa địa chỉ lệch (offset):
* Con trỏ lệnh IP (Instruction Pointer): chứa địa chỉ lệnh tiếp theo trong đoạn mã lệnh CS $\Rightarrow$ CS : IP
* Con trỏ cơ sở BP (Base Pointer): chứa địa chỉ của dữ liệu trong đoạn stack SS hay các đoạn khác $\Rightarrow$ SS : BP
* Con trỏ ngăn xếp SP (Stack Pointer): chứa địa chỉ hiện thời của đỉnh ngăn xếp $\Rightarrow$ SS : SP
* Chỉ số nguồn SI (Source Index): chứa địa chỉ dữ liệu nguồn trong đoạn dữ liệu DS trong các lệnh chuỗi $\Rightarrow$ DS : SI
* Chỉ số đích DI (Destination Index): chứa địa chỉ dữ liệu đích trong đoạn dữ liệu DS trong các lệnh chuỗi $\Rightarrow$ DS : DI
* SI và DI có thể được sử dụng như thanh ghi đa năng.
* 80386 trở lên 32 bits: EIP, EBP, ESP, EDI, ESI
* Thanh ghi đoạn và thanh ghi lệch ngầm định:
| Segment | Offset | Meaning |
|:-------:| ------------------------------------------- | -------------------------- |
| CS | IP | Instruction address |
| SS | SP or BP | Stack address |
| DS | BX, DI, SI, 8-bits number or 16-bits number | Data segment address |
| ES | DI | Destination string address |
:::
:::
* **Control Registers**
:::spoiler
The two most important control registers are the instruction pointer (EIP) and the EFlags register.
* **:triangular_flag_on_post: EFlags Registers (Status Registers)**
<center>
<img src = https://lh6.googleusercontent.com/3m_HlpjBVHKfK-V5dODZeZCSMXa6sNKA0mhiDxCafNhuW7eoZY7T0jzWZQQpOeTzRkCRKcIj1Y3toNYZ9Jkad8pEOo8fS9AljHNB0F-LZraPQBloKHsH0_s2IDyylqFdS-2sxVxt>
</center>
:::spoiler
<center>
<img src = https://scontent.fsgn2-9.fna.fbcdn.net/v/t1.15752-9/410626950_258560796985784_8924629443359617157_n.png?_nc_cat=103&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=C2-I3hS-yTcAX9kQ775&_nc_ht=scontent.fsgn2-9.fna&oh=03_AdShxCmKmtuC4OgQ6QdFtmZ0zpt09C8SP42brXb40M7Z3A&oe=65AA6684>
</center>
* ==**Status or Arithmetic Flags**==
:::spoiler
* Six of the flags in the EFlags register are ==++status or arithmetic flags++==. They are used to record information about the most recently executed arithmetic or logical instruction. Three of the flags: SF, PF and AF are rarely used.
* ==**++Zero Flag (Z or ZF)++**== is set when the result of the last executed arithmetic instruction was zero. ZF is used to test for equality or count down to a preset value. Related instructions are: *jz* and *jnzhis*.
:::spoiler
$\Rightarrow$ ZF = 1 khi kết quả bằng 0
:::
* ==**++Carry Flag (C or CF)++**== is set if the last arithmetic operation (on two unsigned integers) was either too big or too small (out of range). CF is used to propagate carry or borrow, detect overflow/ underflow or test a bit (using shift/ rotate). Related instructions are: jc, jnc, stc, clc, and cmc. Note that inc and dec does not affect the carry flag.
:::spoiler
$\Rightarrow$ CF = 1 khi có nhớ hoặc mượn từ MSB
:::
* ==**++Overflow Flag (O or OF)++**== indicates when an operation on signed integers resulted in an overflow/underflow. Related instructions are: jo and jno.
:::spoiler
$\Rightarrow$ cờ tràn OF = 1 khi kết quả là một số vượt ra ngoài giới hạn biểu diễn của nó trong khi thực hiện phép toán cộng trừ số có dấu
:::
* ==**++Sign Flag (S or SF)++**== Indicates the sign of the result of an arithmetic operation. Related instructions are: js and jns.
:::spoiler
$\Rightarrow$ SF = 1 khi kết quả là số âm
:::
* ==**++Parity Flag (P or PF)++**== indicates the parity of the 8-bit result produced by an operation. PF = 1 if the byte contains an even number 1 bits. It is used in data encoding programs. Related instructions are jp and jnp.
:::spoiler
$\Rightarrow$ PF = 1(0) khi tổng số bits 1 trong kết quả là chẫn (lẻ)
:::
* ==**++Auxiliary Flag (A or AF)++**== indicates whether an operation has produced a result that has generated a carry, or borrow into the low-order four bits of 8- 16- or 32-bit operands. AF is used in arithmetic operations on BCD numbers.
:::spoiler
$\Rightarrow$ cờ nhớ phụ, AF = 1 khi có nhớ hoặc mượn từ một số BCD thấp sang BCD cao
:::
:::
* ==**Control Flags**==
:::spoiler
<center>
<img src = https://scontent.fsgn2-3.fna.fbcdn.net/v/t1.15752-9/410540781_263853896420040_5295287808247755791_n.png?_nc_cat=107&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=a98lXd90XWMAX9k20w3&_nc_ht=scontent.fsgn2-3.fna&oh=03_AdTbsTN83ROZ7SjVbzmp6BvRWqqJj0xTv913QREp0JKBOA&oe=65AA2EEF>
</center>
* ==**++Direction Flag (D or DF)++**== determines wetter string operations should scan the string forward or backward. It is only used in string instructions. DF can be set by std and cleared by cld.
* If DF = 1, the string will be accessed from higher memory address to lower memory address.
* If DF = 0, it will do reverse.
:::spoiler
$\Rightarrow$ DF là cờ hướng, DF = 1 khi CPU làm việc với chuỗi ký tự theo thứ tự từ phải sang trái (lệnh STD, CLD)
:::
* ==**++Trap Flag (T or TF)++**==
* TF used for on chip debugging
* If TF = 1, CPU will work in a single step mode.
* Generate an interrupt after each instruction.
:::spoiler
$\Rightarrow$ là cờ bẫy, TF = 1 khi CPU làm việc ở chế độ chạy từng lệnh.
:::
* ==**++Interrupt Flag (I or IF)++**==
* If IF = 1, CPU will recognize the interrupts from peripherals.
* If IF = 0, the interrupts will be ignored.
:::spoiler
$\Rightarrow$ là cờ cho phép ngắt, IF = 1 thì CPU sẽ cho phép các yêu cầu ngắt (ngắt che được) được tác động (các lệnh: STI, CLI)
:::
:::
* ==**System Flags**==
:::spoiler
* The remaining eight flags are ==++system flags++==. They are used to control the operation of the processor. Ordinary application programs cannot set these flags directly.
* IOPL (I/O privilege level)
* NT (nested task)
* RF (resume flag)
* VM (virtual 8086 mode)
* AC (alignment check)
* VIF (virtual interrupt flag)
* VIP (virtual interrupt pending)
* ID (ID flag)
:::
* ==**Examples**==
:::spoiler
```p=
mov EAX, 8 ; ZF = 0
sub EAX, 8 ; ZF = 1
cmp char, 0 ; ZF = 1 if char == '\0'
cmp EAX, EBX ; ZF = 1 if EAX = EBX
; for (i = 0; i < 12; i++)
mov ECX, 12 ; ECX 12
loop:
<do something>
dec ECX ; ECX = ECX - 1
jnz loop ; Jump if ZF = 0
mov AL, 100
add AL, 200 ; CF = 1
mov AX, 100
sub AX, 101 ; CF = 1 (any negative integer is out of range)
mov AL, 100
add AL, 30 ; OF = 1 (signed char range is -128...127)
```
:sparkle: Note that the processor does not know if you are using signed or unsigned integers. OF and CF are set for every arithmetic operation.
```p=
mov AL, 15
add AL, 100 ; SF = 0 (positive result)
mov AL, 15
sub AL, 100 ; SF = 1 (negative result)
```
* Ví dụ:
<center>
<img src = https://scontent.fsgn2-8.fna.fbcdn.net/v/t1.15752-9/410369784_916336596728856_4835710388444218032_n.png?_nc_cat=102&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=xfLND-bt5WAAX_DmqEP&_nc_ht=scontent.fsgn2-8.fna&oh=03_AdRp32pFHcy_-zSnFjVV_uZ0BjlfTppV1tSO6grqjcNJDw&oe=65AA3585>
</center>
* SF = 0 vì msb trong kết quả = 0
* PF = 1 vì có 0 bit của tổng = 1
* ZF = 1 vì kết quả thu được là 0
* CF = 1 vì có nhớ từ bit msb trong phép cộng
* OF = 1 vì có overflow trong phép cộng 2 số âm
:::
:::
* **Instruction Pointer (Program Counter)**
:::spoiler
* EIP (EPC) contains address (offset) of the next instruction that is going to be executed (at run time). EIP cannot be accessed directly.
* EIP (EPC) changed by unconditional jump, conditional jump, procedure call, and return instructions.
:::
:::
#### 3. Registers in all ISA
<center>
<img src = https://scontent.fsgn2-7.fna.fbcdn.net/v/t1.15752-9/403401954_1009202240381162_9150369702958801190_n.png?_nc_cat=100&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=qAuW3AnXBI4AX-rc3Gv&_nc_ht=scontent.fsgn2-7.fna&oh=03_AdQ9RkJEIiRfPYLIlEs81de8zxvsyxRWXR8iBNODMOkVdg&oe=65AA7098>
</center>
### IV. Assembly Language Program
* ==**Assembly Program**== consist of ==**statement**==, one per line; translated by ==**Assembler**== into MLIS that can be loaded into memory and executed.
* Each statement is either an instruction, which is the assembler translate into machine code, or assembler directive, which instructs the assembler to perform some specific tasks, such as allocating memory space for a variable or creating a procedure.
* Both instructions and directive have up four fields:
| Component 01 | Component 02 | Component 03 | Component 04 |
|:------------:|:-------------:|:--------------:|:------------:|
| ==Name== | ==Operation== | ==Operand(s)== | ==Comment== |
*(All least one blank or tab character must separate the fields)*
#### 1. Instruction and Directive
:::spoiler
* An example of an instruction is
* The name field consists if the label ==**START:**==
* The operation is ==**MOV,**== the operands are ==**CX**== and ==**5**==
* The comment is ==**; initialize counter**==
```p=
START: MOV CX,5 ; initialize counter
```
* An example of an assembler directive is
* ==**MAIN**== is the name, and the operation field contains ==**PROC**==.
* This particular directive creates a procedure called ==**MAIN**==.
```p=
MAIN PROC
```
:::
#### 2. Program Statement Structure
<center>
<img src = https://scontent.fsgn2-9.fna.fbcdn.net/v/t1.15752-9/403618115_1407137666680602_2681698422476956272_n.png?_nc_cat=103&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=-UDIQUK99nsAX9JRsAm&_nc_ht=scontent.fsgn2-9.fna&oh=03_AdTVFnt16Qf8zfF8rdjgTqUo49v5Ni5JzLEGHbuQ1aooaw&oe=65AA6759>
</center>
##### a. NAME
:::spoiler
* A ==**NAME**== field identifies a label, variable, or symbol. It may contain any of the following characters:
* Names are case sentitive (==++MOV++== or ==++mov++== is same).
* The first character may not be a digit. The period (.) may be used only as the first character.
:::warning
A **Keyword**, or **Reversed Word** always have some predefined meaning to the assembler. It may be **an instruction** (==MOV==, ==ADD==), or **an assembler directive** (==PROC==, ==TITLE==, ==END==).
:::
##### b. OPERATION
:::spoiler
* An ==**OPERATION**== field is a predefined or reversed word
* ==**mnemonic**== - symbolic **operation code**
* The assembler translates a symbolic opcode into a **machine language opcode**.
* Opcode symbols often describe the operation's function. For examples: **MOV**, **ADD**, **SUB**
* ==**assembler directive**== - pseudo operation code
* In a assembler directive, the operation field contains a pseudo-operation code (**pseudo-op**).
* Pseudo-op are not translated into machine code. For example: the **PROC** pseudo-op is used to create a procedure.
:::
##### c. OPERAND(S)
:::spoiler
* An ==**OPERAND**== field specifies the data that are to be acted on by the operation.
* An instruction may have zero, one, or two operands. For examples:
```p=
NOP No operands; does nothing
INC AX one operand; adds 1 to the contents of AX
ADD WORD1,2 two operands; adds 2 to WORD1
```
:::
##### d. COMMENT
:::spoiler
* The ==**COMMENT**== field is used by the programmer to say something about what the statement does.
* A semicolon marks the beginning of this field, and a the assembler ignores anything typed after semicolon.
* Comments are optional, but because assembly language is low level, it is almost impossible to understand an assembly language program without comments.
:::
#### 3. Opcodes and Operands
:::spoiler
:::info
* The ==**Machine Language**== (aka **low-level language**) consists of strings of binary numbers (that is 0's and 1's), which means the code is written in binary language, and this is the only language that is recognized by the computer system.
* ==**Machine code**== is the fundamental language of any computer system.
:::
##### a. Opcodes
:::spoiler
* ==**Opcodes**== is the first part of an instruction that tells the computer what functions to perform and is also called **++Operation Codes++** (Opcodes). Opcodes are the numeric codes that holds the íntructions given to the computer system.
* There are the instructions that describe the CPU what operations are to be performed. The computer system has an **operation code** or **opcode** for each and every function given to it.
* Types of Opcodes:
* Arithmetic, Logical (add, sub, mult, and, or, cmp, ...)
* Memory Load / Store (ld, st)
* Control Transfer (jmp, bne)
* Complex (movs,...)
:::
##### b. Operands
:::spoiler
* ==**Operand**== is another second part of **instruction**, which indicates the computer system where to find the data or instructions or where to store the data or **instructions**.
* The number of **operands** varies amongst different computer systems. Each **instruction** indicates the Control Unit of the computer system what to perform and how to perform it.
* The operations are Arithmetic, Logical, Branch operation, so on depending upon the problem that is provided to the computer.
:::
##### c. Assembly Language Instructions
:::spoiler
* Instruction là dãy bits chứa yêu cầu mà bộ xử lý trong CPU (ALU) phải thực hiện.
* AL instructions are built from 2 pieces:
* Opcodes : what to do with the data $\Rightarrow$ thao tác cần thực hiện
* Operands : where to get the data $\Rightarrow$ các đối tượng bị tác động bởi thao tác chứa trong mã lệnh.
:::spoiler
* **++Ex 01 :++** In instruction `add R1, R3, 3`
* Opcode is `add`
* Operand is `R1, R3, 3`
* **++Ex 02 :++**
* ++Assembly code:++
```p=
MOV AL, 61h ; load AL with 97d
```
* ++Binary code:++ ==1011==**0**++000++ 01100001
:::success
* ==1011== : a binary code (opcode) of instruction ==**MOV**==
* **0** : specifies if data is byte (`0`) or full size 16/32 bits(`1`)
* ++000++ : a binary identifier for a register `AL`
* 01100001 : a binary representation of 97d (= 61h)
:::
:::
:::
#### 4. Types of Assembly Language
:::spoiler
:::info
* AL closely tied to processor architecture, so there are many AL.
* At least four main types:
* CISC: Complex Instruction-Set Computer
* RISC: Reduced Instruction-Set Computer
* DSP: Digital Signal Processor
* VLIW: Very Long Instruction Word
* When programming, we can use one of two forms:
* ==**Inline Assembly**==: some compilers allows AL instructions to be embedded within a program, such as C, C++, Pascal, Ada, ... We don't need any Assembler to translate AL instructions.
* ==**Full Assembly**==: we must use an Assembler to translate AL instructions into MLIs (binary code). TASM (Turbo Assembler), MASM (Macro, ...), NASM (Netwide, ...), ... are assemblers for x86 architecture.
:::
##### a. CISC Assembly Language
:::spoiler
* Developed when people wrote assembly language
* Complicated, often specialized insructions with many effects
* Examples from x86 architecture: String move, Procedure enter, leave
* Many, complicated addressing modes
* So complicated, often executed by a little program (micro-code)
* Examples: Intel x86, 68000, PDP - 11
:::
##### b. RISC Assembly Language
:::spoiler
* Response to growing use of compilers
* Easier-to-target, uniform instruction sets "Make the most common operations as fast as possible"
* Load-store architecture:
* Arithmetic only performed on registers
* Memory load / store instructions for memory - register transfers
* Designed to be pipelined
* Examples: SPARC, MIPS, HP-PA, PowerPC
:::
##### c. DSP Assembly Language
:::spoiler
* Digital signal processors designed specifically for signal processing algorithms.
* Lots of regular arithmetic on vectors.
* Often written by hand
* Irregular architectures to save power, area
* Substantial instruction-level parallelism
* Examples: TI 320, Motorola 56000, Analog Devices
* Digital Signal Processor Apps
* Low-cost embedded systems: Modems, cellular telephones, disk drives, printers
* High-throughput application: Halftonin, base stations, 3-D sonar, tomography
* PC based multimedia: Compression / Decompression of audio, graphics, video
:::
##### d. VLIW Assembly Language
:::spoiler
* Response to growing desire for instruction-level parallelism
* Using more transistors cheaper than running them faster
* Many parallel ALUs
* Objective: keep them all busy all the time
* Heavily pipelined
* More regular instruction set
* Very difficult to program by hand
* Looks like parallel RISC instructions
* Examples: Itanium, TI 320C6000 56000 Analog Devices
:::
### V. Modular Programming
:::spoiler
* Many programs are too large to be developed by one person. This means that programs are routinely developed by a teams.
* The **Assembler** converts a **source module** (file) into a **object file**.
* The **Linker** program is used so that modules can be linked together into a complete program. It reads the object files that are created by the assembler and links them together into a single execution file.
* An execution file is created with the file name extension .EXE
* In DOS / Windows: if a file is short enough (less than 64K bytes long), it can be converted from an execution file to a command file (.COM).
* The command file is slightly different from an execution file in that the program must be originated at location 0100H before it can execute.
<center>
<img src = https://scontent.fsgn2-9.fna.fbcdn.net/v/t1.15752-9/410486317_941496864201357_4456230525301376108_n.png?_nc_cat=103&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=_hPZt4E8cQkAX_300iF&_nc_ht=scontent.fsgn2-9.fna&oh=03_AdQe42_aJv9GJiFtgM3iJYg20rNF84m3zStY9btv63qjJA&oe=65AB28AC>
</center>
* ASCII Table
:::spoiler
<center>
<img src = https://scontent.fsgn2-10.fna.fbcdn.net/v/t1.15752-9/410410574_1397246237596193_1018757048090937255_n.png?_nc_cat=109&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=6gz5EgktfA0AX_FzyO-&_nc_ht=scontent.fsgn2-10.fna&oh=03_AdTcXQcLJ8fQSTy4jDRN4VgA0h8WEK1plP5QgHTLX5hKyA&oe=65AB1F51>
</center>
:::
:::
---
## :keyboard: Chapter :six: : ASSEMBLY LANGUAGE PROGRAMMING
### I. x86
#### 1. Instruction and Directive
:::spoiler
* Consider the following statement:
```p=
Start: MOV CX, 5 ;initialize counter
```
* Instruction : The operation and operands ==MOV CX, 5==
* Directive: The **lable** (Start;) and the **comment**
* Some important instructions : MOV, ADD, SUB, CMP, JMP, J<condition> INT, ...
* Some important directives except labels and comments: .MODEL, .STACK, .DATA, .CODE, .PROC, .ENDP, .END, DB/DW/DD/... , ...
:::
#### 2. The most basis x86 instructions
:::spoiler
* MOV <Dest>, <Source> : copies content of <Source> to <Dest>
* ADD / SUB <Destination> , <Source> : add / subtract the content of <Dest> with <Source>, then copy the result to <Dest>
* CMP <Source1> , <Source2> : compare <Source1> with <Source2>
* JMP/Jxxx<Label> : jump / jump_if <xxx> to <Label>
* INT <InterruptNo> : call pre-defined procedure *<Interrupt Number>*
:::
#### 3. Instructions
##### a. Instruction Arguments
:::spoiler
* A typical instruction has 2 operands
* target operand (left)
* source operand (right)
* 3 kinds of operands exists
* ==**immediate**==: value $\to$ stands for `imm`
* ==**register**==: AX, EBX, DL, ... $\to$ stands for `reg`
* ==**memory location**==: variable or pointer $\to$ stands for `mem`
* Examples:
<center>
<img src = https://scontent.fsgn2-10.fna.fbcdn.net/v/t1.15752-9/403412951_2541095249405518_7914789027534919670_n.png?_nc_cat=109&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=0E1rxvGOM3MAX8Yhvlv&_nc_ht=scontent.fsgn2-10.fna&oh=03_AdTVuuYAriqczHzx-pnluSfumqWX0E7V2N9-SnFyA56uEg&oe=65AC9F83>
<img src = https://scontent.fsgn2-4.fna.fbcdn.net/v/t1.15752-9/412693543_285943147347418_2048850548536876248_n.png?_nc_cat=101&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=Vx_FTpak3k8AX_K8cjK&_nc_ht=scontent.fsgn2-4.fna&oh=03_AdSxWjDvJMpZKS-8BJU_7biSdBHuvkphFvhQa0LQi0INJg&oe=65AE4528>
</center>
* ==**:x: Note**: x86 processor does not allow both operands be memory locations.==
<center>
<img src = https://scontent.fsgn2-7.fna.fbcdn.net/v/t1.15752-9/386884757_1040411987173143_4039781218035215700_n.png?_nc_cat=108&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=2EDaxjiGRwkAX-fSm7j&_nc_ht=scontent.fsgn2-7.fna&oh=03_AdTfjrm8PNM862qg3wYpvEglyaCWQ2KW9TO1HwhbJ0A9iA&oe=65AE4BE6>
</center>
:::
##### b. Move instructions
* Công thức tổng quát: ==mov **reg$_{8 (16,32)}$** / **mem$_{8(16,32)}$** , **reg$_{8 (16,32)}$** / **imm$_{8 (16,32)}$**==
:::spoiler
$\Rightarrow$ copies content of **register** / **immediate** (`source`) to **register** / **memory location** (`destination`)
:::
* Công thức tổng quát: ==mov **reg$_{8 (16,32)}$** , **reg$_{8 (16,32)}$** / **mem $_{8(16,32)}$**==
:::spoiler
$\Rightarrow$ copies content of **register** / **memory location** (source) to **register** (`destination`)
:::warning
**:negative_squared_cross_mark: Operands have to be of the same size**
:::
* Examples:
:::spoiler
<center>
<img src = https://scontent.fsgn2-6.fna.fbcdn.net/v/t1.15752-9/410846617_739850141037385_4147571872738101079_n.png?_nc_cat=110&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=VNMDM00v_6MAX-SPQee&_nc_ht=scontent.fsgn2-6.fna&oh=03_AdSaHx2dlIJhftz9k6l3nGLrz-i9jrHV6bRfCJFS2gL0cQ&oe=65AE6A39>
</center>
:::
##### c. Basic Arithmetical instructions
* **Binary Operators** *(Toán tử hai ngôi)*
:::spoiler
* Công thức tổng quát:
* ==**<instruction>**== **reg$_{8 (16,32)}$** / **mem$_{8(16,32)}$** , **reg$_{8 (16,32)}$** / **imm$_{8 (16,32)}$**
:::spoiler
:::info
* Source: **reg$_{8 (16,32)}$** / **imm$_{8 (16,32)}$**
* Destination: **reg$_{8 (16,32)}$** / **mem $_{8(16,32)}$**
:::
* ==**<instruction>**== **reg$_{8 (16, 32)}$** , **reg$_{8 (16,32)}$** / **mem$_{8(16,32)}$**
:::spoiler
:::info
* Source: **reg$_{8 (16,32)}$** / **mem$_{8(16,32)}$**
* Destination: **reg$_{8 (16, 32)}$**
:::warning
**:negative_squared_cross_mark: Operands have to be of the same size**
:::
* Công thức chi tiết
:::spoiler
| <instruction> | Explanation | Examples |
|:-------------:|:----------------------------------------------------:|:------------------------------------------------:|
| **ADD** | add 2 integers | *add AX, BX* ;(AX gets a value of AX + BX) |
| **SUB** | substract 2 integers | *sub AX, BX* ;(AX gets a value of AX - BX) |
| **ADC** | add integers with carry (value of Carry Flag) | *adc AX, BX* ;(AX gets a value if AX + BX + CF) |
| **SBB** | substract integers with borrow (value of Carry Flag) | *sbb AX, BX* ;(AX gets aa value of AX - BX - CF) |
:::
:::
* **Unary Operators** *(Toán tử một ngôi)*
:::spoiler
* Công thức tổng quát: ==**<instruction>**== **reg$_{8 (16,32)}$** / **mem$_{8(16,32)}$**
:::spoiler
:::info
$\Rightarrow$ **source** / **destination** - **register** / **memory location**
:::
* Công thức chi tiết
:::spoiler
| <instruction> | Explanation | Examples |
|:-------------:|:-----------------:|:------------------------------------------------------------:|
| **INC** | increment integer | *inc AX* ;(AX gets a value of AX + 1) |
| **DEC** | decrement integer | *dec byte [buffer]* ;([buffer] gets a value of [buffer] - 1) |
:::
:::
##### d. Basic Logical Instructions
* **Unary Operator** *(Toán tử một ngôi)*
:::spoiler
* Công thức tổng quát: ==**<instruction>**== **reg$_{8 (16,32)}$** / **mem$_{8(16,32)}$**
:::spoiler
:::info
$\Rightarrow$ **source** / **destination** - **register** / **memory location**
:::
* Công thức chi tiết:
* NOT - one's complement negation - inverts all the bits
* Examples:
```p=
mov al, 11111110b
not al // ; (al gets a value of 00000001b)
// ; (11111110b + 00000001b = 11111111b)
```
* NEG - two's complement negation - inverts all the bits, and adds 1 finally.
* Examples:
```p=
mov al, 11111110b
neg al // ; (al gets a value of not(11111110b) + 1 = 00000001b + 1 = 00000010b)
// ; (11111110b + 00000010b = 100000000b = 0)
```
:::
* **Binary Operator** *(Toán tử hai ngôi)*
:::spoiler
* Công thức tổng quát
* ==**<instruction>**== **reg$_{8 (16,32)}$** / **mem$_{8(16,32)}$** , **reg$_{8 (16,32)}$** / **imm$_{8 (16,32)}$**
:::spoiler
:::info
* Source: **reg$_{8 (16,32)}$** / **imm$_{8 (16,32)}$**
* Destination: **reg$_{8 (16,32)}$** / **mem $_{8(16,32)}$**
:::
* ==**<instruction>**== **reg$_{8 (16, 32)}$** , **reg$_{8 (16,32)}$** / **mem$_{8(16,32)}$**
:::spoiler
:::info
* Source: **reg$_{8 (16,32)}$** / **mem$_{8(16,32)}$**
* Destination: **reg$_{8 (16, 32)}$**
:::warning
**:negative_squared_cross_mark: Operands have to be of the same size**
:::
* Công thức chi tiết
* ==**OR**== - bitwise OR - bit at index i of the destination gets `1` if bit at index i of source or destination are `1` ; otherwise `0`
:::spoiler
* Examples:
```p=
mov al, 11111100b
mov bl, 00000010b
or al, bl ; (al gets a value of 11111110b)
```
:::
* ==**AND**== - bitwise AND - bit at index i of the destination gets `1` if bits at index i of both source and destination are `1`; otherwise `0`
:::spoiler
* Examples:
```p=
mov al, 11111100b
mov bl, 00000010b
and al, bl ; (with the same values of al and bl, as in previous example, al gets a value of 0)
```
:::
:::
##### e. Comparison Instructions
* CMP - Comparison Instruction - compares integers
:::spoiler
* CMP performs a `mental` substraction - **affects the flags** as if the substraction had taken place, but does not store the result of the substraction.
* Công thức chi tiết:
* ==**cmp**== **reg$_{8 (16,32)}$** / **mem$_{8(16,32)}$** , **reg$_{8 (16,32)}$** / **imm$_{8 (16,32)}$**
:::spoiler
:::info
* Source: **reg$_{8 (16,32)}$** / **imm$_{8 (16,32)}$**
* Destination: **reg$_{8 (16,32)}$** / **mem $_{8(16,32)}$**
:::
* ==**cmp**== **reg$_{8 (16, 32)}$** , **reg$_{8 (16,32)}$** / **mem$_{8(16,32)}$**
:::spoiler
:::info
* Source: **reg$_{8 (16,32)}$** / **mem$_{8(16,32)}$**
* Destination: **reg$_{8 (16, 32)}$**
:::warning
**:negative_squared_cross_mark: Operands have to be of the same size**
:::
* Examples:
* Không bằng nhau:
```p=
mov al, 11111100b
mov bl, 00000010b
cmp al, bl ; (ZF (zero flag) gets a value 0)
```
* Bằng nhau:
```p=
mov al, 11111100b
mov bl, 11111100b
cmp al, bl ; (ZF (zero flag) gets a value 1)
```
:::
##### f. Jump Instruction
* Unconditional Jump Instruction
:::spoiler
* Công thức tổng quát: JMP <Label>
* JMP tells the processor that the next instruction to be executed is located at the label that is given as part of jmp instruction.
* Example
:::spoiler
```p=
mov eax, 1
inc_again: ; this is infinite loop !
inc eax
jmp inc_again
mov ebx, eax ; this instruction is never reached from this code.
```
:::
* Conditional Jump Instructions
:::spoiler
* Công thức tổng quát: J<Condition> <Label>
* execution is transferred to the target instruction only if the specified condition is satisfied.
* usually, the condition being tested is the result of the last arithmetic or logic operation.
* Examples:
* Ex 01:
:::spoiler
```p=
mov eax, 1
inc_again:
inc eax
cmp eax, 10
je end_of_loop ; if eax == 10, jump to end_of_loop
jmp inc_again ; go back to the loop
end_of_loop:
```
:::
* Ex 02:
:::spoiler
```p=
mov eax, 1
inc_again:
inc eax
cmp eax, 10
jne inc_again ; if eax != 10, go back to loop
```
:::
* Bảng công thức điều kiện JUMP:
:::spoiler
| Instruction | Description | Flags |
|:---------------:|:--------------------------------------------------------------:|:------------------:|
| JO | Jump if overflow | OF = 1 |
| JNO | Jump if not overflow | OF = 0 |
| JS | Jump if sign | SF = 1 |
| JNS | Jump if not sign | SF = 0 |
| JE / JZ | Jump if equal / Jump if zero | ZF = 1 |
| JNE / JNZ | Jump if not equal / Jump if not zero | ZF = 0 |
| JB / JNAE / JC | Jump if below / Jump if not above or equal / Jump if carry | CF = 1 |
| JNB / JAE / JNC | Jump if not below / Jump if above or equal / Jump if not carry | CF = 0 |
| JBE / JNA | Jump if below or equal / Jump if not above | CF = 1 or ZF = 1 |
| JA / JNBE | Jump if above / Jump if not below or equal | CF = 0 or ZF = 0 |
| JL / JNGE | Jump if less / Jump if not greater or equal | SF <> OF |
| JGE / JNL | Jump if greater or equal / Jump if not less | SF = OF |
| JLE / JNG | Jump if less or equal / Jump if not greater | ZF = 1 or SF <> OF |
| JG / JNLE | Jump if greater / Jump if not less or greater | ZF = 0 or SF = OF |
| JP / JPE | Jump if parity / Jump if parity even | PF = 1 |
| JNP / JPO | Jump if not parity / Jump if parity odd | PF = 0 |
| JCXZ / JECXZ | Jump if CX register 0 / Jump if ECX register 0 | CX = 0 / ECX = 0 |
:::
:::
##### g. Declare Initialized Data
* Công thức tổng quát
:::spoiler
:::success
$\Rightarrow$ D<size> [initialValue]
:::
* Bảng công thức cú pháp
:::spoiler
| Pseudo - instruction | <size> field | <size> value |
|:--------------------:|:---------------:|:------------:|
| DB | byte | 1 byte |
| DW | word | 2 bytes |
| DD | double word | 4 bytes |
| DQ | quad word | 8 bytes |
| DT | ten byte | 10 bytes |
| DDQ | double quadword | 16 bytes |
| DO | octo word | 16 bytes |
:::
* Examples
:::spoiler
```p=
var: db 0x55 ; define a variable 'var' of size byte, initialized by 0x55
var: db 0x55, 0x56, 0x57 ; three bytes in succession
var: db 'a' ; character constant 0x61 (ascii code of 'a')
var: db 'hello', 13, 10, '$' ; string constant
var: dw 0x1234 ; 0x34 0x12
var: dw 'A' ; 0x41 0x00 - complete to word
var: dw 'AB' ; 0x41 0x42
var: dw 'ABC' ; 0x41 0x42 0x43 0x00 - complete to word
var: dd 0x12345678 ; 0x78 0x56 0x34 0x12
```
:::
##### h. Arrays
:::spoiler
* Any consecutive storage locations of the same size can be called array.
```p=
X DW 40CH,10B,-13,0 ; Components of X are at X, X+2, X+4, X+6
Y DB 'This is an array' ; Components of Y are at Y, y+1, Y+2, ..., Y+15
Z DD -2019, FFFFFh, 100b ; Components of Z are at Z, Z+4, Z+8
```
* DUP allows a sequence of storage locations to be defined.
* Only used as an operand of a define directive
```p=
DB 40 DUP (?) ; 40 Bytes uninitialized
Table1 DW 10 DUP (?) ; 10 Words, uninitialized
Mes DB 3 DUP ('ole') ; 9 Bytes, initialized as oleoleole
a DB 30 DUP ('?') ; 30 Bytes, each initialized to ?
DD 9 DUP (0) ; 9 DWords, initialized as 0
Matrix DW 3 DUP (5 DUP (?)) ; define a 3 x 5 matrix
```
:::
#### 4. Segment Directives
* There are 5 most Directives : .Model, .Code, .Data, .Stack, .End
* .MODEL
* .Model statement followed by the size of the memory system designates the Memory Model.
* Syntax of Memory Models: .Model *memory_model*
* tiny: code + data <= 64K(.computer program)
* small: code <= 64K, data <= 64K, one of each
* medium: data <= 64K, one data segment
* compact: code <= 64K, one code segment
* large: multiple code and data segments
* huge: allows individual arrays to exceed 64K
* flat: no segments, 32 - bit addresses, protected mode only (80386 and higher)
* .CODE
* Designates the beginning of the CODE segment in the program.
* END
* Designates the ending of the CODE segment in the program.
* .DATA
* Designates the beginning of the DATA segment in the program.
* .STACK
* Defines STACK segment in the program.
* Syntax:
```p=
.STACK [memory - size] ; memory size is optional
```
* Default memory size for stack segment is 1KB.
* Initializes Stack Segment (SS), Stack Pointer (SP) and Base Pointer (BP).
#### 5. Memory Organization
* The assembler uses two basic formats for developing software:
1. Using Memory Models:
* Memory Models are unique to the MASM assembler program.
* The TASM assembler also uses memory models, but they differ somewhat from the MASM models.
* The models are easier to use for some simple tasks.
2. Using full-segment definitions:
* The full-segment definitions are common to most assemblers, including the Intel assembler, and are often used for software development.
* The full - segment definitions offer better control over the assembly language task and are recommended for complex programs.
#### 6. Some form of Assembly Program
* Form 01
```p=
.Model Small ; Select a memory model
.Stack 100h ; Define the stack size
.Code
; code
End
```
* Form 02
```p=
.Model Small
.Stack 100h
.Data
; Declare variables
.Code
Main proc
; code
Main endp
; other procs
End Main
```
#### 5. Standard I/O
* DOS funtion calls are used for Standard Input / Output in Assembly language (8086).
* To use a DOS function call in a DOS program.
1. Place the function number in AH (8 bit register) and other data that might be necessary in other registers.
2. Once everything is loaded, execute the INT 21h instruction to perform the task.
* After execution of a DOS funtion, it may return results in some specific registers.
* Examples:
```p=
MOV AH, 01H ; load DOS funtion number in AH
INT 21H ; access DOS
; returns with AL = ASCII key code
```
* AH = 1 $\#$ INT 21h : Read the Keyboard (nhập ký tự)
* This function waits until a character is input from the keyboard.
* Returns ASCII key code of character in AL register.
* AH = 2 $\#$ INT 21h : Write to Standard Output Device (xuất ký tự)
* This function displays single character on the video display.
* ASCII code of the character to be displayed must be loaded in DL register.
* Examples:
```p=
MOV DL, 'A' ; load ASCII key code of Character 'A' in DL
MOV AH, 2 ; load DOS function number in AH
INT 21h ; access DOS Interrupt 21h procedure
```
* AH = 9 $\#$ INT 21h : Display a character string (xuất chuỗi ký tự)
* This function displays a character string on the video display.
* The character string must end with '$' (24H). The string can be of any length and may contain control characters such as CR and LF.
* DX must contain address of the character string.
* Examples:
```p=
Buf DB "Hello World$" ; define character string
MOV DX, offset Buf ; load address of the string in DX
MOV AH,9
INT 21h
```
### II. MIPS
#### 1. MIPS (RISC) Design Principles
* Simplicity favors regularly
* fixed size instructions - 32 bits
* small number of instruction formats
* opcode always the first 6 bits
* Good design demands good compromises
* three instruction formats
* Smaller is faster
* limited instruction set
* compromise on number of registers in register file
* limited number of addressing modes
* Make the common case fast
* arithmetic operands from the register file (load-store machine)
* allow instructions to contain immediate operands
#### 2. MIPS Organization
<center>
<img src = https://scontent.fsgn2-11.fna.fbcdn.net/v/t1.15752-9/385529457_745631557453686_5176200896300992178_n.png?_nc_cat=105&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=bOwzPeK8ukAAX9WGVx6&_nc_ht=scontent.fsgn2-11.fna&oh=03_AdT1QwEUg-o4Ct71pmq2i12txNDH_aMN-Llo4P014-4IMw&oe=65AF3CFC>
</center>
#### 3. MIPS R3000 Instruction Set Architecture (ISA)
* Instruction Categories
* Computational
* Load / Store
* Jump and Branch
* Floating Point
* coprocessor
* Memory Management
* Special
<center>
<img src = https://scontent.fsgn2-8.fna.fbcdn.net/v/t1.15752-9/410679934_257995490633634_8806890268468616796_n.png?_nc_cat=102&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=gZvDVn3X67AAX-Nod8k&_nc_ht=scontent.fsgn2-8.fna&oh=03_AdTtTcOsxlSRuhhWDYYNjVhi--FeTrFzTjjGOTloxihnuw&oe=65AF6127>
<img src = https://scontent.fsgn2-6.fna.fbcdn.net/v/t1.15752-9/411631054_221312247685190_2877010231180290596_n.png?_nc_cat=111&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=yUm77Pk60TAAX9aaDWj&_nc_ht=scontent.fsgn2-6.fna&oh=03_AdQhH0jNWyX3PjItPiLkwFwgwDQgyWo0ryaWmwy6l9kJRg&oe=65AF4623>
</center>
#### 4. MIPS Addressing Modes
<center>
<img src = https://scontent.xx.fbcdn.net/v/t1.15752-9/403604126_1033912274549233_1430823845115807141_n.png?stp=dst-png_p403x403&_nc_cat=107&ccb=1-7&_nc_sid=510075&_nc_ohc=cQdWTpY7eDQAX9GE4RA&_nc_ad=z-m&_nc_cid=0&_nc_ht=scontent.xx&oh=03_AdSjSeQ6EUtRBh3pKfBrkkEa1AASn-M6LNAqpLKylM4WhQ&oe=65AF6A79>
</center>
#### 5. MIPS Register Convention
<center>
<img src = https://scontent.fsgn2-9.fna.fbcdn.net/v/t1.15752-9/410432097_768182885350428_7083352675499292074_n.png?_nc_cat=106&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=z7FBBwrrYPMAX_5DRL-&_nc_ht=scontent.fsgn2-9.fna&oh=03_AdQprAY24JJQqrMNZpsXr60GumEqsSbzHUrb_FQNxzHMJQ&oe=65AF65F3>
</center>
#### 6. A MIPS Sample Program
* C program
```cpp=
#include <stdio.h>
int main (int argc, char *argv[])
{
int i;
int sum = 0;
for (i = 0; i <= 100; i = i + 1)
sum = sum + i * i;
printf("The sum from 0 ... 100 is %d\n", sum);
}
```
* MIPS Assembly Program
```p=
.text
.align 2
.globl main
main:
subu $sp, $sp, 32
sw $ra, 20($sp)
sd $a0, 32($sp)
sw $0, 24($sp)
sw $0, 28($sp)
loop:
lw $t6, 28($sp)
mul $t7, $t6, $t6
lw $t8, 24($sp)
addu $t9, $t8, $t7
sw $t9, 24($sp)
addu $t0, $t6, 1
sw $t0, 28($sp)
ble $t0, 100, loop
la $a0, str
lw $al, 24($sp)
jal printf
move $v0, $0
lw $ra, 20($sp)
addu $sp, $sp, 32
jr $ra
.data
.align 0
str:
.asciiz "The sum from 0 ... 100 is %d\n"
```
* Machine Code Memory Dump
<center>
<img src = https://scontent.fsgn2-7.fna.fbcdn.net/v/t1.15752-9/412704031_735277281842125_8092078504235107638_n.png?_nc_cat=100&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=J3dKWd17CWwAX8YRwE4&_nc_ht=scontent.fsgn2-7.fna&oh=03_AdRXkWj_REZl8drvJLvBejyqtZ6EV-RE6dshXIbT8DSLpw&oe=65AF6067>
</center>
* Reverse Engineered Code
```p=
addiu $29, $29, -32
sw $31, 20($29)
sw $4, 32($29)
sw $5, 36($29)
sw $0, 24($29)
sw $0, 28($29)
lw $14, 28($29)
lw $24, 24($29)
multu $14, $14
addiu $8, $14, 1
slti $1, $8, 101
sw $8, 28($29)
mflo $15
addu $25, $24, $15
bne $1, $0, -9
sw $25, 24($29)
lui $4, 4096
lw $5, 24($29)
jal 1048812
addiu $4, $4, 1072
lw $31, 20($29)
addiu $29, $29, 32
jr $31
move $2, $0
```
#### 7. Procedures
* Supporting Procedures
* Process:
* Place parameters where procedure can access them
* Transfer control to the procedure
* Acquire storage resources for the procedure
* Perform the task
* Place result where calling program can access it
* Return control to calling program
* Support structure:
* $a0 $\to$ $a3 : argument passing registers
* $v0 $\to$ $v1 : return value registers
* $ra : return address integer
* Procedure Call Convention
* First caller must:
1. Pass arguments. By convention, the first four arguments are passed in registers $a0 $\to$ $a3. Any remaining arguments are pushed on the stack and appear at the beginning of the called procedure's stack frame.
2. Save caller - saved registers. The called procedure can use these registers ($a0 $\to$ $a3 and $t0 $\to$ $t9) without first saving their value. If the caller expects to use one of these registers after a call, it must save its value before the call.
3. Execute a jal instruction, which jumps to the callee's first instruction and saves the return address in register $ra.
<center>
<img src = https://scontent.fsgn2-8.fna.fbcdn.net/v/t1.15752-9/385545639_396736072709053_3841746264092268563_n.png?_nc_cat=102&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=5yMszlW27xgAX86FcaP&_nc_ht=scontent.fsgn2-8.fna&oh=03_AdRpuwoc-b2SWSlq9gpOS7YV74R_O0fdpLRrIDjCWA0AnA&oe=65AF7827>
</center>
* Before a called routine starts running, it must take the following steps to set up its stack frame.
1. Allocate memory for the frame by substracting the frame's size from the stack pointer.
2. Save callee-saved registers in the frame. A callee must save the values in these registers ($s0 $\to$ $s7, $fp, and $ra) before altering them since the caller expects to find these registers unchanged after the call. Register $fp is saved by every procedure that allocates a new stack frame. However, register $ra only needs to be saved if the callee itself makes a call. The other callee-saved registers that are used also must be saved.
3. Establish the frame pointer by adding the stack frame's size minus 4 to $sp and storing the sum in register $fp.
* Finally, the callee returns to the caller by executing the following steps:
1. If the callee is a function that returns a value, place the returned value in register $v0.
2. Restore all callee-saved registers that were saved upon procedure entry.
3. Pop the stack frame by adding the frame size to $sp.
4. Return by jumping to the address in register $ra.
* MIPS 32 Context Frames
<center>
<img src = https://scontent.fsgn2-7.fna.fbcdn.net/v/t1.15752-9/410527959_1111447020014107_2732132554106947472_n.png?_nc_cat=108&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=0yLY74efiigAX8yn43l&_nc_ht=scontent.fsgn2-7.fna&oh=03_AdQ4Nol4127vEyYkt5UQwy_b_O9Chhv177UZsAEQA4jF4w&oe=65AF632A>
</center>
* Calling Procedure : Spilling Registers
* What if the callee needs more registers ? What if the procedure is recursive ?
:::spoiler
$\Rightarrow$ It uses a **stack** - a last-in-first-out queue- in memory for passing additional values or saving (recursive) return address(es)
<center>
<img src = https://scontent.fsgn2-4.fna.fbcdn.net/v/t1.15752-9/410571369_353298167301881_1528822442148512720_n.png?_nc_cat=101&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=xV5xke2GXKgAX-wZeRL&_nc_ht=scontent.fsgn2-4.fna&oh=03_AdQyqtQMR_iySHRvCSvDSIOFG7lJxr6XC5pNGV5unT2B5Q&oe=65AF5FFB>
</center>
* $sp is used to address the stack (which "grows" from high address to low address)
* add data onto the stack $\to$ push
* $sp = $sp - 4 $\Rightarrow$ data on
* stack at new $sp
* remove data from the stack $\to$ pop
* data from stack at $sp
* $sp = $sp + 4
:::
#### 8. MIPS Arithmetic Instructions
* MIPS assembly language arithmetic statement
* add $t0, $s1, $s2
* sub $t0, $s1, $s2
* Each arithmetic instruction performs only **one** operator
* Each arithmetic instruction fits in 32 bits and specifies exactly **three** operands
<center>
<img src = https://scontent.fsgn2-6.fna.fbcdn.net/v/t1.15752-9/410740372_798366678976839_7833418764699149855_n.png?_nc_cat=110&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=yCYKXFWOjXoAX-lH5bn&_nc_ht=scontent.fsgn2-6.fna&oh=03_AdSE5vl0veCqasUnCLHpHOJzhUnDT0Rfdk8FtqtMaSvdZQ&oe=65AF962D>
</center>
* Operand order is fixed (destination first)
* Those operands are **all** contained in datapath's **register file** ($t0, $s1, $s2) - indicated by $.
#### 9. Machine Language - Add Instruction
* Instructions, like registers and words of data, are 32 bits long.
* Arithmetic Instruction Format (R Format):
<center>
<img src = https://scontent.fsgn2-7.fna.fbcdn.net/v/t1.15752-9/403419892_1326131571440911_305352265323133308_n.png?_nc_cat=108&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=shWPKiVvib0AX8nBzUF&_nc_ht=scontent.fsgn2-7.fna&oh=03_AdRO5Ovup_0oZjM1dmaxaHXILYdgS5-u3-1ui7X6IFZVUQ&oe=65AF9010>
</center>
* **op** $\to$ 6-bits $\to$ **op**code that specifies the operation
* **rs** $\to$ 5-bits $\to$ **r**egister file address of the first **s**ource operand
* **rt** $\to$ 5-bits $\to$ **r**egister file address of the second source operand
* **rd** $\to$ 5-bits $\to$ **r**egister file address of the result's **d**estination
* **shamt** $\to$ 5-bits $\to$ **sh**ift **am**oun**t** (for shift instructions)
* **funct** $\to$ 6-bits $\to$ **funct**ion code augmenting the opcode
#### 10. MIPS Immediate Instructions
* Small constants are used often in typical code
* Possible approaches ?
* put `typical constants` in memory and load them
* create hard-wired registers (like $zero) for constants like 1
* have special instructions that contain constants !
<center>
<img src = https://scontent.fsgn2-6.fna.fbcdn.net/v/t1.15752-9/412917105_1034817684452967_7934568067562472346_n.png?_nc_cat=110&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=4ZA9o5CODmEAX9s5Ehz&_nc_ht=scontent.fsgn2-6.fna&oh=03_AdT8sH03uNXykzVdV0xnoBsIhfOaeMOV3C3e6cN4uXOZIQ&oe=65AF9B08>
</center>
* Machine format (I format):
<center>
<img src = https://scontent.fsgn2-7.fna.fbcdn.net/v/t1.15752-9/410662560_626529556183991_8974267361659594382_n.png?_nc_cat=100&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=ZtmjQbztNmkAX_Hee7Y&_nc_ht=scontent.fsgn2-7.fna&oh=03_AdQsAXqNGPXfMsqC025pkg4r4g9qHT0A1ZVhWtwL-SikVg&oe=65AF9501>
</center>
* The constant is kept ==inside== the instruction itself !!!
* Immediate format ==limits== values to the range $+ 2^{15} - 1 \to - 2^{15}$
* How about larger constants ?
* We'd also like to be able to load a 32 bit constant into a register, for this we must use two instructions.
* a new "load upper immediate" instruction
```p=
lui $t0, 1010101010101010
```
* then must get the lower order bits right
```p=
ori $t0, $t0, 1010101010101010
```
<center>
<img src = https://scontent.fsgn2-7.fna.fbcdn.net/v/t1.15752-9/371514131_1102953217725970_7712602038520298855_n.png?_nc_cat=100&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=NFqbqmaVuD4AX_wU_u2&_nc_ht=scontent.fsgn2-7.fna&oh=03_AdRzWf_m6hwwcqztUV36Ty_SX_GmK1-WUEbF0Ac88bO-tQ&oe=65AF9061>
</center>
#### 11. MIPS Memory Access Instructions
* MIPS has two basic **data transfer** instructions for accessing memory
```p=
lw $t0, 4($s3) # load word from memory
sw $t0, 8($s3) # store word to memory
```
* The data is loaded into (lw) or stored from (sw) a register in the register file - a 5 bit address.
* The memory address - a 32 bit address - is formed by adding the contents of the **base address register** to the **offset** value.
* A 16 - bit field meaning access is limited to memory locations within a region of $\pm2^{13}$ or 8192 words ($\pm2^{15}$ or 32768 bytes) of the address in the base register
* Note that the offset can be positive or negative
#### 12. Machine Language - Load Instruction
* Load / Store Instruction Format (I format):
<center>
<img src = https://scontent.fsgn2-6.fna.fbcdn.net/v/t1.15752-9/410555173_1415889759008779_179896745213831715_n.png?_nc_cat=110&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=NCNlM1oAOYAAX9liv5L&_nc_ht=scontent.fsgn2-6.fna&oh=03_AdRpl4ETx0BzUONsjufNTWxQ8Gp4ui3AlPxeaKy_aJewTQ&oe=65AFBA34>
<img src = https://scontent.fsgn2-9.fna.fbcdn.net/v/t1.15752-9/410720643_684841157067140_6995100115906998362_n.png?_nc_cat=103&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=9nd6cwcYVicAX-q3MNq&_nc_ht=scontent.fsgn2-9.fna&oh=03_AdRcgI0c59TUxzP39EE8hWiUgj4sQCMW-iXiTClWdcuEwQ&oe=65AFCF51>
<img src = https://scontent.fsgn2-11.fna.fbcdn.net/v/t1.15752-9/412729659_187590211107964_906011466597537671_n.png?_nc_cat=105&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=71UF_1WlPDIAX9LriRe&_nc_oc=AQmacGkPR0ocSY-ZnkgD1Z7qV2q6wQ6VrDOT_Ruhr2iEKrBlbAmC9qGLPFiCIudv48I&_nc_ht=scontent.fsgn2-11.fna&oh=03_AdT7AxItklf0VOJIz4koqBaGwA1njaTnUgsvxnlIOagRvg&oe=65AFD231>
</center>
#### 13. Byte Addresses
* Since 8-bit bytes are so useful, most architectures address individual bytes in memory
* The memory address of a word must be a multiple of 4 (alignment restriction)
* Big Edian: leftmost byte is word address
* IBM 360/370, Motorola 68k, MIPS, Sparc, HP PA
* Little Edian: rightmost byte is word address
* Intel x86/x64, DEC Vax, DEC Alpha (Windows NT)
<center>
<img src = https://scontent.fsgn2-7.fna.fbcdn.net/v/t1.15752-9/412535175_1447554846102462_269226560189937578_n.png?_nc_cat=108&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=MPF_9-mMrwEAX9BnJiJ&_nc_ht=scontent.fsgn2-7.fna&oh=03_AdTKlNgatP2pv_4Wmj-K28zrFbuKZnITCLQFVGubhYM4Dg&oe=65AFC438>
</center>
#### 14. MIPS Control Flow Instructions
* MIPS **conditional branch** instructions:
```p=
bne $s0, $s1, Lbl # go to Lbl if
$s0 # $s1
beq $s0, $s1, Lbl # go to Lbl if
$s0 = $s1
```
* Examples:
```p=
if (i == j)
h = i + j;
bne $s0, $s1, Lbl1
add $s3, $s0, $s1
Lbl1: ...
```
* Instruction Format (I format):
<center>
<img src = https://scontent.fsgn2-11.fna.fbcdn.net/v/t1.15752-9/412693535_1106278100363187_3233867810403602674_n.png?_nc_cat=105&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=luG1ZqBiB5kAX-0BALc&_nc_ht=scontent.fsgn2-11.fna&oh=03_AdT8usAN5A2APUqDefI6n5xQ2F2ulzNFHf8f6N_MLoFg2A&oe=65AFBC0E>
</center>
* How is the branch destination address specified ?
:::spoiler
* Use a register (like in lw and sw) added to the 16-bit offset
* which register ?
:::spoiler
$\Rightarrow$ **Instruction Address Register (the PC)**
* its use is automically implied by instruction
* PC gets updated (PC + 4) during the **fetch** cycle so that it holds the address of the next instruction.
:::
* limits the branch distance to $- 2^{15} \to + 2^{15} - 1$ instructions from the (instruction after the) branch instruction, but most branches are local anyway.
<center>
<img src = https://scontent.fsgn2-6.fna.fbcdn.net/v/t1.15752-9/411599739_737447804943731_5054311730792767244_n.png?_nc_cat=110&ccb=1-7&_nc_sid=8cd0a2&_nc_ohc=iJtkejwMF-AAX-Wt-Sk&_nc_ht=scontent.fsgn2-6.fna&oh=03_AdSqBIri0cpYLZLDkEQJp9J9YWiemRCt0K_eOSEWAOzssQ&oe=65AFC810>
</center>
:::