Simple NASM “boot program” not accessing memory co

2019-02-14 05:02发布

问题:

**Note that when I say boot program, I don't mean a program that boots an OS. I mean, a simple program that runs when you start up the computer and does something.

Alright, so I'm not extremely well-versed in Assembly/NASM, but I think I have a good enough grasp on it to write simple boot programs.

Well, I thought I had a good enough grasp. Apparently not.

I tried a simple boot program I found online. It ran fine (prints the letter 'A'). I then modified it to print a letter stored in memory. It failed; instead of printing an 'A', it prints a smiley face. (I swear, the computer's laughing at me right now.)

This is the code from the source file:

[BITS 16]    ; We start up in 16-bit real mode
[ORG 0x7C00] ; We're booted into memory at this address. (Or so I'm told)

mov ah, 0x0E       ; Teletype command
mov bh, 0x00       ; Page number
mov bl, 0x07       ; Attributes (7 == white foreground, black background)
mov al, [testChar] ; Character to print; load it from the memory referenced by testChar.

int 0x10  ; Tell the BIOS to execute the teletype command.

jmp $  ; Infinite loop prevents us from going off and executing the other junk in memory

testChar db 65  ; This is the character we want to print. 'A'.

; The following code pads the rest of the outputted binary file
;   and concludes it with the bootloader signature so I don't have
;   to do so manually.
times 510-($-$$) db 0
dw 0xAA55

If I replace 'move al, [testChar]' with 'move al, 65', the letter 'A' is printed correctly. I've tried moving the memory declaration around, I've tried every combination of brackets or no brackets around BITS and ORG, and I've tried incrementing and decrementing testChar (i.e. [testChar+1]). Every time, it prints either a smiley, an inverse smiley (when I increment testChar), or nothing at all (when I put the memory declaration before the code, probably because no code is being executed =P). I can't get the damn thing to work.

Now, for specifications (because they're probably relevant):

  • I'm running a Dell Latitude CPi with an Intel Pentium II processor, because that's all I've got to test with (I'm not testing assembler with my normal computer. Hell no.). I'm pretty sure said processor is x86, as I've run Windows XP, Ubuntu and Arch Linux on it.

  • I'm currently writing and compiling the programs on Arch Linux using NASM.

  • The boot program is run from a floppy disk

  • I use 'nasm -f bin FILENAME' to compile the code.

  • I then use the 'mformat' command from the 'mtools' package for AL to transfer the compiled boot program to a floppy disk via 'mformat -f 1440 -B BOOTPROGRAM A:'.

So, what did I screw up this time? Or is it a problem with my processor/BIOS?

回答1:

DS is probably filled with some garbage value, so just do:

push cs
pop ds

or

mov ax, cs
mov ds, ax
mov es, ax

Better yet, don't trust CS and do:

xor ax, ax
mov ds, ax

See this discussion: some BIOSes may use 07c0:0000 instead of the traditional 0000:7c00, specially when booting from CD-ROM using ElTorito.



回答2:

This is producing the following code (simply run objdump on your compiled code).

00000000  B40E              mov ah,0xe
00000002  B700              mov bh,0x0
00000004  B307              mov bl,0x7
00000006  A00D7C            mov al,[0x7c0d]
00000009  CD10              int 0x10
0000000B  EBFE              jmp short 0xb
0000000D  41                inc cx ; this is actually your testChar
                                   ; ignore the opcode translation

Now if you are located at 0x7C00, then [0x7c0d] will be the final byte in that (i.e. 0x41 or 65, or ASCII "A"). But if like one of the other contributors (ninjalj) has mentioned you have some odd bios bug that means you are not located at 0x7C00 then [0x7c0d] is anyone's guess.



回答3:

It ran fine when I ran it the first time! It prints 'A'. Use command nasm [filename.asm] -o [filename.com] -l [filename.lst]

I used nasm OSbad.asm -o OSbad.com . Used MagicISO to make a bootable image file OSbad.iso and used Windows disk burner to burn it to a DVD/RW. Loaded Oracle VM and made a new Virtual Machine with 256 Mb RAM, CD/DVD, Hard disk of 2GB. Booted with DVD and it prints 'A' on the screen.

So I guess you program is working. It must be other things that you are doing that makes it not work.