1

I am learning programming in real mode and found a post here on SO which is quite useful for me But I have some doubts regarding how things are working in given code

Basic NASM bootstrap

  ;This is NASM

    BITS 16                 ; 16 bits!

    start:                          ; Entry point
    mov ax, 07C0h           ; Move the starting address (after this bootloader) into 'ax'
    add ax, 288             ; Leave 288 bytes before the stack beginning for some reason
    mov ss, ax              ; Show 'stack segment' where our stack starts
    mov sp, 4096            ; Tell 'stack pointer'  that our stack is 4K in size

    mov ax, 07C0h           ; Use 'ax' as temporary variable for setting 'ds'
    mov ds, ax              ; Set data segment to where we're loaded


    mov si, text_string     ; Put string position into SI (the reg used for this!)
    call print_string       ; Call our string-printing routine

    jmp $                   ; Jump here - infinite loop!

     text_string db 'This is my cool new OS!', 0 ; Our null terminated string

                                                ; For some reason declared after use


   print_string:                   ; Routine: output string in SI to screen
    mov ah, 0Eh             ; I don't know what this does..
                            ; Continue on to 'repeat'
   .repeat:
    lodsb                   ; Get character from DS:SI into AL
    cmp al, 0               ; If end of text_string
    je .done                ; We're done here
    int 10h                 ; Otherwise, print the character (What 10h means)
    jmp .repeat             ; And repeat

   .done:
    ret

    times 510-($-$$) db 0   ; Pad remainder of boot sector with 0s
    dw 0xAA55               ; The standard PC 'magic word' boot signature

1)Are DS and CS overlapping here??

2)Does CS start from 0h location ??enter image description here,the attached images show the 512 bytes that are the bootsector generated by the assembler

3)Are both DS and CS started from 07c00H ?? first of all ,the code part is filled in before putting the Data which the text string

4)Stack is start from 07c00+288?? and mov sp,4096 would define the stack of size which is (07c00+288+4096-07c00+288).

Community
  • 1
  • 1
Amit Singh Tomar
  • 8,380
  • 27
  • 120
  • 199

2 Answers2

1

Short answer: yes. Real mode segment:offset addresses can and do overlap. Your BIOS loads the bootsector at 7C00h. This is probably cs zero, offset 7C00h (although there are rumors that a certain Compac Presario BIOS loaded at 07C0:0000). This is the same address! We multiply by 16 because that's the way an address is calculated in real mode - segment times 16 plus offset. We can multiply by 16 by shifting a number 4 bits to the left - one hex digit, if you look at it that way.

It is common for a bootsector to say org 7C00h at the top. Since this code doesn't have an org, Nasm assumes org 0. In this "common" bootsector, we'd put 0 in ds (and es?). With org 0 we want 7C0h in ds. 0000:7C00h and 07C0h:0000 are the same address. This is important to find text_string.

The comment in the code you found is somewhat deceptive... it isn't really "288 bytes". It might be easier to write this as hex - 120h. This is added to 7C0h to give 8E0h. Then sp is loaded with 4096 decimal, or 1000h. So the linear address (segment * 16 + offset) of the stack starts at 9E00h and works downward to 8E00h - plenty of room to avoid bumping into your code at 7C00h to 7E00h (512 decimal = 200h is the size of the bootsector).

Might be worth noting that your "data" is in the middle of your code, but it's in a position where it won't be executed, so it's okay.

I hope I've got the arithmetic right, and haven't confused you worse!

Frank Kotler
  • 3,079
  • 2
  • 14
  • 9
  • Thanks Frank for your answer,What I understood of your comments is if we write org 100h ,then cs=0 and offset part would be 100h and if so then yoyr code segment starts from 0 and first instruction to be executed would be at offset 100 h from cs.My next point multiplying 288 with 16 ,As you written above (segment*16 ) segment part should be multiplied with 16 not offset butis n't it 288 is part of offset here. – Amit Singh Tomar Jul 16 '13 at 09:29
0
mov ax, 07C0h           ; Move the starting address (after this bootloader) into 'ax'
add ax, 288             ; Leave 288 bytes before the stack beginning for some reason
mov ss, ax              ; Show 'stack segment' where our stack starts

This sets up your stack segment. Segment registers are bits 4 through 19 in your address. So your stack segment starts at address 07C00h + 288*16 or 08180h (you added 288 decimal to ax, which had 07C0h in it, then you moved that to the segment register).

mov sp, 4096            ; Tell 'stack pointer'  that our stack is 4K in size

This gives you a 4k stack only if you know that address range 08180h through 0917Fh is available for stack use.

mov ax, 07C0h           ; Use 'ax' as temporary variable for setting 'ds'
mov ds, ax              ; Set data segment to where we're loaded

This sets the data segment to start at address 07C00h.

I don't know from your listing where your code segment starts or what cs is set to, so it's unclear whether cs and ds overlap. cs doesn't start at 0 normally.

lurker
  • 56,987
  • 9
  • 69
  • 103
  • but the opcode(which is part of the code) starts from address 0 and why 288 is multiplied by 16 here – Amit Singh Tomar Jul 15 '13 at 14:39
  • @AmitSinghTomar I don't know what your hex dump is from. But it would go through a relocation process before it was actually loaded into memory. There are interrupt vectors and such at literal address `0` on a CPU, so it's unlikely the code starts at `0`. – lurker Jul 15 '13 at 14:41