diff --git a/03-bootsector-memory/README.md b/03-bootsector-memory/README.md index fedc14e..146005c 100644 --- a/03-bootsector-memory/README.md +++ b/03-bootsector-memory/README.md @@ -1,13 +1,13 @@ *Concepts you may want to Google beforehand: memory offsets, pointers* -The only goal of this lesson is to learn where the boot sector is stored - Please open page 14 [of this document]( http://www.cs.bham.ac.uk/~exr/lectures/opsys/10_11/lectures/os-dev.pdf)1 and look at the figure with the memory layout. -I could just go ahead and tell you that it starts at `0x7C00`, but it's -better with an example. +The only goal of this lesson is to learn where the boot sector is stored + +I could just go ahead and tell you that the BIOS places it at `0x7C00`, but an +example with wrong solutions will make things clearer. We want to print an X on screen. We will try 4 different strategies and see which ones work and why. @@ -23,7 +23,7 @@ Then we will try to access `the_secret` in many different ways: 1. `mov al, the_secret` 2. `mov al, [the_secret]` 3. `mov al, the_secret + 0x7C00` -4. `mov al, 2d + 0x7C00`, where `2d` is the actual position of the X in the binary +4. `mov al, 2d + 0x7C00`, where `2d` is the actual position of the 'X' byte in the binary Take a look at the code and read the comments. @@ -33,6 +33,21 @@ the bytes following 1 and 2 are just random garbage. If you add or remove instructions, remember to compute the new offset of the X by counting the bytes, and replace `0x2d` with the new one. +Please don't continue onto the next file unless you have 100% understood +the boot sector offset and memory addressing. + +Now, since offsetting `0x7c00` everywhere is very inconvenient, assemblers let +us define a "global offset" for every memory location, with the `org` command: + +```nasm +[org 0x7c00] +``` + +Go ahead and open `boot_sect_memory_org.asm` and you will see the canonical +way to print data with the boot sector, which is now attempt 2. Compile the code +and run it, and you will see how the `org` command affects each previous solution. + +Read the comments for a full explanation of the changes with and without `org` ----- diff --git a/03-bootsector-memory/boot_sect_memory.asm b/03-bootsector-memory/boot_sect_memory.asm index b67f4de..d41e78e 100644 --- a/03-bootsector-memory/boot_sect_memory.asm +++ b/03-bootsector-memory/boot_sect_memory.asm @@ -10,7 +10,7 @@ int 0x10 ; attempt 2 ; It tries to print the memory address of 'the_secret' which is the correct approach. -; However, BIOS starts loading at address 0x7c00 +; However, BIOS places our bootsector binary at address 0x7c00 ; so we need to add that padding beforehand. We'll do that in attempt 3 mov al, "2" int 0x10 @@ -19,7 +19,9 @@ int 0x10 ; attempt 3 ; Add the BIOS starting offset 0x7c00 to the memory address of the X -; and then dereference the contents of that pointer +; and then dereference the contents of that pointer. +; We need the help of a different register 'bx' because 'mov al, [ax]' is illegal. +; A register can't be used as source and destination for the same command. mov al, "3" int 0x10 mov bx, the_secret @@ -29,19 +31,21 @@ int 0x10 ; attempt 4 ; We try a shortcut since we know that the X is stored at byte 0x2d in our binary +; That's smart but ineffective, we don't want to be recounting label offsets +; every time we change the code mov al, "4" int 0x10 mov al, [0x7c2d] int 0x10 -jmp $ - +jmp $ ; infinite loop the_secret: - ; ASCII code 0x58 is stored just before the zero-padding - ; on this code that is at byte 0x2d (check it out using xdd) + ; ASCII code 0x58 ('X') is stored just before the zero-padding. + ; On this code that is at byte 0x2d (check it out using 'xdd file.bin') db "X" +; zero padding and magic bios number times 510-($-$$) db 0 dw 0xaa55 diff --git a/03-bootsector-memory/boot_sect_memory_org.asm b/03-bootsector-memory/boot_sect_memory_org.asm new file mode 100644 index 0000000..9a29adc --- /dev/null +++ b/03-bootsector-memory/boot_sect_memory_org.asm @@ -0,0 +1,47 @@ +[org 0x7c00] +mov ah, 0x0e + +; attempt 1 +; Will fail again regardless of 'org' because we are still addressing the pointer +; and not the data it points to +mov al, "1" +int 0x10 +mov al, the_secret +int 0x10 + +; attempt 2 +; Having solved the memory offset problem with 'org', this is now the correct answer +mov al, "2" +int 0x10 +mov al, [the_secret] +int 0x10 + +; attempt 3 +; As you expected, we are adding 0x7c00 twice, so this is not going to work +mov al, "3" +int 0x10 +mov bx, the_secret +add bx, 0x7c00 +mov al, [bx] +int 0x10 + +; attempt 4 +; This still works because there are no memory references to pointers, so +; the 'org' mode never applies. Directly addressing memory by counting bytes +; is always going to work, but it's inconvenient +mov al, "4" +int 0x10 +mov al, [0x7c2d] +int 0x10 + + +jmp $ ; infinite loop + +the_secret: + ; ASCII code 0x58 ('X') is stored just before the zero-padding. + ; On this code that is at byte 0x2d (check it out using 'xdd file.bin') + db "X" + +; zero padding and magic bios number +times 510-($-$$) db 0 +dw 0xaa55