NASM中的寻址的问题

本文介绍了NASM汇编器中 '$' 和 '$$' 的特殊用法,用于获取当前指令地址和段开始地址。在需要根据代码长度填充0的场景下,正确使用这两个符号的技巧是计算 '$ - $$' 得到纯数值,以解决TIMES指令的参数问题。此外,文章还提及DS数据段寄存器的重要性及其在内存操作中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2009-07-13 21:36

NASM 在表达式中支持两个特殊的记号,即'$'和'$$',它们允许引用当前指令的地址。'$'计算得到它本身所在源代码行的开始处的地址;所以你可以简单地写这样的代码'jmp $'来表示无限循环。'$$'计算当前段开始处的地址,所以你可以通过($-$$)找出你当前在段内的偏移。

 

有些时候,对于代码编译后的长度要求达到一个规定的值,需要在代码末尾填充若干个0,这时候,经常会使用到如下的语句:

                    TIMES n DB 0

这里的n应为一个数值,表示填充的0的个数。

 

例如,要求目标代码的长度为512字节,此时一个常见的错误是写成:

                             TIMES 510-$ DB 0 
即误认为'$'是一个纯数字,就像 510,所以它们相减的值也是一个纯数字,可以很好地被TIMES 使用。

 

由于NASM 是一个模块化的汇编器:不同的组成部分被设计为可以很容易的单独重用,所以它们不会交换一些不必要的信息.结果,'BIN'输出格式尽管被'ORG'告知'.text'段应当在 0处开始,但是不会把这条信息传给表达式的求值程序.所以对求值程序来讲,'$'不是一个纯数值:它是一个从一个段基址开始的偏移值.因为'$'和 510'之间的计算结果也不是一个纯数,而是含有一个段基址.含有一个段基址的结果是不能作为参数传递给'TIMES'的.  
 
正确的写法应该如下: 
 
              TIMES 510-($-$$) DB 0 
 
在这里,'$'和'$$'是从同一个段基址的偏移,所以它们相减的结果是一个纯数,这句代码会解决上述问题,并产生正确的代码。

 

PS:下午那个问题已经想明白了,还是概念不清惹的祸。感谢相关同学耐心帮助好

 

PS2:还是写一下吧。下午的那个问题,我在把代码向上翻了N页后,偶然间在定义部分发现了如下内容:

         mov    ax,SelectorData

         mov    ds,ax

原来代码开头部分早就定义了数据段,我忘了……汗

然后呢,DS 数据段(或称数据选择器),这个寄存器的低16 bit连同ESI一同指向的指令将要处理的内存。同时,所有的内存操作指令默认情况下都用它指定操作段(实模式)或内存(作为选择器,在保护模式,这个寄存器可以被装入任意数值,然而在这么做的时候需要小心一些。方法是,首先把数据送给AX,然后再把它从AX传送给DS(当然,也可以通过堆栈来做)。我把两个地址的差值(也就是字符串相对于数据段起始地址的偏移值,这确实是一个纯数值……)传给ESI后,在没有特别指明的情况下,程序就会自动按照[DS:ESI]去读取数据了……唉,基础啊~~概念啊~~咋就忘得这么一干二净了呢……汗

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值