Перейти к содержанию

BootASM: Hello, world!

Запускаем «Hello, world!» вне операционных систем, в реальном режиме, с дискеты.

section .text
     use16
     org  0x7C00  			; наша программа загружается по адресу 0x7C00


start:
     mov  ax, cs
     mov  ds, ax         		; выбираем сегмент данных
 
     mov  si, message
     cld              			; направление для строковых команд
     mov  ah, 0x0E    			; номер функции BIOS
     mov  bh, 0x00    			; страница видеопамяти


puts_loop:
     lodsb            			; загружаем очередной символ в al
     test al, al      			; нулевой символ означает конец строки
     jz   puts_loop_exit
     int  0x10             		; вызываем функцию BIOS
     jmp  puts_loop


puts_loop_exit:
     jmp  $           			; вечный цикл
 

message:
     db   'Hello World!', 0


finish:
     times 0x1FE-finish+start db 0
     db   0x55, 0xAA  			; сигнатура загрузочного сектора
#!/bin/bash

# remove files
rm -rf test.bin test.img


# compile files
yasm -f bin -o test.bin test.asm


# make fdd
dd if=/dev/zero of=test.img bs=1024 count=1440


# write bin to fdd
dd if=test.bin of=test.img conv=notrunc


# running fdd
qemu-system-x86_64 -fda test.img -boot a

Переходим в Защищённый режим

;16-битная адресация, пока мы находимся в реальном режиме
use16
org 0x7c00
start:
  jmp 0x0000:entry              ;теперь CS=0, IP=0x7c00
entry:
  mov ax, cs
  mov ds, ax
 
;очистить экран
  mov ax, 0x0003
  int 0x10
 
;открыть A20
  in  al, 0x92
  or  al, 2
  out 0x92, al
 
;Загрузить адрес и размер GDT в GDTR
  lgdt  [gdtr]
;Запретить прерывания
  cli
;Запретить немаскируемые прерывания
  in  al, 0x70
  or  al, 0x80
  out 0x70, al
 
;Переключиться в защищенный режим
  mov  eax, cr0
  or   al, 1
  mov  cr0, eax
 
;Загрузить в CS:EIP точку входа в защищенный режим
  O32 jmp 00001000b:pm_entry
 
;32-битная адресация
use32
;Точка входа в защищенный режим
pm_entry:
;Загрузить сегментные регистры (кроме SS)
  mov  ax, cs
  mov  ds, ax
  mov  es, ax
 
  mov  edi, 0xB8000             ;начало видеопамяти в видеорежиме 0x3
  mov  esi, msg                 ;выводимое сообщение
  cld
.loop                           ;цикл вывода сообщения
  lodsb                         ;считываем очередной символ строки
  test al, al                   ;если встретили 0
  jz   .exit                    ;прекращаем вывод
  stosb                         ;иначе выводим очередной символ
  mov  al, 7                    ;и его атрибут в видеопамять
  stosb
  jmp  .loop
.exit
 
  jmp  $                        ;зависаем
 
msg:
  db  'Hello World!', 0
 
;Глобальная таблица дескрипторов.
;Нулевой дескриптор использовать нельзя!
gdt:
  db  0x00, 0x00, 0x00, 0x00, 0x00,      0x00,      0x00, 0x00 
  db  0xFF, 0xFF, 0x00, 0x00, 0x00, 10011010b, 11001111b, 0x00
gdt_size  equ $ - gdt
 
;данные, загружаемые в регистр GDTR
gdtr:
  dw  gdt_size - 1
  dd  gdt
 
finish:
times 0x1FE-finish+start db 0
db   0x55, 0xAA ; сигнатура загрузочного сектора
Опубликовано в рубрикеПрограмммирование