Very simple OS in Assembly
Can I make this code shorter?


If you use the ORG 7C00h directive, then loading the segment registers will be shorter code.
You can choose to setup the stack below the bootloader and shave off that addition. Even if you leave the stack where you placed it before (above the bootloader), with SS=0 the change would become mov sp, 9E00h.
You avoid having to load the string address (and the need to come up with suitable label names) if you store the actual string directly beneath the call instruction and have the print_string routine jump back to behind the terminating zero.
This technique becomes more interesting if more than 1 string is to be printed.

    BITS  16
    ORG   7C00h

start:
    cld                          &lt;--- Not shorter but better!
    xor   ax, ax
    mov   ds, ax
    mov   ss, ax
    mov   sp, 7C00h

    call  print_string
    db    'OS', 0
    jmp   $

print_string:
    pop   si
    mov   bx, 7                  &lt;--- Not shorter but better!
    mov   ah, 0Eh
.repeat:
    cs lodsb ; Need CS override since SI is an offset in code segment!
    cmp   al, 0
    je    .done
    int   10h
    jmp   .repeat
.done:
    jmp   si


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

The CS segment override on the LODSB instruction is required unless you know that DS == CS. Many bootloaders will have a far jump at the top to ensure that this is the case. e.g. jmp 0000h:7C05h as the very first instruction. This will set CS=0.
Not shorter but better

Adding a CLD instruction makes sure that the LODSB instruction will function correctly.
Passing all the required parameters to the BIOS.Teletype function is best. BH is DisplayPage and BL is GraphicsColor. If you know that the screen is in a text video mode then you can drop the setting for BL and just write mov bh, 0 to select the video page.