Assembly 纳斯姆。方括号返回相对位置。如何找到绝对值?

Assembly 纳斯姆。方括号返回相对位置。如何找到绝对值?,assembly,nasm,x86-16,qemu,real-mode,Assembly,Nasm,X86 16,Qemu,Real Mode,我想用电传打字机打印这个符号。 下面是一段代码: mov al, [smb] int 0x10 smb: db "X" 但事实证明,这显示的是来自内存的任意符号,而不是来自该位置的任意符号。似乎[]返回符号的相对地址。这可能是意料之中的,但问题是:我如何才能找到绝对地址? 我正在使用QEMU-i386,与标准NASM组装 在回顾了与NASM相关的其他问题后,请注意:请不要告诉我去查看NASM的文档,因为这里有很多人问了很多关于C#的简单问题,但是它们并没有被发送到里希特。您要找的指令是加载有

我想用电传打字机打印这个符号。 下面是一段代码:

mov al, [smb]
int 0x10

smb: db "X"
但事实证明,这显示的是来自内存的任意符号,而不是来自该位置的任意符号。似乎[]返回符号的相对地址。这可能是意料之中的,但问题是:我如何才能找到绝对地址? 我正在使用QEMU-i386,与标准NASM组装


在回顾了与NASM相关的其他问题后,请注意:请不要告诉我去查看NASM的文档,因为这里有很多人问了很多关于C#的简单问题,但是它们并没有被发送到里希特。

您要找的指令是
加载有效地址

您要找的指令是
加载有效地址

64位代码;默认为绝对寻址,要获得RIP相对寻址,您可以使用类似于
mov al、[rel smb]
的内容。然而;可以使用
default REL
指令更改默认值;在这种情况下,如果需要绝对寻址,可以使用类似于
mov-al、[abs-smb]
的东西

用于16位和32位代码;绝对寻址是唯一的选择(忽略“绝对地址编码为相对位移”这一可能不必要的混淆,这种混淆发生在一些跳转和调用中,这对
mov al,[smb]
)并不重要

对于这两种情况(16位和32位代码,以及64位代码);“绝对寻址”实际上是从段基的绝对偏移量。例如,
mov al,[smb]
将隐式使用
DS
段,因此如果DS段的基址不为零(这仅适用于32位和16位代码-对于64位代码,只有FS和GS可以有段基址),则实际绝对地址将为“段基址+绝对偏移”。如果段基准为零,则可以忽略此项(“段基准+绝对偏移”=“0+绝对偏移”=“绝对偏移”)


当然,如何确定绝对偏移取决于它位于哪个截面以及截面的起始位置;哪个(取决于输出文件格式-平面二进制文件与对象文件)取决于
org
指令、节定义或链接器。

对于64位代码;默认为绝对寻址,要获得RIP相对寻址,您可以使用类似于
mov al、[rel smb]
的内容。然而;可以使用
default REL
指令更改默认值;在这种情况下,如果需要绝对寻址,可以使用类似于
mov-al、[abs-smb]
的东西

用于16位和32位代码;绝对寻址是唯一的选择(忽略“绝对地址编码为相对位移”这一可能不必要的混淆,这种混淆发生在一些跳转和调用中,这对
mov al,[smb]
)并不重要

对于这两种情况(16位和32位代码,以及64位代码);“绝对寻址”实际上是从段基的绝对偏移量。例如,
mov al,[smb]
将隐式使用
DS
段,因此如果DS段的基址不为零(这仅适用于32位和16位代码-对于64位代码,只有FS和GS可以有段基址),则实际绝对地址将为“段基址+绝对偏移”。如果段基准为零,则可以忽略此项(“段基准+绝对偏移”=“0+绝对偏移”=“绝对偏移”)


当然,如何确定绝对偏移取决于它位于哪个截面以及截面的起始位置;哪个(取决于输出文件格式-平面二进制文件与对象文件)取决于
org
指令、节定义或链接器。

这是相关的,但这不是解决问题的方法-我只需要LEA计算的绝对地址。@AlexeyKhrenov注意LEA只处理“偏移量”seg的一部分:关闭地址。如果您没有一个平面内存模型和/或您没有正确使用
org
告诉汇编程序在哪里加载程序,LEA将不会有帮助。这是相关的,但它并不能解决问题-我只需要LEA计算的绝对地址。@AlexeyKhrenov注意到LEA只处理“偏移量”seg的一部分:关闭地址。如果您没有平面内存模型和/或您没有正确使用
org
告诉汇编程序加载的位置,LEA将不会有帮助。您应该提供一个.
mov al,[smb]
smb
处的字节(
X
在本例中)移动到al。这可能是您想要做的。我假设您已将
0x0e
移动到AH中,以便通过BIOS服务int 10h进行TTY输出调用。您可能希望在int 0x10和下面的数据之间放置一个无限循环或其他东西,这样就不会出错,而是开始以数据的形式执行代码。但如果我不得不猜测,您的问题可能是DS段寄存器指向错误的段。如果你展示了你所有的代码,这会有所帮助。我猜想您可能是在某种引导加载程序或第一阶段执行此操作的?另一种可能是您没有根据代码预期设置ORG语句。例如,在引导加载程序中,我通常在NASM文件的顶部使用
ORG 0x7c00
,然后在引导加载程序代码的顶部,我使用类似于
xor ax,ax
mov DS,ax的东西将DS设置为0谢谢!即使没有将DS设置为0x00,调用组织0x7c00也可以工作。是的,我正在为一个爱好项目构建一个简单的引导扇区。您应该提供一个。
mov al,[smb]
smb
处的字节(
X
在本例中)移动到al。这可能是您想要做的。我假设您已将
0x0e
移动到AH中,以便通过BIOS服务int 10h进行TTY输出调用。您可能希望在int 0x10和下面的数据之间放置一个无限循环或其他东西,这样就不会出错,而是开始以数据的形式执行代码。但如果让我猜的话,你的