"qemu-system-x86_64 -cdrom OS.iso" says "No bootable device" - nasm

When I start the OS with "qemu-system-x86_64 boot.bin" it is working perfectly fine but when I try to start it with "qemu-system-x86_64 -cdrom OS.iso" it say "No bootable device". The same when I am trying to start it with my computer from a flash drive.
boot.asm:
bits 16
org 0x7c00
start:
call x16_clearscreen
mov si, msg
call x16_printstring
call x16_getkey
call x16_reboot
hlt
jmp $
msg db "Press any key to restart...", 0
%include"video.asm"
%include"keyboard.asm"
%include"power.asm"
times 510-($-$$) db 0
dw 0xaa55
video.asm:
bits 16
x16_setvideomode:
int 0x10
ret
x16_setbackcolor:
mov ah, 0x0b
mov bh, 0x00
int 0x10
ret
x16_printchar:
mov ah, 0x0e
int 0x10
ret
x16_printstring:
.loop:
lodsb
cmp al, 0
je .end
call x16_printchar
jmp .loop
.end:
ret
x16_clearscreen:
mov ah, 0x00
mov al, 0x02
int 0x10
ret
keyboard.asm:
bits 16
x16_getkey:
mov ah, 0x00
int 0x16
ret
power.asm:
bits 16
x16_reboot:
int 0x19

Related

Why is my floppy disk reading code failing?

