NASM JMP offset ignored
Posted: Sun Feb 04, 2018 8:34 pm
I am new to NASM and i386 assembly. I did some 8 bit work back in the day, but ... enough said about that.
From various tutorials online, I have cobbled together a bootloader that reads a kernelette directly from sector 2 and transfers control.
My problem is that the final JMP instruction's offset address seems to be ignored. I can set JMP SEG:OFFSET to any value of offset and the kernelette still works. Even if the offset is way past the address where the instructions would have loaded (eg 0xFFFF) my kernelette still executes.
I have read all I can about the JMP instruction and nothing says real mode JMP immediate ignores the offset. My code is below.
I don't want code that works by accident, so if anyone can explain the JMP (or NASM's interpretation of JMP) better than what I've found online so far, I would be most grateful!
Thanks for reading.
DP
boot loader code
kernel code
From various tutorials online, I have cobbled together a bootloader that reads a kernelette directly from sector 2 and transfers control.
My problem is that the final JMP instruction's offset address seems to be ignored. I can set JMP SEG:OFFSET to any value of offset and the kernelette still works. Even if the offset is way past the address where the instructions would have loaded (eg 0xFFFF) my kernelette still executes.
I have read all I can about the JMP instruction and nothing says real mode JMP immediate ignores the offset. My code is below.
I don't want code that works by accident, so if anyone can explain the JMP (or NASM's interpretation of JMP) better than what I've found online so far, I would be most grateful!
Thanks for reading.
DP
boot loader code
Code: Select all
;bootloader code
%assign KERNEL_BASE_SEGMENT 0x1000 ; DPP: I added this.
%assign KERNEL_ENTRY_ADDRESS 0x0000 ; DPP: I added this.
%assign KERNEL_SECTOR_START 1 ; DPP: I added this.
%assign KERNEL_SECTOR_COUNT 12 ; DPP: I added this.
%define BOOT_DRIVE_NUMBER 0x80
%assign BIOS_VIDEO_SERVICES 0x10
%assign BIOS_DISK_SERVICES 0x13
%assign READ_DISK_SECTORS 0x02
%assign SET_VIDEO_MODE 0x00
[BITS 16]
[ORG 0x7C00]
mov si, MESSAGE_LOADING
call print
;load kernelette from sector 2 into 0x1000:0000
MOV DL, 0x80 ;drive number
MOV DH, 0x0 ;head (0=base)
MOV CH, 0x0 ;track/cylinder
MOV CL, 0x02 ;sector
MOV BX, 0x1000 ;can't update ES directly, so put destination segment into BX
MOV ES, BX ;place BX in pointer ES
MOV BX, 0x0 ;BX is actually destination offset, so we want it to be zero.
read_disk:
MOV AH, 0x02
MOV AL, 0x01
INT 0x13
JC read_disk ;infinite retry for now.
;pointers to kernel segment (0x1000)
MOV AX, 0x1000
MOV DS, AX ;DS (update data segment)
MOV SS, AX ;SS (update stack segment)
;ANY of these JMPs work. Offset is ignored. why?
JMP 0x1000:0x0000
;JMP 0x1000:0x0200
;JMP 0x1000:0x0020
;JMP 0x1000:0xDADA
;JMP 0x1000:0xFFFF
never_get_here:
cli
hlt
jmp $
print:
mov bp,sp
print_repeat:
lodsb
or al,al
jz print_done
mov ah,0x0e
mov bx,0
int BIOS_VIDEO_SERVICES
jmp print_repeat
print_done:
mov sp,bp
ret
MESSAGE_LOADING db "Loading simple Kernel...",10,13,0
MESSAGE_LOADED db "Kernel Loaded. Transferring control",10,13,0
TIMES 510 - ($ - $$) db 0 ;pad to exact sector size (512) minus signature
DW 0xAA55 ;boot loader signature
Code: Select all
;kernelette code
[BITS 16]
%assign BIOS_VIDEO_SERVICES 0x10
mov AH, 0x0E
mov BH, 0x00
mov BL, 0x07
hello_again:
MOV SI, message_hello ;move msg to SI-pointer
CALL print ;call function to print SI (msg)
mov ah,0 ;wait for keypress
int 16h
jmp hello_again
print:
mov bp,sp
print_repeat:
lodsb
or al,al
jz print_done
mov ah,0x0e
mov bx,0
int BIOS_VIDEO_SERVICES
jmp print_repeat
print_done:
mov sp,bp
ret
message_hello db 'Hello world from the kernel!', 13, 10, ' Press any key to continue!', 13, 10, 0
TIMES 512 - ($ - $$) db 0 ;pad the sector