0

I'm just approaching to machine-level x86 coding, so please excuse the triviality of my question. The following code is intended to be a simple bootloader. It dumps some sector of floppy disk into memory and then it jumps to loaded code. In the loaded code I was trying to read from a memory variable, without success, as described in comments.

    [ORG 0]

            jmp 07C0h:start     ; Goto segment 07C0

    start:
            ; Update the segment registers
            mov ax, cs
            mov ds, ax
            mov es, ax


    reset:                      ; Reset the floppy drive
            mov ax, 0          
            mov dl, 0          
            int 13h            
            jc reset         


    read:
            mov ax, 1000h       ; ES:BX = 1000:0000
            mov es, ax          
            mov bx, 0           

            mov ah, 2           ; Load disk data to ES:BX
            mov al, 5           ; Load 5 sectors
            mov ch, 0           ; Cylinder=0
            mov cl, 2           ; Sector=2
            mov dh, 0           ; Head=0
            mov dl, 0           ; Drive=0
            int 13h             ; Read!

            jc read             ; on error


            jmp 1000h:0000      ; Jump to the program


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

       ;     ==  Loaded code from second floppy sector  ==
prog:
        mov     ah,     0x0E       ; Prints a char. This one works: the '-'
        mov     al,     '-'        ;   is printed.
        mov     bx,     0
        int     10h

        mov     bx,     0 
a:                                 
        mov     al,     [L1+bx]    ; Should read from L1 and print out chars.
        inc     bx                 ;   But it prints only white spaces. Why?
        int     10h
        cmp     bx,     10
        jz      h
        jmp a

        cli
        hlt

        L1 db "0123456789"        ; my string

I can't understand why it doesn't work. I very appreciate any help.

mghis
  • 517
  • 1
  • 5
  • 14

2 Answers2

2

If the above is a single assembler file, change jmp 1000h:0000 to jmp 0FE0h:200h, this will appropriately compensate for the ip register offset accumulated from all the way from [ORG 0] and still transfer control to physical address 0x10000.

In addition to that, set ds to cs (or to 0FE0h) in the second part of the code.

Alexey Frunze
  • 61,140
  • 12
  • 83
  • 180
  • DS was set to CS, which would be 0 in the beginning, which would give the correct address if the "Loaded from floppy" was loaded at the same address as the code before it – Sten Petrov Mar 29 '13 at 17:32
  • @StenPetrov Nope. I mean `ds` when executing the second part of the code. When in there, `cs`!=`ds`. – Alexey Frunze Mar 29 '13 at 17:34
  • I tried to set the data segment register. I added after `prog:` the following: `mov ax, 1000h`, `mov ds, ax`, but nothing changed. – mghis Mar 29 '13 at 17:40
  • @mghis it doesn't matter if DS points to the CS segment. You have one ORG and it's 0, the address L1 is calculated compile-time and most likely different from the actual address where you're loading it from disk – Sten Petrov Mar 29 '13 at 17:52
  • @StenPetrov Oh, I think I got it. The above is a single source file and not two. I was assuming it was two. – Alexey Frunze Mar 29 '13 at 17:56
2

The "Loaded from floppy" part was compiled for a different base offset than the one it was loaded into, you need to recalculate its address

You could also use ORG 7C00h and spare yourself the jump, the difference being your segments will be 0 instead of 07C0h

You can either calculate the new offset as [L1-prog] or you can reorder your code:

            jmp 1000h:000Ah      ; Jump to the program
....
L1          db "0123456789"        ; my string
prog:
        mov     ah,     0x0E   

...
        mov     al,     cs:[bx]

I don't have an assembler to test but you get the idea - remove the need for a floating address, put it in the beginning

I roughly estimate your actual offset in segment 1000H to be around 32-ish, that's where your translated L1 will roughly be. Instead your L1 is calculated compile time to be about-ish 550, so you're actually trying to load something from the second sector you read. Do you have some blank characters or zeroes in the beginning of the second loaded sector?

Sten Petrov
  • 10,943
  • 1
  • 41
  • 61
  • @AlexeyFrunze oh I see now – Sten Petrov Mar 29 '13 at 17:34
  • In fact, the first sector was padded with zeroes till second was reached. Then it was printing out those memory. Well, I tried to change `[L1+bx]` to `[L1-prog+bx]`, and it worked, but only after setting ds register as said in the other answer. Now I am in trouble about the answer to accept. :-) So, both the segment selector and the offset were wrong. Thanks for your help! – mghis Mar 29 '13 at 18:08