-
August 10th, 2020, 05:36 PM
#1
[RESOLVED] MBR bootloader segments initialization problem!
I'm compiling using I'm running the bootloader using 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.
-
August 11th, 2020, 10:58 AM
#2
Re: MBR bootloader segments initialization problem!
I figured it out.
The problem is that when I'm referencing a memory address like this:
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:
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)
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|