为了账号安全,请及时绑定邮箱和手机立即绑定

$ NAS如何在NASM中工作?

/ 猿问

$ NAS如何在NASM中工作?

$ NAS如何在NASM中工作?

message db "Enter a digit ", 0xA,0xDLength equ $- message

它用于获取字符串的长度吗?
它在内部如何运作?


查看完整描述

1 回答

?
慕少森

$是发出它出现的行的字节(如果有)之前的当前位置的地址。 本手册的第3.5节没有详细介绍。

$ - msg就像在做here - msg,即当前位置(在字符串末尾)和字符串开头之间的字节距离。(另请参阅本教程中有关NASM标签和指令的内容resb

(相关:$除了使用.(句点)的 GAS之外,大多数其他x86汇编程序也使用相同的方式.MMIX汇编程序使用@,具有正确的语义含义)。


为了更好地理解它,可能有助于了解当你弄错时会发生什么: 在NASM中,内存中彼此相邻的标签会导致打印问题。这个人用过

HELLO_MSG db 'Hello, World!',0GOODBYE_MSG db 'Goodbye!',0hlen equ $ - HELLO_MSGglen equ $ - GOODBYE_MSG

导致hlen包括两个字符串的长度。

EQU立即评估右侧,达到恒定值。(在一些像FASM这样的汇编程序中,equ是一个文本替换,你必须用它glen = $ - GOODBYE_MSG来评估$这个位置,而不是$在后面的mov ecx, glen指令或其他东西中equ进行评估。但是NASM的评估是在现场; %define用于文本替换)


使用$完全等同于将标签放在行的开头并使用它而不是$

对象大小示例也可以使用常规标签完成:

msg:   db "Enter a digit "msgend: Length equ msgend - msgLength2 equ $ - msg     ; Length2 = Lengthnewline: db 0xA,0xDLength3 equ $ - msg     ; Length3 includes the \n\r LF CR sequence as well.
                        ; sometimes that *is* what you want

你可以放在Length equ msgend - msg任何地方,或mov ecx, msgend - msg直接。(有时在某些东西的末尾有一个标签很有用,例如cmp rsi, msgendjb .loop在循环的底部。

顺便说一句,它通常是CR LF,而不是LF CR。


不太明显的例子:

times 4  dd $

汇编与此相同(但不创建符号表条目或与现有名称冲突):

here:    times 4 dd here

times 4  dd $$不会为每个双字更新到自己的地址,它仍然是该行开头的地址。(在文件中单独尝试并使用hexdump平面二进制文件:它全部为零。)


但是%rep之前的块已经扩展$,所以

%rep 4
    dd $%endrep

确实生成0,4,8,12(从0本例中的平面二进制文件的输出位置开始。)

$ nasm -o foo  rep.asm  && hd foo00000000  00 00 00 00 04 00 00 00  08 00 00 00 0c 00 00 00

手动编码跳跃位移:

正常直接callE8 rel32,相对于指令的结束计算位移。(即,在执行指令时相对于EIP / RIP,因为RIP保存下一条指令的地址.RIP相对寻址模式也是这样工作的。)dword是4字节,所以在dd带有一个操作数的伪指令中,结尾的地址是$+4。你当然可以在下一行标注并使用它。

earlyfunc:           ; before the call
    call func        ; let NASM calculate the offset
    db  0xE8
    dd  func - ($ + 4)       ; or do it ourselves
    db  0xE8
    dd  earlyfunc - ($ + 4)  ; and it still works for negative offsets
    ...func:                ; after the call

反汇编输出(来自objdump -drwC -Mintel):

0000000000400080 <earlyfunc>:
  400080:       e8 34 00 00 00          call   4000b9 <func>    # encoded by NASM
  400085:       e8 2f 00 00 00          call   4000b9 <func>    # encoded manually
  40008a:       e8 f1 ff ff ff          call   400080 <earlyfunc>  # and backwards works too.

如果你得到错误的偏移,objdump会把符号部分作为func+8例如。前2个调用指令中的相对位移相差5,因为它call rel32是5个字节长并且它们具有相同的实际目的地,而不是相同的相对位移。请注意,反汇编程序负责将rel32添加到调用指令的地址,以显示绝对目标地址。

您可以使用db target - ($+1)短消息编码jmp或偏移jcc。(但要注意:db 0xEB, target - ($+1)不正确,因为指令的结尾实际上$+2是将操作码和位移作为同一db伪指令的多个参数。)


相关:$$是当前的开始部分,所以$ - $$你是如此遥远的当前部分。但这仅在当前文件中,因此链接两个放入内容的文件.rodata不同于section .rodata在同一源文件中有两个块。请参阅nasm中$$的真正含义。

到目前为止,最常见的用途是times 510-($-$$) db 0dw 0xAA55垫(有db 0)引导扇区出510个字节,然后添加引导扇区签名,使512个字节。(NASM手册解释了这是如何工作的)


查看完整回答
反对 回复 2019-08-28

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信