NASM编译LEA/MOV获取label地址时为何生成0x011e而非0x001e?
16位NASM汇编中LEA/MOV获取Label地址偏移异常的原因分析
出现这种地址偏差的核心原因,是16位实模式的逻辑地址规则与NASM汇编器的地址计算逻辑共同作用的结果,具体分以下几种情况:
1. ORG伪指令的设置差异
NASM通过org伪指令指定程序加载后的段内起始偏移。如果你的代码中设置了org 0x100(这是COM格式程序的标准配置),汇编器会给所有标签的偏移地址加上0x100:
- 假设
end标签在程序自身代码内的相对偏移是0x001E,加上org 0x100后,汇编器计算出的段内绝对偏移就是0x011E,对应lea dx, [end]生成的机器码就是8D161E01(小端存储,低字节在前)。 - 你看到的反汇编显示
end位于0x001E,大概率是反汇编工具以程序自身的起始字节为基准计算的相对偏移,而非段内的绝对偏移。
2. 段基址与地址类型的误解
16位实模式下,内存地址采用段:偏移的逻辑地址格式,物理地址 = 段地址 << 4 + 偏移地址:
- 若程序运行时段寄存器(如CS、DS)的基址为
0x0000,那么0x011E的段内偏移对应的物理地址就是0x011E;如果你看到的反汇编结果显示的是物理地址0x001E,则说明你可能混淆了反汇编工具的地址显示类型。 - 若反汇编工具显示的是程序自身的相对偏移(从程序第一个字节开始计数),那么
0x001E是程序内的位置,而汇编器生成的0x011E是段内的绝对偏移,二者的差值就是org指令设置的起始偏移。
3. LEA与MOV指令的地址解析逻辑
对于lea dx, [end]和mov dx, [end]:
lea指令直接将end的段内偏移地址加载到DX寄存器,完全由汇编器根据段配置计算;mov dx, [end]本质是读取end偏移地址处的内存值,但如果end是地址标签而非变量,NASM会默认将其解析为段内偏移地址,最终生成的机器码同样会使用汇编器计算后的绝对偏移。
验证方法
- 检查代码开头的
org伪指令,尝试添加org 0x0000后重新编译,观察机器码是否变为8D161E00; - 确认反汇编工具的地址显示规则,区分是段内偏移、程序相对偏移还是物理地址;
- 运行程序时打印段寄存器(如DS、CS)的值,结合DX的值计算物理地址,对比反汇编中的地址。
内容的提问来源于stack exchange,提问作者ExecAssa
相关产品推荐
相关产品推荐

