急求一个汇编语言的小程序,急呀……

[复制链接]
查看11 | 回复6 | 2021-1-27 06:42:58 | 显示全部楼层 |阅读模式
课程题目:声卡发声程序,要求通过声卡,使音响发声。只要使音响发个声音就行,拜托各位高手了,急用呀,全天在线,等候答案ing……
分 -->
回复

使用道具 举报

千问 | 2021-1-27 06:42:58 | 显示全部楼层
dma方式直接操作声卡
;DOS下直接控制声卡发声的汇编例子程序
;在winXP的cmd窗口中调试通过
;有的机器在纯dos下找不到声卡,可能主板上的集成声卡不兼容
codeSEGMENT
ASSUMECS:code,ds:code
ORG100H
start:;jmploc_2;去掉jmp前的分号,可以跳过显示作者信息
callloc_1
db"DOSvoctestv1.0(c)SYZ2006.7.13",0dh,0ah
db"pressanykey",0dh,0ah,24h
;山东海化集团盛玉增编制,qq:5611409e-mail:[email protected]
;http://www.wfhyjl.cn转载请保留作者信息,谢谢。
val_1dw0
loc_1:
popdx
movah,9
int21h;显示信息
loc_2:
movdx,226h
moval,1
outdx,al
;;;;;;;;复位dsp
movcx,0
loop$
moval,0
outdx,al
calldspin
cmpal,0aah;判断声卡是否准备好
jzloc_3
jmperror_1;出错退出
loc_3:

moval,0d1h
calldspout;打开喇叭
movsi,offsetdata_1;音频数据开始
movcx,offsetdata_end;音频数据结尾
subcx,si;算出音频数据字节数
movval_1,cx;保存到变量中
movdi,8000h
moves,di
movdi,0
cld
repmovsb;把音频数据移动到8000:0
;目的是免了计算DMA页和偏移的麻烦,同时也
;可以防止出现DMA传输的的跨段错误
movdx,0ah;DMA屏蔽寄存器
moval,5;选择通道1
;用通道3时,al=7
;一般声卡默认是用通道1
outdx,al;maskoffdmachannel
movdx,0ch;DMACFFREG
moval,0
outdx,al;clearflip-flop
movdx,0bh
moval,59h
outdx,al;setmodefordac
movdx,2;dma偏移
moval,0;8000:0的偏移是0
outdx,al;低8位0
outdx,al;高8位0
movdx,83h;dma页
moval,8h;8000:0的页是8
outdx,al
movdx,3;dma计数
movcx,val_1;数据块大小
moval,cl
decal
outdx,al;低8位
moval,ch
outdx,al;高字节
movdx,0ah;dmac屏蔽寄存器
moval,1;允许通道1接受请求
outdx,al
moval,040h;dspcmdtimeconst命令
calldspout
moval,131;tc控制声音播放的速度
calldspout
moval,48h;dspcmdblocksize命令
calldspout
movcx,val_1;count数据块的大小
deccx;减去一个字节
moval,cl;低8位
calldspout
moval,ch;高8位
calldspout
moval,1ch;dspcmdautodmadac
calldspout;dsp自动模式

ddd_1:movah,0
int16h;等待按任意键
moval,0d3h
calldspout;关喇叭
moval,0dah
calldspout;停止dma传输
error_1:
pushcs
popds
int20h;返回dos
dspout:pushax;dsp输出
movdx,22ch
dso1:inal,dx
oral,al
jsdso1;未就绪,循环等待
popax
outdx,al
retn

dspin:;dsp输入
movdx,22eh
dsi1:inal,dx
andal,80h
jzdsi1;是否就绪?
movdx,22ah
inal,dx
retn
;-------------------------------------------------------------
;以下为voc文件内容,是用cooleditpro2.0录制的,内容是一句典型
;的潍坊方言,请能听懂的朋友与我联系:-)
;直接把数据文件放到这里,是为了免去操作文件的麻烦,作者比较懒,
;用流行的话说是,相当的懒:-)
;以下为voc的文件头部分,是用\masm32\bintodb.exe转化的
;C:\haha.vocis20037byteslong
db67,114,101,97,116,105,118,101,32,86,111,105,99,101,32,70
db105,108,101,26,26,0,10,1,41,17,1,2,64,0,131,0;此处的131是tc
data_1:;以下为音频数据块
db126,126,126,126,125,125,125,125,125,125,125,125,125,125,124,124
db124,124,124,124,124,124,124,124,124,125,125,125,125,126,126,126
db127,127,127,128,128,128,128,128,128,128,128,127,127,127,126,126
db125,125,125,124,124,123,123,123,123,122,122,122,122,122,122,122
db122,122,122,122,123,123,123,124,124,125,126,127,127,128,129,129
db130,131,131,132,132,132,132,131,131,129,128,127,126,125,124,123

