Skip to main content

6 posts tagged with "assembly"

View All Tags

A simple routine to read char from keyboard using BIOS interrupt

; Function to read a character from the keyboard using BIOS interrupt 0x16
; Returns -> AL holds the read character
getch:
mov ah, 0x00
int 0x16
ret

Example usage

[BITS 16]
[ORG 0x7C00] ; BIOS loads the boot sector here

; Main loop
main:
mov si, buffer ; Initialize pointer to the buffer
input_loop:
; Read a character from the keyboard
call getch ; The read character will be stored as a byte in the al register
sub al, '0' ; Convert ASCII to numerical value
cmp al, 7
ja halt ; If input is greater than '7', jump to halt CPU

mov byte [si], al ; Store numerical value into the buffer
inc si ; Move to the next byte in the program array
jmp input_loop

%include "src/getch.asm"

halt:
jmp halt

; Reserve the remaining space on the boot sector for the program we input
buffer: times 510-($-$$) db 0
; Boot sector magic number
dw 0xAA55

Date created: 2024-09-24

Resources and links

[[os-development-lectures-pdf]]

Example routine for reading from disk

; load DH sectors to ES:BX from drive DL
disk_load:
push dx ; Store DX on stack so later we can recall
; how many sectors were request to be read ,
; even if it is altered in the meantime
mov ah, 0x02 ; BIOS read sector function
mov al, dh ; Read DH sectors
mov ch, 0x00 ; Select cylinder 0
mov dh, 0x00 ; Select head 0
mov cl, 0x02 ; Start reading from second sector ( i.e.
; after the boot sector )
int 0x13 ; BIOS interrupt
jc disk_error ; Jump if error ( i.e. carry flag set )
pop dx ; Restore DX from the stack
cmp dh, al ; if AL ( sectors read ) != DH ( sectors expected )
jne disk_error ; display error message
ret

disk_error:
mov bx, DISK_ERROR_MSG
call print_string
jmp $

; Variables
DISK_ERROR_MSG db "Disk read error !", 0

Example usage

[ORG 0x7c00]

mov [BOOT_DRIVE], dl ; BIOS stores our boot drive in DL, so it's best to
; remember this for later

mov bp, 0x8000 ; Set stack safely out of the way
mov sp, bp

mov bx, 0x9000 ; Load 5 sectors to 0 x0000 (ES ):0 x9000 (BX)
mov dh, 5 ; from the boot disk
mov dl, [BOOT_DRIVE]
call disk_load

mov ax, [0x9000]
call print_hex_word

mov ax, [0x9000 + 512]
call print_hex_word

jmp $

%include "src/disk_load.asm"
%include "src/print_hex_word.asm"

BOOT_DRIVE: db 0;

times 510-($-$$) db 0
dw 0xAA55

times 256 dw 0xdada ; We read this and the next sectors from this disk.
times 256 dw 0xface

The first 512 bytes of a bootable drive, which the BIOS can read into memory and execute immediately after a [[power-on self-test|POST]] check.

Things to note about the boot sector:

  • At this time, the CPU will operate in [[16-bit-real-mode]]. In NASM assembly, this can be signified with [bits 16].

  • The BIOS will load the boot sector onto RAM with offset 0x7C00. This can be signified in NASM assembly as [ORG 0x7c00].

  • The boot sector must end on the magic number 0xaa55.

Example Boot Sector in NASM assembly

[bits 16]                   ; Work in 16-bit mode
[ORG 0x7C00] ; Set memory offset for where BIOS will load this

loop:
jmp loop ; Endless loop

times 510-($-$$) db 0 ; Fill remainder of boot sector with zeroes
dw 0xAA55 ; End with magic number

Date created: 2024-10-01

Description

To build binaries for the ARM architecture, and run them on an x86 based processor inside of linux, we need to set up an environment involving some specialised tools.

Prerequisites

  • qemu (qemu-user)
  • gcc-arm-linux-gnueabihf

Setup

  • Install the required tools
$ sudo apt install build-essential gcc-arm-linux-gnueabihf qemu-user
  • Assemble the target code using the cross-compiler
$ arm-linux-gnueabihf-gcc -o <binary-name> <source-code.c> -static
  • Run the programme
$ qemu-arm <./binary-name>

Date created: 2024-10-01

Description

Normally, we would use gdb to debug binaries on linux, but we need a special setup to debug binaries targetting the ARM architecture while working on a x86 based computer.

Prerequisites

  • gdb-multiarch

Setup

  • Install gdb-multiarch
$ sudo apt install gdb-multiarch
  • Build as shown in [[build-binary-for-arm]].

  • Run the programme in gdb server using [[qemu]]

$ qemu-arm <./binary-name> -g 4242
  • Debug the programme
$ gdb-multiarch 
(gdb) file <./binary-name>
(gdb) target remote localhost:4242