CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 2 of 2

Thread: [RESOLVED] MBR bootloader segments initialization problem!

  1. #1
    Join Date
    Jul 2017
    Location
    Greece
    Posts
    126

    [RESOLVED] MBR bootloader segments initialization problem!

    I'm compiling using
    Code:
    nasm -f bin
    I'm running the bootloader using
    Code:
    qemu-system-x86_64
    I have 2 versions of the same code with a slight change to the second version. First version uses the [org 0x7c00] NASM directive
    where the second version does it manually by setting the ds register to 0x7c0.

    The bootloader defines 2 functions. print_static which prints a string that lives in the data segment.
    The second function is named print_dynamic which prints a string that lives in the stack.

    The expected output of both versions should be: Hello World!dynamic

    The first version works correctly, but the second does not print the dynamic string

    First Version:
    Code:
    [bits 16]
    [org 0x7c00]
    
    ;Initialize the stack.
    mov bp, 0x7e00 ;This is the address where the 512 bootloader ends.
    add bp, 50000  ;Set the bp and sp 50kb above the bootloader.
    mov sp, bp     ; Finally we have 50kb stack.
    
    ;Print a static string.
    mov bx, hello_world
    call print_static
    
    ;Push a string into the stack and print it.
    push 'd'   ;Push the first character.
    mov si, sp ;Store the beggining of the string.
    push 'y'
    push 'n'
    push 'a'
    push 'm'
    push 'i'
    push 'c'
    push 0     ;End the string.
    call print_dynamic
    add sp, 16 ;Deallocate the string.
    
    jmp $
    
    
    ;Get a null terminated character stored in the data segment and print it.
    ;[in] : bx (Pointer at the beggining of the string)
    ;[out]: void
    print_static:
    
        ;Save all general purpose registers.
        pusha
        
        ;Bios function for int 0x10 to print a char to the screen.
        mov ah, 0x0e
        
        ;Print while loop.
        print_static_while:
            mov al, [bx] ;copy the current character to al.
            cmp al, 0 ;if its zero
            je print_static_end ;stop;
            int 0x10 ;else print al to the screen.
            add bx, 1;go to the next character.
            jmp print_static_while ;start again.
    
    
        ;exit print_static
        print_static_end:
    
            ;Retrieve all general purpose registers.
            popa
            ret
    
    
    ;Get a null terminated character stored in the stack and print it.
    ;[in] : si (the beggining of the string)
    ;[out]: void
    print_dynamic:
        
        pusha
    
        print_dynamic_while:
            mov ax, [si] ;copy the current character to al.
            mov ah, 0x0e ;bios print char
            cmp al, 0 ;if its zero
            je print_dynamic_end ;stop;
            int 0x10 ;else print al to the screen.
            sub si, 2;go to the next character.
            jmp print_dynamic_while ;start again.       
    
        print_dynamic_end:
            popa
            ret
    
    
    ;Data
    hello_world: db "Hello World!", 0
    
    
    ;Padding the remaining space with 0s and the magic number.
    times 510-($-$$) db 0x0000
    dw 0xaa55
    Second Version:
    Code:
    [bits 16]
    
    ;Initialize the stack.
    mov bp, 0x7e00 ;This is the address where the 512 bootloader ends.
    add bp, 50000  ;Set the bp and sp 50kb above the bootloader.
    mov sp, bp     ; Finally we have 50kb stack.
    
    ;Initialize the data segment register.
    mov ax, 0x7c0
    mov ds, ax
    
    ;Print a static string.
    mov bx, hello_world
    call print_static
    
    ;Push a string into the stack and print it.
    push 'd'   ;Push the first character.
    mov si, sp ;Store the beggining of the string.
    push 'y'
    push 'n'
    push 'a'
    push 'm'
    push 'i'
    push 'c'
    push 0     ;End the string.
    call print_dynamic
    add sp, 16 ;Deallocate the string.
    
    jmp $
    
    
    ;Get a null terminated character stored in the data segment and print it.
    ;[in] : bx (Pointer at the beggining of the string)
    ;[out]: void
    print_static:
    
        ;Save all general purpose registers.
        pusha
        
        ;Bios function for int 0x10 to print a char to the screen.
        mov ah, 0x0e
        
        ;Print while loop.
        print_static_while:
            mov al, [bx] ;copy the current character to al.
            cmp al, 0 ;if its zero
            je print_static_end ;stop;
            int 0x10 ;else print al to the screen.
            add bx, 1;go to the next character.
            jmp print_static_while ;start again.
    
    
        ;exit print_static
        print_static_end:
    
            ;Retrieve all general purpose registers.
            popa
            ret
    
    
    ;Get a null terminated character stored in the stack and print it.
    ;[in] : si (the beggining of the string)
    ;[out]: void
    print_dynamic:
        
        pusha
    
        print_dynamic_while:
            mov ax, [si] ;copy the current character to al.
            mov ah, 0x0e ;bios print char
            cmp al, 0 ;if its zero
            je print_dynamic_end ;stop;
            int 0x10 ;else print al to the screen.
            sub si, 2;go to the next character.
            jmp print_dynamic_while ;start again.       
    
        print_dynamic_end:
            popa
            ret
    
    
    ;Data
    hello_world: db "Hello World!", 0
    
    
    ;Padding the remaining space with 0s and the magic number.
    times 510-($-$$) db 0x0000
    dw 0xaa55
    Does anyone know why the second version does not print the dynamic string?
    It seem that after removing the [org 0x7c00] even though that the ds
    is initialized correct, someting bad is happening with the stack.
    Last edited by babaliaris; August 10th, 2020 at 05:38 PM.

  2. #2
    Join Date
    Jul 2017
    Location
    Greece
    Posts
    126

    Re: MBR bootloader segments initialization problem!

    I figured it out.

    The problem is that when I'm referencing a memory address like this:

    mov ax, [si]
    by default, the data segment register is being used to do the segment - offset calculation. For example, the above code is exactly the same as this:
    mov ax, [ds:si]
    In my print_dynamic function, I want to access the stack, so I have to explicitly say:
    (and also initialize the ss register to zero in the begging of my code)
    mov ax, [ss:si]
    In the first version, this wasn't an issue because the ds was zero so any offset like ds:si was absolute.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width




On-Demand Webinars (sponsored)