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

如何编写将自身操作码首字节存入al寄存器的汇编指令?

解决读取自身操作码到al的问题

你原来的代码mov al,byte[0100];的问题在于依赖固定内存地址,DOS下程序的加载地址不是固定的(即使是.com程序默认从CS:100h开始,硬编码地址依然不可靠),而且没有定位到当前指令的地址。

在iapx88(8088)架构下,无法直接访问IP(指令指针)寄存器,所以要获取当前指令的地址,得用call指令的特性间接实现:call执行时会把下一条指令的地址压入栈,我们弹出这个地址后,减去当前call指令的长度,就能得到call指令自身的起始地址,再读取该地址的字节到al。

可行代码示例(适用于DosBox下的NASM .com程序)

org 100h  ; .com程序的起始地址,DOS会加载到CS:100h

start:
    call get_self_addr  ; 这条指令的操作码第一个字节是0E8h,长度为3字节
get_self_addr:
    pop ax              ; ax现在是get_self_addr标签的地址(即call指令的下一条指令地址)
    sub ax, 3           ; 减去call指令的长度3,得到call指令自身的起始地址
    mov al, byte [ax]   ; 读取call指令的第一个操作码字节到al

    ; 可选:验证结果,将al的值以十六进制输出
    mov ah, 0Eh
    mov dl, al
    shr dl, 4
    add dl, '0'
    cmp dl, '9'
    jbe print_high
    add dl, 7
print_high:
    int 10h
    mov dl, al
    and dl, 0Fh
    add dl, '0'
    cmp dl, '9'
    jbe print_low
    add dl, 7
print_low:
    int 10h

    mov ah, 4Ch
    int 21h  ; 退出程序

代码解释

  • call get_self_addr:执行时先把下一条指令(pop ax)的地址压栈,然后跳转到get_self_addr标签。
  • pop ax:将栈中保存的地址弹出到ax,此时ax等于get_self_addr的地址,也就是call指令的下一条指令地址。
  • sub ax,3:8088中call near指令是3字节长度,减去3就得到了call指令自身的起始地址。
  • mov al, byte [ax]:读取该地址的第一个字节(也就是call指令的操作码0E8h)存入al。

如果需要读取其他指令的自身操作码,只需要调整sub ax的数值(对应指令的字节长度)即可。

内容的提问来源于stack exchange,提问作者user19963011

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 15:05:21