Code: Select all
usleep:
push ebp
mov ebp,esp
mov eax,ebp
mov ah,0x86
mov edx,eax
int 0x15
mov esp,ebp
pop ebp
ret
Code: Select all
extern void usleep(int);
Code: Select all
usleep:
push ebp
mov ebp,esp
mov eax,ebp
mov ah,0x86
mov edx,eax
int 0x15
mov esp,ebp
pop ebp
ret
Code: Select all
extern void usleep(int);
You're in protected mode, and the BIOS is designed for real mode, so none of the BIOS functions ("ints") will work.JackMacWindows wrote:I'm playing around with writing a kernel, and I would like to be able to play sound from the speaker. I need the tones to be specific lengths, so I need some sort of sleep function. I've tried using INT 15h, 86h to sleep but the system crashes at the INT instruction and reboots. This happens both in QEMU and on real hardware. I'm not using interrupts (yet), so I'm guessing I can't use INT. Here is my assembly:Code: Select all
usleep: push ebp mov ebp,esp mov eax,ebp mov ah,0x86 mov edx,eax int 0x15 mov esp,ebp pop ebp ret
I'm not sure about JackMacWindows; but I use PC speaker to try to alert the user that the OS can't boot (especially for headless systems where there's no video), with different noises at different stages (e.g. continuous tone if 1st stage boot loader can't continue, 1 second beeps if 2nd stage can't continue, etc). Of course in this case if it doesn't work it can't make anything worse.Schol-R-LEA wrote:But all of that may be irrelevant, for one simple reason: as far as I know, most motherboards don't even have a PC Speaker of that type any more, and modern Sound systems (most current ones being based on the Intel High Definition Audio spec) work in a completely different manner from the old PC speaker subsystem of the original IBM PC. While my understanding is that most implementations of AC97 and later sound standards will still emulate the PC speaker, AFAIK it isn't required by those standards, so there's no guarantee that your hardware does or not. If anyone can correct or clarify this point, please do so.
Maybe we need to start over, as this is getting into 'XY Problem' territory. Can you tell us what you want to use the speaker for?
As far as I know, I am running in real mode. I don't switch to protected mode anywhere, but I'm able to address more than 1 MB of RAM using the manual memory probing code from Detecting Memory (x86). (I'm using manual probing because I can't use BIOS calls, and even though I'm aware it's slow, I just wanted to do something other than printing a string.)Schol-R-LEA wrote:Part of the reason we are having trouble answering this is because you don't mention whether you are in real mode or not. This is a crucial question with the given code, since - as has already been stated - all of the standard BIOS calls are written for 16-bit real mode, and won't run in any form of protected or long mode without heroic efforts (e.g., setting up Virtual 8086 support, which would only work if you already have p-mode interrupt handling set up). Furthermore, interrupt handling in protected mode is radically different from interrupt handling in real mode, meaning that the interrupt vectors to the BIOS calls found in the real mode Interrupt Vector Table won't even exist in your p-mode Interrupt Descriptor Table unless you put them there (and there's no sane reason to do so in most cases).
I originally named it sleep(), but I changed it because 1) I thought maybe something else was named 'sleep' (which is false), and 2) I thought it would be giving me μs-precision, but I see that that is not the case. I don't need the timer to be that precise, as I only need around 100 ms.Schol-R-LEA wrote:As an aside, according to the RBIL entry discussing that interrupt vector, the interrupt only gives a timing resolution of 997 microseconds, or just a little better than a tenth of a second. This probably is fast enough for your intended use here, but not even remotely fast enough for a general sleep() routine, and certainly not fast enough for the function usually indicated by the name usleep() (where the 'u' is an ASCII-ism for the Greek letter mu (μ), short for micro - in other words, a sleep with a microsecond resolution). I mean, call it what you want, you do you, but be aware that you'll have trouble getting help from others if you use common function names in unexpected ways.
I am aware of many motherboards not having a PC speaker; in fact, my main machine doesn't have one (though I have considered adding one at some point). The reason I want to use it is for the '\a' escape code; one use being to beep when trying to backspace with nothing typed in.Schol-R-LEA wrote:But all of that may be irrelevant, for one simple reason: as far as I know, most motherboards don't even have a PC Speaker of that type any more, and modern Sound systems (most current ones being based on the Intel High Definition Audio spec) work in a completely different manner from the old PC speaker subsystem of the original IBM PC.
Maybe we need to start over, as this is getting into 'XY Problem' territory. Can you tell us what you want to use the speaker for?
Code: Select all
;nasm directive - 32 bit
bits 32
section .text
;multiboot spec
align 4
dd 0x1BADB002 ;magic
dd 0x00 ;flags
dd - (0x1BADB002 + 0x00) ;checksum. m+f+c should be zero
I wasn't planning on really releasing the code, but since you say it's a good idea I've put it up at https://github.com/MCJack123/thin-krnl. The intention is to have something similar to a BASIC interpreter. (I might use BASIC, but I'm not sure right now how the syntax will work as I want to get the basic drivers out of the way first.)Schol-R-LEA wrote:OK, before I continue, I want to ask one question: how are you handling Code Management, and specifically, have you set up version control for your code (using a VCS tool such as Subversion, Git, BitBucket, or Mercurial), and if you have, do you have an offsite repo on a free repo host such as GitHub, SourceForge, CloudForge, or Git?
I am indeed compiling the C with GCC. But when I test it, I use qemu with the -kernel option, which probably sets it into protected mode. When running on real hardware, though, I use GRUB.Schol-R-LEA wrote:The bits 32 directive, and the comment referring to a MultiBoot header, tells me that the system is in fact going to be in 32-bit protected mode at this point. I am assuming you are using a Multiboot compatible boot loader, probably GRUB, and that it is loading the ELF file with the compiled and linked code, correct? And if I may speculate further, that you compiled the C code with GCC?
If this is all correct, then yes, you are definitely running in 32-bit p-mode. GRUB always siwtches to 32-bit protected mode before loading a kernel image unless specifically directed otherwise, and the default loadable format for GRUB is ELF32. Furthermore, on the x86 platform, GCC really only targets 32-bit and 64-bit code. While neither of those is absolute (GRUB can always chain-load formats it doesn't know, and I've been told that it is possible to coax GCC to target real mode), you would know it if that's what you were doing.
Oh well, I guess I'll go get started with writing ~memory and~ interrupt managers. What resources are available where I can see how to implement them? I'm not sure exactly what I should be looking for.Schol-R-LEA wrote:So, this pretty rules out the possibility of calling the BIOS. It also means that your next order of business more or less must be to move the memory and interrupt management from the minimal GDT and IDT which GRUB sets up, to ones organized whichever your OS will need them. You won't be able to progress much further until you have that in place.
There are alternatives, but they all would amount to starting over from scratch, including either writing your own bootloader, or finding one for a 16-bit real mode kernel which you could adapt. You would also need to find a 16-bit real mode C compiler, if you do that. I personally wouldn't recommend it.
Sorry to be the bearer of bad news, but this is pretty much where things stand now.
I got the base code from https://arjunsreedharan.org/post/827107 ... e-a-kernel and built up other code from the wiki to make what I have now.Schol-R-LEA wrote:One final question to bookend the first: are you following a tutorial of any sort, and if so, which one?