What are the various Data types available in GNU Assembler?
A group of bits used in representing a unit to frame various data types.What is a data type?
A data type is used to identify the characteristic of a data. Various data types are as below.- byte
- word
- int
- ascii
- asciz
byte:
It is eight bits long. A byte is considered as the smallest unit on a computer onto which data can be stored through programming.
word:
It is a unit of data that is 16 bits long.
.text #executable code location
.globl _start;
_start: #code entry point
. = _start + 510 #mov to 510th byte from 0 pos
.byte 0x55 #append boot signature
.byte 0xaa #append boot signature
int:
An int is a data type that represents data of 32 bits long. Four bytes or two words constitute an int.ascii:
A data type to represent a group of bytes with out a null terminator.asciz:
A data type to represent a group of bytes terminated with a null character in the end.How do I generate code for real mode through an assembler?
When the CPU starts in Real Mode (16-bit), all we can do while booting from a device is to utilize the built in functions provided by the BIOS to proceed further. What I mean here is we can utilize the functions of BIOS to write our own boot loader code, and then dump into onto the boot sector of the device, and then boot it. Let us see how to write a small piece of code in assembler that generates 16-bit CPU code through GNU Assembler.Example: test.S
.code16 #generate 16-bit code.text #executable code location
.globl _start;
_start: #code entry point
. = _start + 510 #mov to 510th byte from 0 pos
.byte 0x55 #append boot signature
.byte 0xaa #append boot signature
Let me explain each statement in the code above.
On the command prompt type the below:
How to copy the executable code to a bootable device and then test it?
To create a floppy disk image of 1.4mb size, type the following on the command prompt.
#romimage: file=/usr/local/bochs/1.4.1/BIOS-bochs-latest, address=0xf0000
#vgaromimage: /usr/local/bochs/1.4.1/VGABIOS-elpin-2.40
floppya: 1_44=floppy.img, status=inserted
boot: a
log: bochsout.txt
mouse: enabled=0
You should see a typical emulating window of bochs as below.
Nothing has just happened as we did not write anything to display on the screen in our code. So you only see a message “Booting from Floppy”. Let us see a few more examples on writing assembly code on an assembler.
- .code16: It is a directive or a command given to an assembler to generate 16-bit code rather than 32-bit ones. Why is this hint necessary? Remember that you will be using an operating system to utilize an assembler and a compiler to write boot loader code. However, I have also mentioned that an operating system works in 32 bit protected mode. So when you utilize assembler on a protected mode operating system, it’s configured by default to produce 32-bit code rather than 16-bit code, which does not serve the purpose, as we need 16-bit code. To avoid assembler and compilers generating 32-bit code, we use this directive.
- .text: The .text section contains the actual machine instructions, which make up your program.
- .globl _start: .global <symbol> makes the symbol visible to linker. If you define symbol in your partial program, its value is made available to other partial programs that are linked with it. Otherwise, symbol takes its attributes from a symbol of the same name from another file linked into the same program.
- _start: Entry to the main code and _start is the default entry point for the linker.
- . = _start + 510: traverse from beginning through 510th byte
- .byte 0x55: It is the first byte identified as a part of the boot signature.(511th byte)
- .byte 0xaa: It is the last byte identified as a part of the boot signature.(512th byte )
How to compile an assembly program?
Save the code as test.S file.On the command prompt type the below:
- as test.S -o test.o
- ld –Ttext 0x7c00 --oformat=binary test.o –o test.bin
What does the above commands means to us anyway?
- as test.S –o test.o: this command converts the given assembly code into respective object code which is an intermediate code generated by the assembler before converting into machine code.
- The --oformat=binary switch tells the linker you want your output file to be a plain binary image (no startup code, no relocations, ...).
- The –Ttext 0x7c00 tells the linker you want your "text" (code segment) address to be loaded to 0x7c00 and thus it calculates the correct address for absolute addressing.
What is a boot signature?
Remember earlier I was briefing about boot record or boot sector loaded by BIOS program. How does BIOS recognize if a device contains a boot sector or not? To answer this, I can tell you that a boot sector is 512 bytes long and in 510th byte a symbol 0x55 is expected and in the 511th byte another symbol 0xaa is expected. So I verifies if the last two bytes of a boot sector are 0x55 and 0xaa and if it is then it identifies that sector as a boot sector and proceeds execution of the boot sector code or else it throws an error that the device is not bootable. Using a hexadecimal editor you can view the contents of the binary file in a more readable way and below is the snapshot for your reference when you view the file using the hexedit tool.How to copy the executable code to a bootable device and then test it?
To create a floppy disk image of 1.4mb size, type the following on the command prompt.
- dd if=/dev/zero of=floppy.img bs=512 count=2880
- dd if=test.bin of=floppy.img
- bochs
- sudo apt-get install bochs-x
Sample bochsrc.txt file
megs: 32#romimage: file=/usr/local/bochs/1.4.1/BIOS-bochs-latest, address=0xf0000
#vgaromimage: /usr/local/bochs/1.4.1/VGABIOS-elpin-2.40
floppya: 1_44=floppy.img, status=inserted
boot: a
log: bochsout.txt
mouse: enabled=0
You should see a typical emulating window of bochs as below.
Observation:
Now if you view the test.bin file in a hexadecimal editor you will see the boot signature is placed at the end of the 510th byte and here is the screenshot for your reference.Nothing has just happened as we did not write anything to display on the screen in our code. So you only see a message “Booting from Floppy”. Let us see a few more examples on writing assembly code on an assembler.
Example: test2.S
.code16 #generate 16-bit code.text #executable code location
.globl _start;
_start: #code entry point
movb #39;X' , %al #character to print
movb $0x0e, %ah #bios service code to print
int $0x10 #interrupt the cpu now
. = _start + 510 #mov to 510th byte from 0 pos
.byte 0x55 #append boot signature
.byte 0xaa #append boot signature
After typing the above, save to test2.S and then compile as instructed before by changing the source file name. When you compile and successfully copy this code to the boot sector and run bochs you should see the below screen. On the command prompt type bochs to see the result and you should see the letter ‘X’ on the screen as shown in the below screenshot.
Congrats!!!
Observation:
if viewed in a hexadecimal editor, you will see that the character 'X' is in the second position from the start address.Now lets do something different like printing a text onto the screen.
Example: test3.S
.code16 #generate 16-bit code.text #executable code location
.globl _start;
_start: #code entry point
#print letter 'H' onto the screen
movb $'H' , %al
movb $0x0e, %ah
int $0x10
#print letter 'e' onto the screen
movb $'e' , %al
movb $0x0e, %ah
int $0x10
#print letter 'l' onto the screen
movb $'l' , %al
movb $0x0e, %ah
int $0x10
#print letter 'l' onto the screen
movb $'l' , %al
movb $0x0e, %ah
int $0x10
#print letter 'o' onto the screen
movb $'o' , %al
movb $0x0e, %ah
int $0x10
#print letter ',' onto the screen
movb $',' , %al
movb $0x0e, %ah
int $0x10
#print space onto the screen
movb $' ' , %al
movb $0x0e, %ah
int $0x10
#print letter 'W' onto the screen
movb $'W' , %al
movb $0x0e, %ah
int $0x10
#print letter 'o' onto the screen
movb $'o' , %al
movb $0x0e, %ah
int $0x10
#print letter 'r' onto the screen
movb $'r' , %al
movb $0x0e, %ah
int $0x10
#print letter 'l' onto the screen
movb #39;l' , %al
movb $0x0e, %ah
int $0x10
#print letter 'd' onto the screen
movb $'d' , %al
movb $0x0e, %ah
int $0x10
. = _start + 510 #mov to 510th byte from 0 pos
.byte 0x55 #append boot signature
.byte 0xaa #append boot signature
Save it as test3.S. When you compile and successfully copy this code to the boot sector and run bochs you should see the below screen.
Okay...now we do something more different than the previous programs.
Let us write an assembly program to print the letters “Hello, World” onto the screen.
We will also try to define functions and macros through which we will try to print the string.
Example: test4.S
#generate 16-bit code.code16
#hint the assembler that here is the executable code located
.text
.globl _start;
#boot code entry
_start:
jmp _boot #jump to boot code
welcome: .asciz "Hello, World\n\r" #here we define the string
.macro mWriteString str #macro which calls a function to print a string
leaw \str, %si
call .writeStringIn
.endm
#function to print the string
.writeStringIn:
lodsb
orb %al, %al
jz .writeStringOut
movb $0x0e, %ah
int $0x10
jmp .writeStringIn
.writeStringOut:
ret
_boot:
mWriteString welcome
#move to 510th byte from the start and append boot signature
. = _start + 510
.byte 0x55
.byte 0xaa
Save it as test4.S. When you compile and successfully copy this code to the boot sector and run bochs you should see the below screen.
Well!!! If you did understand what I have done and you were able to write similar program then congratulations again!
Observation:
What is a function?
A function is a block of code that has a name and it has a property that it is reusable.What is a macro?
A macro is a fragment of code, which has been given a name. Whenever the name is used, it is replaced by the contents of the macro.What is the difference between a macro and a function in terms of syntax?
To call a function we use the below syntax.push <argument>
call <function name>
To call a macro we use the below syntax
macroname <argument>
But the calling and usage syntax of the macro is very simple when compared to that of a function. So I preferred to write a macro and use it instead of calling a function in the main code. You can refer to more materials online as to how to write assembly code on GNU Assembler.