I am writing a bootloader in x86-16 assembly on a floppy disk, meaning that I will have to read from the disk in order to load more of my code, however, every time I attempt to read the disk and check the disk status code, I always get 0x04 - sector not found. I have attempted to read with CX set to 0x0000, 0x0001, and 0x0101, but I don't really know what to do, or what I am doing wrong.
INT 13,1 - Disk Status Codes
INT 13,2 - Read Disk Sectors
BITS 16
%include "C:\x86asm\nasm\nasm.asm"
;%macro pad 1-2 0
; times %1 - ($ - $$) db %2
;%endmacro
;%idefine PUSHW PUSH STRICT WORD
;%idefine PUSHD PUSH STRICT DWORD
[org 0x7C00]
; https://stanislavs.org/helppc/ ;; BIOS
; https://c9x.me/x86/ ;; Instruction Set
; https://wiki.osdev.org/ ;; OS Development
; absolute address = (segment << 4) + address
; to simulate NES/SNES style memory mapping (banks), only use bits[9..15] ($x000)
JMP 0x0000:_start ; ensure CS = $0000
_start:
CLI ; clear interrupt flag (disable
; interrupts, opposite of 6502)
CLD ; clear direction flag
PUSH CS
POP DS ; prepare for puts / puthexbyte
PUSH CS
POP SS ; set up stack segment
MOV SP, 0x7C00
;; set graphics ;;
MOV AX, 0x0012 ; set screen mode
INT 0x10
MOV AH, 0x0B
MOV BX, 0x0201
INT 0x10
MOV DX, 0x0D22 ; display "LOADING..."
MOV BX, 0x0007
MOV SI, loadstr
CALL putsl
MOV AH, 0x86 ; wait a moment...
MOV CX, 0x000F
INT 0x15
;; load floppy disk ;;
MOV BP, 0x0800 ; if fail, read x times
.loadfailure:
SUB BP, 0x0100 ; decrement # of tries left
MOV AH, 0x02 ; print # of tries left
XOR DX, DX
INT 0x10
MOV DX, BP
CALL puthexbyte
MOV AH, 0x00 ; reset disk system
MOV DL, 0x00
INT 0x13
MOV AX, 0x0201 ; read
MOV CX, 0x0101
XOR DX, DX
PUSHW 0x1800 ; write to $18000 ~ $1FFFF
POP ES
XOR BX, BX
INT 0x13
PUSHF
MOV DH, AH ; show error code
CALL puthexbyte
POPF
JNC .loadsuccess
TEST BP, BP
JNE .loadfailure
MOV DX, 0x0D0F ; read fail;
MOV SI, badload ; print msg
CALL putsl
MOV AH, 0x86 ; wait
MOV CX, 0x001E
INT 0x15
INT 0x18 ; boot windows
.loadsuccess:
MOV DX, 0x0D0F ; read success;
MOV SI, nosystem ; DOS not finished,
CALL putsl ; tell user
MOV AH, 0x86 ; wait
MOV CX, 0x001E
INT 0x15
JMP 0x1000:0x8000 ; boot test
putsl:
; [DX] : (Y,X)
; (AH)
MOV AH, 0x02
INT 0x10 ; set cursor position
puts:
; [DS:SI] : String
; (AX, BX, SI)
MOV AH, 0x0E ; teletype mode
MOV BX, 0x000F ; set white text attribute
.putsloop:
LODSB ; load character from [DS:SI++]
TEST AL, AL ; check if NULL (x86 MOV does not
JE .endputs ; change zero-flag unlike 6502 LDA/LDX/LDY)
INT 0x10 ; print character
JMP .putsloop ; loop until NULL
.endputs:
RET
puthexbyte:
; [DH] : Value
; (AX, DH, BX)
MOV AH, 0x0E
MOV BX, asciihex
MOV AL, DH
SHR AL, 4
XLAT
MOV BX, 0x000F
INT 0x10 ; print character
MOV BX, asciihex
MOV AL, DH
AND AL, 0x0F
XLAT
MOV BX, 0x000F
INT 0x10
RET
asciihex:
db "0123456789ABCDEF", 0
loadstr:
db "LOADING...", 0
badload:
db "Unable to load disk. Attempting to load Windows...", 0
nosystem:
db "Operating System is incomplete. Loading Windows...", 0
tststr:
db "Disk read success. INT 0x20 set success. Jump success.", 0
pad 0x01FE ; pad to end of boot sector
dw 0xAA55 ; floppy disk boot sector signature
; code
PUSHW 0x0000 ; test setting INT
POP DS ; (tested; works when in
MOV [4 * 0x20], DWORD putsl ; boot sector)
MOV DX, 0x0D0D ; test INT by
MOV SI, tststr ; printing
INT 0x20 ; string
MOV AH, 0x86 ; wait
MOV CX, 0x001E
INT 0x15
INT 0x18 ; boot windows
pad 0x0400 ; pad to end of sector 1
;incbin "os.bin"
pad 0x00167FFF ; pad to disk end
db 0x00
Edit:
An explanation on how to convert disk sectors and tracks (ie. CX in INT 13,2) into a "linear address" would be greatly appreciated, as the method I am using to get my code onto a floppy disk has me opening the program HxD and manually copying and pasting my binary onto the the disk.
Also, the disk I am using is 'unformatted' (as far as Windows is concerned).
Also, also, if this changes anything, my PC's BIOS is (msinfo32)"American Megatrends Inc. 5.35, 2008-12-16."

Definition of uninitialized memory produces a "attempt to initialize memory" error

