首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在8086汇编程序中,outportb和out指令之间是否有显著差异?

在8086汇编程序中,outportb和out指令之间是否有显著差异?
EN

Stack Overflow用户
提问于 2019-06-02 23:53:54
回答 1查看 195关注 0票数 1

我是编码在旧的,1994年时代的游戏编程乐趣,并输出数据从一个RAD文件到OPL3 FM合成芯片。我要离开DOSBox了。

为了提高处理硬件寄存器时的性能(特别是因为我正在通过定时中断更新FM Synth芯片(以保持节拍),并且希望尽快回到主代码中),我考虑在汇编中重写我的寄存器输出。

然而,虽然这种方法有效,但它似乎在synth芯片的输出中引入了失真,这在我使用纯C的outportb时是不存在的,我想我应该在这里询问是否有人能告诉我发生了什么。“out dx,al”和“outp(int,char)”之间有什么特别的、细微的区别吗?

代码语言:javascript
复制
OPLStatus status = NONE;
unsigned int primAd;
unsigned int secAd;
unsigned int backAd;

void OPLWriteImpl(void *argument, unsigned int registerNumber, unsigned char registerValue) {
    (void)argument; /* Unused variable */
    if(status == OPL3 || status == DUALOPL2) {
        if(registerNumber <= REGISTER_THRESHOLD) {
            outp(primAd, registerNumber);
            outp(primAd+1, registerValue);
        }
        else {
            outp(secAd, registerNumber);
            outp(secAd+1, registerValue);
        }
    }
    else {
        outp(backAd, registerNumber);
        outp(backAd+1, registerValue);
    }
}
代码语言:javascript
复制
EXTRN status:WORD, primAd:WORD, backAd:WORD

.CODE

PUBLIC OPLWriteImpl
OPLWriteImpl PROC FAR C argument:DWORD, regnum:WORD, regval:BYTE

cmp status,0        ; if status == 0, go to OPL3
je three
cmp status,2        ; if status == DUAL, also go to OPL3
jne two             ; otherwise, go to OPL2

three:
mov dx,primAd       ; put OPL3 primary bank in dx
cmp regnum,100h     ; check if regnum <=than threshold (256)
jle prim            ; if so, go straight to primary bank
    inc dx          ; otherwise, writing to secondary bank (primary+2)
    inc dx
prim:
    mov ax,regnum   ; put the register number in ax
    out dx,ax       ; output to register
    inc dx          ; go to data address
    mov al,regval   ; put the value in al
    out dx,al       ; output to data
    jmp done        ; finished
two:
    mov dx,backAd
    mov ax,regnum
    out dx,ax
    mov cx,6
loopOne:
    in al,dx
    loop loopOne

    inc dx
    mov al,regval
    out dx,al
    dec dx
    mov cx,36
loopTwo:
    in al,dx
    loop loopTwo
done:
ret             ; return to C
OPLWriteImpl ENDP

当使用我的C例程时,音乐像在RAD Tracker中一样正确输出。但是当我使用我的汇编程序时,一些乐器似乎有一种奇怪的沙哑的声音。我真的不能责怪Dosbox仿真,因为,就像我说的,它在纯C语言中工作得很好。区别并不是非常惊人,但它非常明显。我唯一的猜测是outportb的实现实现了一些我的例程中没有的魔力。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-06-03 00:54:09

C语言和汇编语言程序有一个主要的区别:

我不知道你的C编译器的库,但是outp()要么等同于out dx,ax,要么等同于out dx,al

(我猜它等同于out dx,al。)

然而,在你的汇编程序中,你有时用out dx,ax代替outp(),有时用out dx,al代替。两者中肯定有一个是错的。

如果真正的声卡具有8位ISA接口,并且 outp()等同于out dx,al,则使用以下汇编程序代码:

移动ax,注册输出dx,ax增量dx移动,注册输出dx,al

..。取自你的汇编程序,等于下面的C程序:

代码语言:javascript
复制
outportb(address, regnum);
outportb(address + 1, regnum >> 8); // This may cause the noise
outportb(address + 1, regval);

尝试用out dx,al替换out dx,ax

(不幸的是,我不知道DOSbox是用8位还是16位接口模拟声卡。)

请注意

读完我之前写的内容后,您可能会尝试仅使用一条out指令同时写入寄存器和值:

代码语言:javascript
复制
mov al,regnum
mov ah,regval
out dx,ax

很有可能这将与8位连接器的真正声卡一起工作。

但是,这可能不适用于具有16位连接器的真实声卡(也可能不适用于DOSbox之类的模拟器)。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56416630

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档