This is my first post! And I want to start it with a special and unpopular topic, Assebmly at least when we first start programming. However, this language is important to any programmer who wants to understand how processors, operating systems, firmware, compilers, and programming languages work.
Assembly is a human-readable way of representing Machine Code or CPU Instruction Set.
As we said, that is a human-readable language and not a Machine Code, so the machine will not run it as it is. That’s why there is a program called Assembler that converts the assembly code that we write to Machine Code.
How Assembly Works
First we should understand that our assembly code run on a CPU, so we have two things first is that our code should load into an address in memory, second is that our code will take control of the cpu from the operating system. and we do that in assembly by using using ‘org’ to load our code in a specific address in memory and ‘ret’ to return the control to the operating system.
quick note, we write assembly values (like addresses …) in hexadecimal, as hexadecimal is more human-readable than binary.
as we said assembly run code in the CPU, and as we know most of program use data or storage in programs to take decisions or do calculations and store results and so on. here in assembly as we run it in the cpu we use Registers to store data.
example:
mov al, 'A'
in this example we move the character “A” to the register “al” so here the register is “al” and that register we can store only one byte (8 bits). no if we want to store more bytes we can use ‘db’ (data byte) that lets us store more charachters in the same line.
db "hello world",0
Assembly & BIOS
In modern programming languages, we use hardware via APIs or SDKs, so we can talk to the machine and perform actions like printing to the screen, even if we don’t know how that will happen! But this is not the case in assembly. As a low-level language, it gives us more control over the machine. By using assembly, we give the machine instructions step by step. This communication can happen through the int instruction and BIOS. it provides us with a set of prewritten routines that we use to interact with the hardware.
Example :
org 100h
mov ah, 0eh
mov al, "A"
int 10h
ret
In the example, we want to print the character ‘A’ to the screen. But first, we need to talk to the screen, and this happens with the help of the BIOS. We do it via int 10h, which is the video service. We set ah to 0Eh, which tells the BIOS we want to use the sub-function of int 10h.
“Hello Assembly”
org 100h
jmp main
message: db 'Hello Assembly!', 0
print:
mov ah, 0eh
._loop:
lodsb
cmp al, 0
je .done
int 10h
jmp ._loop
.done:
ret
main:
mov si, message
call print
ret
In this, our first program in Assembly, the first thing to understand is that in Assembly, we execute code from top to bottom. For example, when we want to use a variable, we should define it first and then use it — like in Python. Yes, there are other styles of coding where we can define a variable later and the code still works, like in JavaScript. This is because JavaScript uses a concept called hoisting.
As a result, in Assembly they use something called a label, and we jump to those labels. It’s like we define a piece of code, and when we want to run it, we jump to it — that simple!
How “Hello Assembly” code is executed:
We jump to the main label. At the main label, we copy the address of message into the SI register. Then we call the print label. In the print label, we move 0Eh into AH, which is the BIOS function (interrupt 10h) responsible for printing to the screen. After that, we enter a loop. Here, we use lodsb, which takes the first byte from the message (pointed to by SI) and copies it into AL. Then we compare AL with 0. If it’s 0, that means we’ve reached the end of the message, and we jump to the .done label. If not, we call interrupt 10h to print the character, and loop again!