0

I am trying to get my C program to run on a computer with no operating system. I have a version of an MBR that just prints a (!), but when i try to add code to run my C program, as shown here the machine just reboots infinitely.

I only just got the assembly to compile because i took out some definitions and just put the numbers where it says //here Here is my code: `

[org 0x7c00]                        


mov [BOOT_DISK], dl                 



CODE_SEG equ GDT_code - GDT_start
DATA_SEG equ GDT_data - GDT_start

cli
lgdt [GDT_descriptor]
mov eax, cr0
or eax, 1
mov cr0, eax
jmp CODE_SEG:start_protected_mode

jmp $
                                    
                                     
GDT_start:                          
    GDT_null:
        dd 0x0
        dd 0x0

    GDT_code:
        dw 0xffff
        dw 0x0
        db 0x0
        db 0b10011010
        db 0b11001111
        db 0x0

    GDT_data:
        dw 0xffff
        dw 0x0
        db 0x0
        db 0b10010010
        db 0b11001111
        db 0x0

GDT_end:

GDT_descriptor:
    dw GDT_end - GDT_start - 1
    dd GDT_start

[bits 32]
start_protected_mode:


    mov al, '!'
    mov ah, 0x0f
    mov [0xb8000], ax

    ;open the file for reading
   mov eax, 5
file_name db 'e.exe'

   mov ebx, file_name
   mov ecx, 0             ;for read only access
   mov edx, 0777          ;read, write and execute by all
   int  0x80
    

    
   ;read from file
   mov eax, 3
   mov ebx, 1  //here
   mov ecx, 26 //here
   mov edx, 26 //here
   int 0x80

    jmp $


BOOT_DISK: db 0                                    

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

`

user4581301
  • 33,082
  • 7
  • 33
  • 54
  • I don't see an IDT with a handler for interrupt 0x80, so `int 0x80` isn't going to work. Switching to protected mode doesn't magically load a Linux kernel (or any other handlers for `int 0x80` Linux system calls). Also, `db e.exe` in the middle of your code will treat those 4 bytes as machine code: [Assembly (x86): db 'string',0 does not get executed unless there's a jump instruction](https://stackoverflow.com/q/30561366) / [Segmentation fault when using DB (define byte) inside a function](https://stackoverflow.com/q/55642600) – Peter Cordes Nov 26 '22 at 16:50
  • See [How to make the kernel for my bootloader?](https://stackoverflow.com/q/33603842) for what to actually do (complete working example) instead of trying to use system calls from an OS that isn't running. Also, use a debugger to single-step your bootloader, for example Bochs has one built-in. – Peter Cordes Nov 26 '22 at 16:57
  • Under normal circumstances ( with an OS running), the `int 0x80` instruction causes the CPU to look up a function in an Interrupt Descriptor Table (IDT) which is a table of pointers to functions. The IDT is initialized during the boot process by the operating system, so when you try to initiate an `int 0x80` in a computer with no OS, the CPU hasn't been given an IDT so it doesn't know how to handle the interrupt. You will either have to do part of the OS's job and set up an IDT yourself or try to make do without system calls (which should be possible since you will be in real mode) – ZarakshR Nov 26 '22 at 16:58
  • @ZarakshR: There *is* an IVT on entry to a 16-bit MBR bootloader, that's why BIOS calls like `int 0x10` work, and why keyboard input works. (Keyboard interrupt, or possibly USB interrupts triggering SMI to fake a keyboard interrupt.) I'm not sure what happens after switching to protected mode if you haven't used `lidt`, whether it will still use the existing IVT correctly or whether it will treat it as a 32-bit IDT and load garbage causing a double fault and then (assuming that entry is also nonsense) triple fault. The latter would explain the symptoms. – Peter Cordes Nov 26 '22 at 17:02
  • @Peter, you're right - I should have specified that it is specifically interrupt `0x80` that the CPU wouldn't know how to handle in this case. – ZarakshR Nov 26 '22 at 17:05

0 Answers0