CLOSE

In the previous chapter we learnt on how to print character in the console. Now, we will learn how to print a complete string in the console.

Theory

org directive:

In assembly language, ORG (origin) is a directive that tells the assembler where to place the code or data in memory. It sets the starting address for the code or data that follows it.

Here's the syntax for ORG directive:

ORG address
  • address: is the memory address where the code or data should be located.

For example, in the case of a bootloader written for a PC that loads at memory address 0x7C00, you would use ORG 0x7C00 to specify that the code should be loaded at that memory address.

[ORG 0x7C00]     ; Set origin to 0x7C00, where BIOS loads the bootloader

or

; Set origin to 0x7C00, where BIOS loads the bootloader
ORG 0x7C00

lodsb:

It is an x86 assembly language instruction that loads the byte at the address stored in the DS:SI register pair into the AL register, and then increments or decrements the SI register, depending on the direction flag (DF).

Here's a breakdown of how lodsb works:

  • lodsb loads the byte at the memory location addressed by DS:SI into the AL register.
  • If the direction flag (DF) is clear (0), SI is incremented by 1 after the operation.
  • If the direction flag (DF) is set (1), SI is decremented by 1 after the operation.

For Example:

    mov si, msg     ; Set SI to point to the start of the message
print_string:
    lodsb           ; Load the byte from [DS:SI] into AL and increment SI
    ; AL now contains the byte that was loaded from memory

Understanding the lodsb Instruction:

The lodsb instruction is used to load a byte from memory into the AL register. Here' how it works:

print_string:
    lodsb           ; Load the byte from [DS:SI] into AL and increment SI
  • lodsb loads the byte at the memory location addressed by DS:SI into the AL register.
  • After the operation, the SI register is automatically incremented to point to the next byte in memory.

Defining Strings

In assembly language, strings are defined using the DB (Define Byte) directive. Here's how you can define strings:

msg DB 'Hello, World!', 0  ; Our null-terminated string
  • DB is used to define bytes.
  • 'Hello, World!' is the string you want to define.
  • 0 is the null terminator, which marks the end of the string.

Printing String to the Console

Though it sounds difficult, but its very easy. We just have to do the same thing we did during previous chapter for printing character in the console. This time we have to do it for every character in the string. So, we can use some kind of loop to call the same interrupt routine with different character of string. We would need lodsb instruction for this operation.

[ORG 0x7C00]

    mov si, msg     ; Set SI to point to the start of the message
print_string:
    lodsb           ; Load the byte from [SI] into AL and increment SI
    cmp al, 0       ; Check if AL is the null terminator
    je done         ; If AL is 0, we're done

    mov ah, 0x0E    ; BIOS teletype function
    mov bh, 0x00    ; Page number
    mov bl, 0x07    ; Text attribute (white on black)
    int 0x10        ; BIOS video interrupt

    jmp print_string ; Repeat for the next character

done:
    cli             ; Disable interrupts
    hlt             ; Halt the CPU

msg db 'TheJat!', 0   ; Our null-terminated string

times 510 - ($ - $$) db 0   ; Fill the rest of the sector with zeros
dw 0xAA55                   ; Boot signature
image-122.png

Using Loop Statement

The loop instruction is a useful construct in x86 assembly language for creating loops. It decrements the CX register and jumps to a specified label if the CX register is not zero. It's commonly used in combination with other instructions to repeat a block of code a specific number of times.

Here's how it works:

loop label
  • The loop instruction decrements the CX register by 1.
  • If the CX register is not zero after decrementing, the loop instruction jumps to the specified label.

Here's the modified string printing bootloader code using loop statement:

[ORG 0x7C00]     ; Set origin to 0x7C00, where BIOS loads the bootloader

    mov si, msg     ; Set SI to point to the start of the message
    mov cx, 13      ; Length of the string

print_string:
    mov al, [si]    ; Load the byte from [DS:SI] into AL
    cmp al, 0       ; Check if AL is the null terminator
    je done         ; If AL is 0, we're done

    mov ah, 0x0E    ; BIOS teletype function
    mov bh, 0x00    ; Page number
    mov bl, 0x07    ; Text attribute (white on black)
    int 0x10        ; BIOS video interrupt

    inc si          ; Increment SI to point to the next character
    loop print_string ; Repeat for the next character

done:
    cli             ; Disable interrupts
    hlt             ; Halt the CPU

msg db 'Hello, World!', 0   ; Our null-terminated string

times 510 - ($ - $$) db 0   ; Fill the rest of the sector with zeros
dw 0xAA55                   ; Boot signature

Explanation:

  • We initialize SI to point to the start of the string.
  • We use CX register to keep track of the number of characters to print.
  • Inside the loop, we load the byte from the memory location addressed by SI into the AL register.
  • We compare AL with the null terminator to check if we have reached the end of the string.
  • If not, we print the character to the screen using BIOS interrupt 0x10.
  • Finally, we increment SI to point to the next character in the string and repeat the process until CX becomes zero.