You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ubuntu Linux下用GNU Assembly实现扬声器指定频率振动(求示例)

GNU汇编实现PC扬声器可控蜂鸣(x86-64 Ubuntu)

下面是适配你硬件和系统的GNU汇编代码,直接通过硬件端口控制PC扬声器,支持指定频率(赫兹)和发声时长(毫秒),功能等价于C语言的Beep()函数:

.global _start

# 硬件端口与常量定义
.equ PIT_CTRL,    0x43        # PIT(可编程间隔定时器)控制端口
.equ PIT_COUNTER0,0x40        # PIT计数器0端口(用于驱动扬声器)
.equ SPEAKER_PORT,0x61        # PC扬声器控制端口
.equ PIT_BASE_FREQ,1193180    # PIT基准时钟频率(固定值)

_start:
    # 示例:调用beep函数,播放440Hz(标准A调),时长1000毫秒
    mov $440, %rdi            # 第一个参数:发声频率(Hz)
    mov $1000, %rsi           # 第二个参数:发声时长(ms)
    call beep

    # 退出程序
    mov $60, %rax             # syscall编号:exit
    xor %rdi, %rdi            # 退出码0
    syscall

# beep函数:rdi=频率(Hz), rsi=时长(ms)
beep:
    # 保存调用者寄存器(GNU汇编调用约定:rax/rbx/rcx/rdx需手动保存)
    push %rax
    push %rbx
    push %rcx
    push %rdx

    # 1. 计算PIT分频值:分频 = 基准频率 / 目标频率
    mov $PIT_BASE_FREQ, %rax
    div %rdi                  # rax = 基准频率 / 频率,余数存入rdx(忽略)
    mov %rax, %cx             # 分频值存入16位寄存器cx

    # 2. 配置PIT为模式3(方波发生器),使用计数器0
    mov $0b10110110, %al      # 控制字:计数器0、低字节先写、模式3、二进制计数
    out %al, $PIT_CTRL

    # 3. 向计数器0写入分频值(低字节优先)
    mov %cl, %al
    out %al, $PIT_COUNTER0
    mov %ch, %al
    out %al, $PIT_COUNTER0

    # 4. 打开扬声器:置位0x61端口的第0、1位(允许数据+扬声器使能)
    in $SPEAKER_PORT, %al
    or $0b11, %al
    out %al, $SPEAKER_PORT

    # 5. 延时指定毫秒
    mov %rsi, %rdi            # 将时长参数传入msleep函数
    call msleep

    # 6. 关闭扬声器:清除0x61端口的第0、1位
    in $SPEAKER_PORT, %al
    and $0b11111100, %al
    out %al, $SPEAKER_PORT

    # 恢复寄存器并返回
    pop %rdx
    pop %rcx
    pop %rbx
    pop %rax
    ret

# msleep函数:rdi=时长(ms)
msleep:
    # 使用nanosleep系统调用实现高精度延时
    push %rax
    push %rdi
    push %rsi

    # 构造timespec结构体:tv_sec = 毫秒数/1000,tv_nsec = (毫秒数%1000)*1000000
    xor %rdx, %rdx
    mov $1000, %rbx
    div %rbx                  # rax=秒数,rdx=剩余毫秒数
    mov %rax, (%rsp)          # 写入tv_sec字段
    mov %rdx, %rax
    mov $1000000, %rbx
    mul %rbx                  # rax=纳秒数
    mov %rax, 8(%rsp)         # 写入tv_nsec字段

    mov $35, %rax             # syscall编号:nanosleep
    mov %rsp, %rdi            # 指向timespec结构体的指针
    xor %rsi, %rsi            # 忽略剩余未休眠时间
    syscall

    pop %rsi
    pop %rdi
    pop %rax
    ret

编译与运行步骤

  1. 将代码保存为beep.s
  2. 编译汇编文件:as -o beep.o beep.s
  3. 链接生成可执行文件:ld -o beep beep.o
  4. 必须以root权限运行(硬件端口访问需要权限):sudo ./beep

关键说明

  • 代码直接操作硬件端口,而非调用系统默认提示音,完全可控频率和时长
  • 支持20Hz~20000Hz的人耳可听频率范围
  • 延时依赖Linux原生nanosleep系统调用,精度可靠
  • Dell Optiplex 960的PC扬声器完全兼容该硬件控制逻辑

内容的提问来源于stack exchange,提问作者Colton Paul Badock

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 12:10:34