GNU Assembler BIOS Interrupt Handler
I write a loader in Assembly language (GNU Assembler
, syntax AT&T
). You need to write an interrupt handler for it BIOS
.
On the Internet, I found that in order to make my "function" a handler, you need to call the subfunction 0x25
of the interrupt 0x21
, specifying in the register al
the desired number for your interrupt, in the register ds
- a segment, in the register dx
- a shift to your function relative to this segment.
Let them eat program:
.code16
.text
.globl _start
_start:
jmp _boot
.macro mWriteString str
leaw \str, %si
call WriteString
.endm
.func WriteString
WriteString:
lodsb
orb %al, %al
jz WriteString_done
movb $0xe, %ah
movw $9, %bx
int $0x10
jmp WriteString
WriteString_done:
retw
.endfunc
msgHello: .asciz "Hello in my boot loader!\n\r"
myInterrupt:
mWriteString msgHello
iret
_boot:
cli
movw $0x07C0, %ax
movw %ax, %ds
movw %ax, %ss
movw %ax, %sp
sti
mov $0x25, %ah
mov $0x65, %al
mov myInterrupt, %dx
int $0x21
int $0x65
. = _start + 510
.byte 0x55
.byte 0xAA
When interrupted, a line with the text "Hello in my boot loader!
"should be displayed on the screen. But, unfortunately, this line is not output, from where I conclude that the interrupt is not called.
I ask for help in bringing the code to a working state!
1 answers
I have achieved positive results. Special thanks to Mike for a very useful link. Here's what happened:
.code16
.text
.globl _start
_start:
jmp _boot
.macro mWriteString str
leaw \str, %si
call WriteString
.endm
.func WriteString
WriteString:
lodsb
orb %al, %al
jz WriteString_done
movb $0xe, %ah
movw $9, %bx
int $0x10
jmp WriteString
WriteString_done:
retw
.endfunc
msgHello: .asciz "Hello in my boot loader!\n\r"
myInterrupt:
mWriteString msgHello
hlt
// Смещение вектора 0x65
.set off_x65, 0x65*4
old_off_x65: .long 0
old_seg_x65: .long 0
_boot:
cli
movw $0x07C0, %ax
movw %ax, %ds
movw %ax, %ss
movw %ax, %sp
movw $0x0, %ax
movw %ax, %es
// Сохраняем старый вектор
movw %es:off_x65, %ax
movw %ax, old_off_x65
movw %es:off_x65 + 2, %ax
movw %ax, old_seg_x65
// Записываем новый вектор
movw $myInterrupt, %ax
movw %ax, %es:off_x65
push %ds
pop %ax
movw %ax, %es:off_x65+2
sti
int $0x65
. = _start + 510
.byte 0x55
.byte 0xAA