回复

使用道具 举报

千问 | 2021-1-27 06:42:58 | 显示全部楼层
这个问题你问了几个帖子了,给你解决啦~~~

TITLEDemo.asm
;===============================================
;Author:狼の禅
;Date:09/10/2010
;===============================================
.386
.modelflat,stdcall
optioncasemap:none
includewindows.inc
includeuser32.inc
includegdi32.inc
includemasm32.inc
includekernel32.inc
includelibuser32.lib
includelibkernel32.lib
includelibmasm32.lib
;-----------------------------------------------
MENU_ABOUTAUTHORequ1000
;-----------------------------------------------
WinMainPROTO:DWORD,:DWORD,:DWORD,:DWORD
WndProcPROTO:DWORD,:DWORD,:DWORD,:DWORD
GetSizePROTO:DWORD;由簇数获取磁盘空间大小
;===============================================
.data
hInstancedd0;应用程序句柄
hWnddd0;窗口句柄
hMenudd0;菜单句柄
ClassNamedb"Demo",0
WindowNamedb"Demo(狼の禅)",0
MenuAboutdb"帮助(&H)",0
MenuAboutAuthordb"驱动器信息和关于作者(&A)",0
Authordb"Author:狼の禅",0dh,"Date:23/07/2009",0
Driverdd0;驱动器位掩码
DriverNumStringdb"系统驱动器数目:"
DriverNumdb5dup(0)
DriveStringsdb40dup(0)
HardDiskdb"硬盘驱动器",0
CDROMdb"光盘驱动器",0
lpSectorsPerClusterdd0;一个簇内的扇区数
lpBytesPerSectordd0;一个扇区内的字节数
lpNumberOfFreeClustersdd0;剩余簇数
lpTotalNumberOfClustersdd0;总簇数
AllSizeREAL80.0
Num1024REAL81024.0;实数1024
AllSpacedb"总空间:"
AllSizeStringdb30dup(0),0
FreeSpacedb"剩余空间:"
FreeSizeStringdb30dup(0),0
;===============================================
.code
start:
invokeGetModuleHandle,0;获取应用程序模块句柄
movhInstance,eax;保存应用程序句柄
invokeWinMain,hInstance,0,0,SW_SHOWDEFAULT
invokeExitProcess,eax;退出程序,并返回eax的值
;===============================================
WinMainprochInst:DWORD,hPrevInst:DWORD,CmdLine:DWORD,CmdShow:DWORD
LOCALwndclass:WNDCLASSEX
LOCALMsg:MSG
movwndclass.cbSize,sizeofWNDCLASSEX
movwndclass.style,CS_HREDRAWorCS_VREDRAWorCS_BYTEALIGNWINDOW
movwndclass.lpfnWndProc,OFFSETWndProc
movwndclass.cbClsExtra,0
movwndclass.cbWndExtra,0
moveax,hInst
movwndclass.hInstance,eax
movwndclass.hbrBackground,COLOR_WINDOW+1
movwndclass.lpszMenuName,0
movwndclass.lpszClassName,OFFSETClassName
invokeLoadIcon,hInst,NULL
movwndclass.hIcon,eax
invokeLoadCursor,0,IDC_ARROW
movwndclass.hCursor,eax
movwndclass.hIconSm,0
invokeRegisterClassEx,ADDRwndclass;注册用户定义的窗口类
invokeCreateWindowEx,WS_EX_OVERLAPPEDWINDOW,ADDRClassName,
ADDRWindowName,
WS_OVERLAPPEDWINDOW,
200,50,500,300,
0,0,
hInst,0;创建窗口
movhWnd,eax;保存窗口句柄
invokeShowWindow,hWnd,SW_SHOWNORMAL;
invokeUpdateWindow,hWnd
MessageLoop:
invokeGetMessage,ADDRMsg,0,0,0;获取消息
cmpeax,0
jeExitProgram
invokeTranslateMessage,ADDRMsg;转换键盘消息
invokeDispatchMessage,ADDRMsg;分发消息
jmpMessageLoop
ExitProgram:
moveax,Msg.wParam
ret
WinMainendp
;===============================================
WndProcprochWin:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
localhPopMenu;一级菜单句柄
localuint:UINT
.ifuMsg==WM_CREATE
invokeCreateMenu
movhMenu,eax
.ifeax
invokeCreatePopupMenu;创建一级菜单
movhPopMenu,eax;保存一级菜单句柄
invokeAppendMenu,hPopMenu,NULL,MENU_ABOUTAUTHOR,addrMenuAboutAuthor;添加二级菜单
invokeAppendMenu,hMenu,MF_POPUP,hPopMenu,addrMenuAbout;添加一级菜单
.endif
invokeSetMenu,hWin,hMenu;设置菜单
.elseifuMsg==WM_DESTROY
invokePostQuitMessage,0;退出消息循环
.elseifuMsg==WM_COMMAND
.ifwParam==MENU_ABOUTAUTHOR
invokeGetLogicalDrives;获取驱动器位掩码,0位表示驱动器A,若存在的第0位为1,以此类推
movDriver,eax
movedi,0
.while(Driver!=0)
moveax,Driver
andeax,1
.if(eax==1)
incedi
.endif
shrDriver,1
.endw
invokedw2a,edi,addrDriverNum
invokeMessageBoxA,hWin,ADDRDriverNumString,ADDRClassName,MB_OK;输出驱动器数目
invokeGetLogicalDriveStrings,40,addrDriveStrings
leaesi,DriveStrings
movecx,edi
.while(ecx!=0)&&(BYTEPTR[esi]!=0)
invokeGetDriveType,esi
movuint,eax
.if(uint==DRIVE_CDROM);判断是否为光驱
invokeMessageBoxA,hWin,esi,ADDRCDROM,MB_OK
.elseif(uint==DRIVE_FIXED);判断是否为硬盘
invokeMessageBoxA,hWin,esi,ADDRHardDisk,MB_OK
.endif
invokeGetDiskFreeSpace,esi,addrlpSectorsPerCluster,addrlpBytesPerSector,addrlpNumberOfFreeClusters,addrlpTotalNumberOfClusters
invokeGetSize,lpTotalNumberOfClusters;获取磁盘总空间大小
invokeFloatToStr2,AllSize,addrAllSizeString
invokeMessageBoxA,hWin,addrAllSpace,esi,MB_OK
invokeGetSize,lpNumberOfFreeClusters;获取磁盘剩余空间大小
invokeFloatToStr2,AllSize,addrFreeSizeString
invokeMessageBoxA,hWin,addrFreeSpace,esi,MB_OK
dececx
addesi,4
.endw
invokeMessageBoxA,hWin,ADDRAuthor,ADDRClassName,MB_OK
.endif
.else
invokeDefWindowProc,hWin,uMsg,wParam,lParam;调用默认消息处理函数
ret
.endif
xoreax,eax
ret
WndProcendp
;===============================================
GetSizeprocNumberOfClusters:DWORD
finit
fildlpSectorsPerCluster
fildNumberOfClusters
fmulST(0),ST(1)
fildlpBytesPerSector
fmulST(0),ST(1)
fldNum1024
fdivST(1),ST(0)
fdivST(1),ST(0)
fdivST(1),ST(0)
fstpAllSize
fstpAllSize
ret
GetSizeendp
endstart

回复

使用道具 举报

千问 | 2021-1-27 06:42:58 | 显示全部楼层
二楼你怎么发了一个获得驱动器信息的代码上来?
回复

使用道具 举报

千问 | 2021-1-27 06:42:58 | 显示全部楼层
直接操作端口吧,例子可以看《ibm汇编语言程序设计》,网上也一大堆。
回复

使用道具 举报

千问 | 2021-1-27 06:42:58 | 显示全部楼层
学习中...
回复

使用道具 举报

千问 | 2021-1-27 06:42:58 | 显示全部楼层
学习中...
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题

0

回帖

4882万

积分

论坛元老

Rank: 8Rank: 8

积分
48824836
热门排行