First of all, let's begin by saying I am an absolute beginner at assembly language, so there could be a very simple solution that I might not even be seeing/understanding.
My problem is the following: I am trying to create a basic addition program in assembly through nasm. So far, this is the code I've written (changed the comment semicolons to hashes):
#basic assembly file that takes 2 digits, adds them together and prints them on the screen via a function
global _start
section .data
initString db "Please enter the first number:", 0x0a
initStringL equ $-initString
secondString db "Please enter the second number:", 0x0a
secondStringL equ $-secondString
resultString db "The result of the addition is:", 0x0a
resultStringL equ $-resultString
section .bss
num1: resb 0x400
num2: resb 0x400
num3: resb 0x400
BasicMath:
#epilog
push ebp
mov ebp, esp
#print initString
mov eax, 0x4
mov ebx, 0x1
mov ecx, initString
mov edx, initStringL
int 0x80
#read input
mov eax, 0x3
mov ebx, 0x2
mov ecx, num1
mov edx, 0x400
int 0x80
#print secondString
mov eax, 0x04
mov ebx, 0x1
mov ecx, secondString
mov edx, secondStringL
int 0x80
#read second input
mov eax, 0x3
mov ebx, 0x2
mov ecx, num2
mov edx, 0x400
int 0x80
#addition
mov al, num1
add al, num2
mov num3, al
int 0x80
#print resultString
mov eax, 0x04
mov ebx, 0x01
mov ecx, resultString
mov edx, resultStringL
int 0x80
#print actual result
mov eax, 0x04
mov ebx, 0x01
mov ecx, num3
mov edx, 0x400
int 0x80
#prelog
mov esp, ebp
pop ebp
ret
_start:
pushad
pushfd
call BasicMath
popfd
popad
;exit program
mov eax, 0x1
mov ebx, 0x0
int 0x80
Now, when I put this through nasm, I get several dozens of "attempt to initialize memory" errors, and in the middle of them, one "invalid combination of opcode and operands", like so:
Now, I'm not sure at all about the actual addition part of the program, in particular the "mov num3, al" that might be complete gibberish, but I have no idea where the memory problem fits in all of this and what its cause is.

int 10h 13h bios string output not working

i am using nasm and this is my code :
org 0x7c00
bits 16
section .data
zeichen dw 'hello2'
section .text
mov ax,0x7c00
mov es,ax
mov bh,0
mov bp,zeichen
mov ah,13h
mov bl,00h
mov al,1
mov cx,6
mov dh,010h
mov dl,01h
int 10h
jmp $
times 510 - ($-$$) hlt
dw 0xaa55
it does put the cursor on the right position but it prints nothing.
i load this file with qemu-system-i386.
The int10 ah=13h is a string output and in register es:bp has to be the address of the string
For future reference, since i have been trying to get this working for a long time now, here is a working version!
org 0x7c00
bits 16
xor ax, ax
mov es, ax
xor bh, bh
mov bp, msg
mov ah, 0x13
mov bl, [foreground]
mov al, 1
mov cx, [msg_length]
mov dh, [msg_y]
mov dl, [msg_x]
int 0x10
hlt
foreground dw 0xa
msg db 'Beep Boop Meow'
msg_length dw $-msg
msg_x dw 5
msg_y dw 2
times 510 - ($-$$) db 0
dw 0xaa55
here is a version closest to original.
org 0x7c00
bits 16
; video page number.
mov bh, 0
; ES:BP is the pointer to string.
mov ax, 0x0
mov es, ax
mov bp, msg
; attribute(7 is light gray).
mov bl, 0x7
; write mode: character only, cursor moved.
mov al, 1
; string length, hardcoded.
mov cx, 6
; y coordinate
mov dh, 16
; x coordinate
mov dl, 1
; int 10, 13
mov ah, 0x13
int 0x10
; keep jumping until shutdown.
jmp $
msg dw 'hello2'
times 510 - ($-$$) db 0
dw 0xaa55

nasm bootloader, why does where i define ths string matter?

