When computer starts to boot, It makes a beep sound from the BIOS Speaker.
How do i can do this in Assembly or C++ ?
Clearly I want to make Beep Sound by BIOS Speaker.
Remember i mean BIOS Speakers
Does it have any interrupt for that ? I searched about that but nothing found..
I used some interrupt But the didn't do this. the following code :
int main(){
cout<<"\a";
}
Produced the sound from the Speaker, Not Bios
How can i do this ? with any interrupt ?
Try to add this code, too.
.pause1:
mov cx, 65535
.pause2:
dec cx
jne .pause2
dec bx
jne .pause1
in al, 61h ; Turn off note (get value from
; port 61h).
and al, 11111100b ; Reset bits 1 and 0.
out 61h, al ; Send new value.
So, the result is:
void beep(){
__asm{
MOV al, 182 ; Prepare the speaker for the
out 43h, al ; note.
mov ax, 2280 ; Frequency number (in decimal)
; for C.
out 42h, al ; Output low byte.
mov al, ah ; Output high byte.
out 42h, al
in al, 61h ; Turn on note (get value from
; port 61h).
or al, 00000011b ; Set bits 1 and 0.
out 61h, al ; Send new value.
mov bx, 4 ; Pause for duration of note.
.pause1:
mov cx, 65535
.pause2:
dec cx
jne .pause2
dec bx
jne .pause1
in al, 61h ; Turn off note (get value from
; port 61h).
and al, 11111100b ; Reset bits 1 and 0.
out 61h, al ; Send new value.
};
}
The only way you can implement this in any modern Windows OS is, I guess, writing Kernel Mode driver. The reason is that in or out instructions are not available in user mode, and there is no API for beeper available.
http://en.wikipedia.org/wiki/Protection_ring
https://msdn.microsoft.com/en-us/library/windows/hardware/ff554836(v=vs.85).aspx
However, if you're just willing to dig into low-level programming, consider writing own bootloader or even own BIOS (using virtual machine).
Try to include this procedure in your C++ program.
void beep(){
__asm{
MOV al, 182 ; Prepare the speaker for the
out 43h, al ; note.
mov ax, 2280 ; Frequency number (in decimal)
; for C.
out 42h, al ; Output low byte.
mov al, ah ; Output high byte.
out 42h, al
in al, 61h ; Turn on note (get value from
; port 61h).
or al, 00000011b ; Set bits 1 and 0.
out 61h, al ; Send new value.
mov bx, 4 ; Pause for duration of note.
};
}
Related
Basic question here,
I wrote the following block:
IDEAL
MODEL small
STACK 100h
DATASEG
Var1 db 4
Var2 db 2
CODESEG
start:
mov ax, #data
mov ds, ax
xor ax, ax
mov al, [Var1]
cmp al, [Var2]
jg Var1Greater
mov ax, 1
Var1Greater:
mov ax, 0
I'm new to assembly.
I wanted to create a code that compares [Var1] to [Var2].
IF(!) [Var1] is greater than [Var2], execute mov ax, 1. IF(1) anything else(equal or less) excecute, mov ax, 0.
How can this be done? the code I wrote executes both instructions if the condition is true.
Ah, Turbo Assembler "Ideal" mode; It has been a while since I last saw it. I love Ideal mode. It is so much better thought-out and it makes so much more sense than Microsoft Assembler's syntax.
Well, what is happening is that both instructions get executed.
First, mov ax, 0 gets executed, and then control falls through to the next statement, which is mov ax, 1, so what you are left with in ax is 1.
Labels in assembly language do not magically cause control to jump elsewhere. They do not cause the assembler to emit any instructions. They only exist so that you can indicate the target of another jump instruction.
So, what you need is:
...
cmp al, [Var2]
jg Var1Greater
mov ax, 0
jmp skip
Var1Greater:
mov ax, 1
skip:
also, it is good form when writing assembly language to use xor ax, ax instead of mov ax, 0.
You must jump over Var1Greater too to skip mov ax, 1 instruction. As alternative you may do it like:
mov ax, [Var1]
cmp ax, [Var2]
mov ax, 1
jg skip0
mov ax, 0
skip0:
Basic question here,
I wrote the following block:
IDEAL
MODEL small
STACK 100h
DATASEG
Var1 db 4
Var2 db 2
CODESEG
start:
mov ax, #data
mov ds, ax
xor ax, ax
mov al, [Var1]
cmp al, [Var2]
jg Var1Greater
mov ax, 1
Var1Greater:
mov ax, 0
I'm new to assembly.
I wanted to create a code that compares [Var1] to [Var2].
IF(!) [Var1] is greater than [Var2], execute mov ax, 1. IF(1) anything else(equal or less) excecute, mov ax, 0.
How can this be done? the code I wrote executes both instructions if the condition is true.
Ah, Turbo Assembler "Ideal" mode; It has been a while since I last saw it. I love Ideal mode. It is so much better thought-out and it makes so much more sense than Microsoft Assembler's syntax.
Well, what is happening is that both instructions get executed.
First, mov ax, 0 gets executed, and then control falls through to the next statement, which is mov ax, 1, so what you are left with in ax is 1.
Labels in assembly language do not magically cause control to jump elsewhere. They do not cause the assembler to emit any instructions. They only exist so that you can indicate the target of another jump instruction.
So, what you need is:
...
cmp al, [Var2]
jg Var1Greater
mov ax, 0
jmp skip
Var1Greater:
mov ax, 1
skip:
also, it is good form when writing assembly language to use xor ax, ax instead of mov ax, 0.
You must jump over Var1Greater too to skip mov ax, 1 instruction. As alternative you may do it like:
mov ax, [Var1]
cmp ax, [Var2]
mov ax, 1
jg skip0
mov ax, 0
skip0:
For understanding the working of the operating system I have made a simpel bootloader which loads a small test application for testing protected mode etc. After the bootsector has been loaded at 0x7c00 the bootloader loads the test code at segment 0x2000 and starts the first instruction. But when I try to enter the protected mode the systems reboots. Can anyone help me with this problem?
This is my code at section 0x2000
BITS 16
; Entering_ProtectedMode:
cli
mov ax, 2000h
mov ss, ax
mov sp, 0FFFFh
sti
cld
mov ax, 2000h
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
;xor ax, ax
;mov ds, ax ; update data segment
cli ; clear interrupts
lgdt [gdtr] ; load GDT from GDTR (see gdt_32.inc)
call OpenA20Gate ; open the A20 gate
call EnablePMode ; jumps to ProtectedMode
OpenA20Gate:
in al, 0x93 ; switch A20 gate via fast A20 port 92
or al, 2 ; set A20 Gate bit 1
and al, ~1 ; clear INIT_NOW bit
out 0x92, al
ret
EnablePMode:
mov eax, cr0
or eax, 1
mov cr0, eax
jmp CODE_SEG : ProtectedMode
;*********************************
;* Global Descriptor Table (GDT) *
;*********************************
NULL_DESC:
dd 0 ; null descriptor
dd 0
CODE_DESC:
dw 0xFFFF ; limit low
dw 0 ; base low
db 0 ; base middle
db 10011010b ; access
db 11001111b ; granularity
db 0 ; base high
DATA_DESC:
dw 0xFFFF ; limit low
dw 0 ; base low
db 0 ; base middle
db 10010010b ; access
db 11001111b ; granularity
db 0 ; base high
gdtr:
dw gdtr - NULL_DESC - 1 ; length of GDT
dd NULL_DESC ; base of GDT
CODE_SEG equ CODE_DESC - NULL_DESC
DATA_SEG equ DATA_DESC - NULL_DESC
;******************
;* Protected Mode *
;******************
BITS 32
ProtectedMode:
.halt:
jmp .halt
;mov ax, 10h
;mov ds, ax ; update data segment
Try this one:
OpenA20Gate:
in al, 0x92; instead of 0x93; switch A20 gate via fast A20 port 92
or al, 2 ; set A20 Gate bit 1
and al, ~1 ; clear INIT_NOW bit
out 0x92, al
ret
EnablePMode:
mov eax, cr0
or eax, 1
mov cr0, eax
......
;CODE_SEG must be equal 8 like "8:ProtectedMode". 8 points at the first descriptor of the GDT. 16 bit: 15-3 - index in the GDT (0 for the zero descriptor, 1 for the first descriptor - code, 2 for the second descriptor - data), 2 - the table indicator (0 for the GDT, 1 for the LDT), 1-0 - RPL (the request privilege level).
jmp CODE_SEG:ProtectedMode
I am writing a simple program in Assembly (NASM). When the boot sector loads it has to display all the memory (RAM) installed in the computer in Megabytes. There would be no Operating System (DOS, Windows, Linux) when the boot sector is loaded, so how would I find out total RAM size. I have 2 GB RAM in my computer. I have searched alot on the internet but could not find a solution.
Is there an interrupt of BIOS that shows memory size of 2 GB? There is an interrupt that was used in old computers to shows memory, but it does not shows all 2 GBs. I checked and there is no solution for this in Ralph Brown List. May be someone knows alot more about BIOS. If BIOS does not provide this facility then can I use C/C++ to find out Total RAM size? And call C/C++ code from assembly? What function of C/C++ would be used to find Total RAM size?
Remember that my assembly code will do a cold boot and there would be no operating system to provide any facility to my code.
EDITED:
I read the website http://wiki.osdev.org/Detecting_Memory_%28x86%29. And decided to check if int 15 works. So I got the code from this website and edited it to test if int 15 EAX = E820 works. But it fails to work and the output is 'F' in .failed1. 'F' is test case which I made to check for "unsupported function". Test Cases are 'F', 'G' and 'H'. Here is the code.
; use the INT 0x15, eax= 0xE820 BIOS function to get a memory map
; inputs: es:di -> destination buffer for 24 byte entries
; outputs: bp = entry count, trashes all registers except esi
do_e820:
xor ebx, ebx ; ebx must be 0 to start
xor bp, bp ; keep an entry count in bp
mov edx, 0x0534D4150 ; Place "SMAP" into edx
mov eax, 0xe820
mov [es:di + 20], dword 1 ; force a valid ACPI 3.X entry
mov ecx, 24 ; ask for 24 bytes
int 0x15
jc short .failed1 ; carry set on first call means "unsupported function"
mov edx, 0x0534D4150 ; Some BIOSes apparently trash this register?
cmp eax, edx ; on success, eax must have been reset to "SMAP"
jne short .failed2
test ebx, ebx ; ebx = 0 implies list is only 1 entry long (worthless)
je short .failed3
jmp short .jmpin
.e820lp:
mov eax, 0xe820 ; eax, ecx get trashed on every int 0x15 call
mov [es:di + 20], dword 1 ; force a valid ACPI 3.X entry
mov ecx, 24 ; ask for 24 bytes again
int 0x15
jc short .e820f ; carry set means "end of list already reached"
mov edx, 0x0534D4150 ; repair potentially trashed register
.jmpin:
jcxz .skipent ; skip any 0 length entries
cmp cl, 20 ; got a 24 byte ACPI 3.X response?
jbe short .notext
test byte [es:di + 20], 1 ; if so: is the "ignore this data" bit clear?
je short .skipent
.notext:
mov ecx, [es:di + 8] ; get lower dword of memory region length
or ecx, [es:di + 12] ; "or" it with upper dword to test for zero
jz .skipent ; if length qword is 0, skip entry
inc bp ; got a good entry: ++count, move to next storage spot
add di, 24
.skipent:
test ebx, ebx ; if ebx resets to 0, list is complete
jne short .e820lp
.e820f:
mov [mmap_ent], bp ; store the entry count
clc ; there is "jc" on end of list to this point, so the carry must be cleared
mov ah, 0x0E ; Teletype command
mov bh, 0x00 ; Page number
mov bl, 0x07 ; Attributes (7 == white foreground, black background)
mov al, mmap_ent ; Character to print
int 0x10
ret
.failed1:
push eax
push ebx
mov ah, 0x0E ; Teletype command
mov bh, 0x00 ; Page number
mov bl, 0x07 ; Attributes (7 == white foreground, black background)
mov al, 70 ; Character 'F' to print
int 0x10
pop ebx
pop eax
stc ; "function unsupported" error exit
ret
.failed2:
push eax
push ebx
mov ah, 0x0E ; Teletype command
mov bh, 0x00 ; Page number
mov bl, 0x07 ; Attributes (7 == white foreground, black background)
mov al, 71 ; Character 'G' to print
int 0x10
pop ebx
pop eax
stc ; "function unsupported" error exit
ret
.failed3:
push eax
push ebx
mov ah, 0x0E ; Teletype command
mov bh, 0x00 ; Page number
mov bl, 0x07 ; Attributes (7 == white foreground, black background)
mov al, 72 ; Character 'H' to print
int 0x10
pop ebx
pop eax
stc ; "function unsupported" error exit
ret
mmap_ent db 0
failmsg db 0
failmem db 'Failed', 0
;times 512-($-$$) db 0
;dw 0xAA55
EDITED:
I used nasm memext.asm -o memext.com -l memext.lst . Used MagicISO to make a bootable image file memext.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 for a cold boot test, does not print anything.
Also, I open Command Console and just typed memext and it gave 'F' as output.
You will need to read the ACPI tables on a PC (or other machines that support ACPI).
Note that this will not give you the total size as one number, but give you the memory size of each region of memory - on a simple machine, that may just be two or three regions (there are holes of "not real memory" at the 0xA0000-0xFFFFF and wherever the BIOS decides to put the "PCI-hole").
I suspect it won't be entirely trivial to fit the ACPI reader into a single sector, considering some of the boot sector only has around 400 bytes of space available (although if you completely skip the partition table, I suppose you can use almost all of the 512 bytes).
As to "how to call C/C++", you will not be able to fit any meaningful C or C++ program in less than several sectors. You will need to take a look at an OS bootloader, and see how they achieve the setup for the compiler (and in many cases, you will also need special tools to produce code that is at a particular location suitable to be loaded into the memory and directly executed). This page may be of help for that (I haven't read through it all, it may even tell how much memory you have): http://www.codeproject.com/Articles/36907/How-to-develop-your-own-Boot-Loader
EDIT: my mistake, the wiki is correct, just leaving this here because...
Looks like there's a typo in the wiki - the line:
mov edx,0x0534D4150
should look like:
mov edx,0x050414D53
Notice the bytes are in reverse order (since x86 is little endian).
I would like to have this x86 ASM code ported to C or C++, as I don't understand ASM =)
Searching Google it seams Relogix and IDA Pro can do it. But I don't suppose they are cheap, given I only have this one source.
Understanding the math or the algorithm how it works would be just as good, as I am going to use OpenGL anyway.
Are there other methods?
;
; a n d r o m e d a
;
; a 256b demo
; by insomniac/neon
;
code SEGMENT
ASSUME CS:code, DS:code
p386
LOCALS
ORG 100h
max = 4096
maxZ = 5000
b EQU byte ptr
Start: lea di,vars
mov ch,60
rep stosw
mov al,13h
int 10h
p al: mov al,cl
mov dx,3c8h
out dx,al
inc dx
cmp al,64
jb b64_1
mov al,63
b64_1: out dx,al
mov al,cl
shr al,1
out dx,al
out dx,al
loop pal
.main: push 8000h
pop ES
mov si,max
.loop: mov ax,Z[si]
cmp ax,maxZ-(maxZ/4)
jg NewStar
cmp ax,2
jg Zok
NewStar:
mov ax,bp
mov X[si],ax
imul ax,8405h
inc ax
mov bp,ax
shr ax,6
sub ax,400
mov Y[si],ax
mov Z[si],maxZ-(maxZ/2)
Zok: mov ax,X[si]
movsx dx,ah
shl ax,8
mov cx,Z[si]
idiv cx
add ax,320/2
cmp ax,320-1
jge NewStar
cmp ax,1
jle NewStar
mov di,ax
mov ax,Y[si]
movsx dx,ah
shl ax,8
idiv cx
add ax,200/2
imul ax,320
add di,ax
mov al,127
stosb
mov ax,X[si]
cmp ax,00
jge .add
neg ax
shr ax,6
add Y[si],ax
jmp .notadd
.add: shr ax,6
sub Y[si],ax
.notadd:
add Z[si],ax
mov ax,Y[si]
sar ax,3
add X[si],ax
.NextStar:
dec si
dec si
jnz .loop
push DS
push ES
pop DS
xor di,di
xor cx,cx
.blur: movzx ax,DS:[di]
movzx dx,DS:[di+1]
add ax,dx
mov dl,DS:[di-320]
add ax,dx
mov dl,DS:[di+321]
add ax,dx
shr ax,2
cmp al,0
je .skip
dec ax
.skip: stosb
loop .blur
push 0a000h
pop ES
mov si,di
mov ch,81h
rep movsw
pop DS
mov dx,3dah
.vrt: in al,dx
test al,8
jz .vrt
in al,60h
dec ax
jnz .main
endprog:
mov al,3
int 10h
ret
LABEL vars
X dw max DUP (?)
Y dw max DUP (?)
Z dw max DUP (?)
code ENDS
END Start
In general case, this cannot be done. In this particular case, this cannot be done because this assembly program interacts with PC BIOS directly, using int 10h to turn on 320x200 256 VGA mode, and it interacts with PC hardware directly, by writing to IO ports 0x3c8 and 0x3c9 (this sets the VGA palette) and by reading from 0x3da (VGA status register) and 0x60 (PC keyboard microcontroller). It also writes directly to VGA video memory.
Under the conditions of executing on a PC-compatible computer with MS-DOS or similar OS (or, within a simulated environment such as dosbox), this can be done: you can either make each CPU register a C variable and each assembly mnemonic a C function that modifies those variables or writes at absolute memory addresses or IO ports (with outb() and inb()), or, and I think this would be a much more interesting task, understand the math this demo does, and implement that in a portable manner.
Either way, I haven't heard of tools that could do this automatically. Existing tools might handle simple logic, but understanding a demo is never an easy task! What automatic program can tell that
imul ax,8405h
inc ax
should be replaced with ax = rand();?
You could throw it on RentaCoder and pay someone a few $ to write a C version by hand, including an annotation how it was done.
There are quite a few methods of doing so, for example this or this. ;-)