我正在尝试在汇编代码中生成声音。这是我发现的一些代码:
section .text
global sound
sound:
mov al, 182 ; meaning that we're about to load
mov ax, 182
out 43h, al ; a new countdown value
ret
mov ax, 2153 ; countdown value is stored in ax. It is calculated by
out 42h, al ; Output low byte.
mov al, ah ; Output high byte.
out 42h, al
in al, 61h
or al, 00000011b
out 61h, al ; Send the new value
ret
根据此代码的所有者,它应该可以工作,但是当我使用C main运行它时,它会被分段错误杀死。
通过进一步的研究,我发现在现代操作系统中,由于权利而更难以访问扬声器。如果有人知道如何访问扬声器并播放声音,我很乐意学习它。
注意:当我以超级用户身份运行我的代码时,我没有出现分段错误,但没有声音产生。
答案 0 :(得分:1)
[在您与NASM编译器一起阅读本著作之前,我不确定其他编译器是否有用]
您的代码很好,但这是问题所在:
长话短说,您正在尝试访问主板扬声器,但虚拟机无法使用它,因此您听不到任何声音。
此外,大多数较新的主板也没有板载扬声器。
mov al, 182 ; meaning that we're about to load
mov ax, 182
out 43h, al ; a new countdown value
ret
要稍微修饰一下这一部分,您可以删除mov ax, 182
和ret
,因为那里的返回权将从代码中跳出,您称之为调用它的地方不再运行代码了: / p>
mov ax, 2153 ; countdown value is stored in ax. It is calculated by
out 42h, al ; Output low byte.
mov al, ah ; Output high byte.
out 42h, al
in al, 61h
or al, 00000011b
out 61h, al ; Send the new value
ret
已过时。对于mov ax, 182
,当我使用免提扬声器时,它的工作原理与此无关,因此我想您不需要它,所以我会说有必要将其删除。
因此,您的代码的修订版将是:
bits 16
start:
mov ax, 0x07c0 ; Setup the stack past where we are loaded
add ax, 544
cli ; Disable interrupts
mov ss, ax
mov sp, 4096
sti ; Restore interrupts
mov ax, 0x07c0 ; Set the data segment to where we are
mov ds, ax
sound:
mov al, 182 ; Were about to load
out 0x43, al
mov ax, 15000 ; 15000(Pitch) = 1,193,180 / 79.5453333(Repeating)
out 0x42, al ; Give the port the lower value
mov al, ah
out 0x42, al ; Now give it the higher
in al, 0x61
or al, 00000011b ; Connect the speaker to Timer 2
out 0x61, al
jmp $ ; hang
times 510-($-$$) db 0 ; Pad the rest of the file with 0's
dw 0xaa55 ; Little Endian MBR Signature
要运行此程序以查看其是否有效,请确保您的计算机装有板载扬声器。我的看起来像这样: here
如果您没有它,则您的外观可能不像我的,如果没有,您可以在代码后显示或进行某些操作以确保其运行。
我使用这些命令来运行它。
nasm -f bin <YOURFILENAME>.asm -o boot.bin
dd if=boot.bin of=\\.\<DRIVENUMBER>: bs=512
这些是nasm的工作之一是nasm编译器并编译程序集文件。如果您已经在linux上,则dd是rawwrite,但是在像我正在使用的Windows上,您可以下载rawwrite here。确保您的驱动器号是您正在使用的驱动器,例如USB或FLOPPY。例如,如果您的USB位于驱动器d上:您将使用:
dd if=boot.bin of=\\.\d: bs=512
然后,您可以将USB与振荡器一起插入计算机。为我启动计算机并进入启动菜单,我只是发送垃圾邮件f10,直到到达那里为止,但是对于您来说,它可能是一个不同的按钮,系统将询问您应该引导哪个设备来找到USB并引导至该设备。如果没有操作系统显示,它将启动:
mov ah, 0x0e
mov al, 'X'
int 0x10
要查看是否正在引导,请在bits 16
之后将其添加到文件顶部:
jmp short start
nop
OEMLabel db "Contoso" ; OEM Label
BytesPerSector dw 512 ; There are 512b per sector
SectorsPerCluster db 1 ; Sectors per cluster
ReservedForBoot dw 1 ; # of sectors reserved for boot
NumberOfFats db 2 ; # of fats
RootDirEntries dw 224 ; # of root directory entries
LogicalSectors dw 2880 ; # of sectors
MediumByte db 0x0f0 ; Medium descriptor byte
SectorsPerFat dw 9 ; # of sectors per fat
SectorsPerTrack dw 18 ; # of sectors per track
Sides dw 2 ; # of sides
HiddenSectors dd 0 ; # of hidden sectors
LargeSectors dd 0 ; # of large sectors
DriveNo dw 0 ; The drive number
Signature db 41 ; The drive signature
VolumeID dd 0xdeadbeef ; The volume id
VolumeLabel db "Windows9 "; This can be any 11 characters
FileSystem db "FAT12 " ; File system of the floppy DONT CHANGE
如果由于某种原因该代码不起作用,请检查是否有任何错误,并确保您的主板有板载扬声器。
有关更多信息,请如上所述here。 源代码here的基础。 有关汇编here的一些技巧,这是一个文档齐全的开源操作系统,可以帮助初学者学习汇编。
希望这会有所帮助!
编辑:彼得·科德(Peter Cordes)的一些错别字和帮助(在评论中)