Im experimenting with writing a bootloader in nasm, at the moment it just prints a string.
[BITS 16]
[org 0x7c00]
myString:
db 'Hello World', 0x00
mov bp, 0x8000
mov sp, bp
mov bx, myString
call printString
jmp $
printString:
pusha
mov ah , 0x0e
printStringA:
mov al , [bx]
cmp al, 0x00
je printStringB
int 0x10
add bx, 0x01
jmp printStringA
printStringB:
popa
ret
times 510 -( $ - $$ ) db 0
dw 0xaa55
that works fine, but if i move the string definition to here:
[BITS 16]
[org 0x7c00]
mov bp, 0x8000
mov sp, bp
myString:
db 'Hello World', 0x00
mov bx, myString
call printString
jmp $
printString:
pusha
mov ah , 0x0e
printStringA:
mov al , [bx]
cmp al, 0x00
je printStringB
int 0x10
add bx, 0x01
jmp printStringA
printStringB:
popa
ret
times 510 -( $ - $$ ) db 0
dw 0xaa55
it prints out garbage, im running this in bochs under windows if that helps.
You are assembling to raw machine code. There are no data and text sections. Everything is interpreted as code, including what you insert using db. Hence both code snippets are wrong.
If you finish with an endless loop (as in your example) or a halt instruction, the data can safely be put after the code as it will never be reached. Otherwise you must arrange for the data to be skipped over.
You also need to set the segment registers correctly at the start.
Here is a corrected version, with early declaration of data:
[BITS 16]
[ORG 0]
;;; Set CS and DS
jmp 0x07c0:start
start:
mov ax, cs
mov ds, ax
;;; set SP
mov bp, 0x8000
mov sp, bp
;;; skip over data
jmp L1
myString:
db 'Hello World', 0x00
L1:
mov bx, myString
...
Note that in your first example, the data was interpreted as code.
db 'Hello World', 0x00
is assembled as
48 65 6c 6c 6f 20 57 6f 72 6c 64 00
and corresponds to:
dec ax
gs insb
insb
outsw
and [bx+0x6f],dl
jc short 0x76
fs
db 0x00
In effect this gets executed before your code. It is pure luck that this fragment doesn't prevent your code from working.

asm little-endian register/immediate/memory order

I'm quite new to assembler - I have only done some programming on 8-bit micro-controllers before.
Now I've problems to understand how litte-endian is stored. I already have read the article on wikipedia (http://en.wikipedia.org/wiki/Endianness) and some threads here but I'm still confused.
CPU: x64
Compiler: yasm
OS: Linux
Now the questions:
MOV r32,imm32:
section .bss
var: resb 4 ;reserve 4 bytes
varlen: equ $-var
section .text
global _start
_start:
MOV R10D, 0x6162630A
MOV [var], R10D
CMP R10B, 0x0A
JNE nequal
MOV eax, 0x04 ;printf
MOV ebx, 0x01 ;stdio
MOV ecx, var
MOV edx, varlen
int 0x80 ;tell the kernel to print the msg
end:
MOV eax, 0x01 ;return 0
MOV ebx, 0x00
int 0x80
output:
LF (linefeed - according to 0x0a)
cba
The code above shows that the constant is written to the register without byte-swapping but why is printf reading from the highest memory address to the lowest??
Why is the constant in the register not swapped according to little-endian? Is this compiler-dependent?
Is this correct:
|61h|62h|63h|0Ah| .... the register
31........................0
memory (adr increments in bytes)
adr, data
0x00 61h
0x01 62h
0x02 63h
0x03 0Ah
MOV r32, m32
section .data
msg: db 0x70,0x71,0x72,0x0a
msglen:equ $-msg
section .text
global _start
_start:
MOV EAX, [msg]
CMP AL, 0x70
JNE end
MOV eax, 0x04
MOV ebx, 0x01
MOV ecx, msg
MOV edx, msglen
int 0x80
end:
MOV eax, 0x01
MOV ebx, 0x00
int 0x80
output:
pqrLF (LF represents a linefeed)
Is this correct:
|0Ah|72h|71h|70h| .... the register
31........................0
memory (adr increments in bytes)
adr, data
0x00 70h
0x01 71h
0x02 72h
0x03 0Ah
Could this be a conclusion:
Data in registers is BigEndian and in memory it's LittleEndian?
Thank you for your responses.
Michael
Talking about endianness on registers makes no sense, as registers do not have memory addresses.
From your Wikipedia source: "The terms endian and endianness refer to the convention used to interpret the bytes making up a data word when those bytes are stored in computer memory"

Resources