gpt4 book ai didi

assembly - $ 在 NASM 中究竟是如何工作的?

转载 作者:行者123 更新时间:2023-12-02 08:02:31 25 4
gpt4 key购买 nike

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

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

最佳答案

这让汇编器在汇编时为您计算字符串长度
$是在为它出现的行发出字节(如果有)之前的当前位置的地址。 Section 3.5 of the manual没有详细介绍。
$ - msg就像在做here - msg ,即 当前位置(字符串末尾)和字符串开头之间的距离(以字节为单位) . ( See also this tutorial 在 NASM 标签和指令上,如 resb )

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

为了更好地理解它,看看当你出错时会发生什么可能会有所帮助:In NASM labels next to each other in memory are causing printing issues .这个人用

HELLO_MSG db 'Hello, World!',0
GOODBYE_MSG db 'Goodbye!',0

hlen equ $ - HELLO_MSG
glen equ $ - GOODBYE_MSG

导致 hlen包括两个字符串的长度。
EQU立即将右侧计算为常数值。 (在一些像 FASM 这样的汇编器中, equ 是一个文本替换,你必须使用 glen = $ - GOODBYE_MSG 在这个位置用 $ 来计算,而不是在后面的 $ 指令或其他东西中计算 mov ecx, glen。但是 NASM 的 equ 现场评估;使用 %define 进行文本替换)

使用 $完全等同于在行首放置一个标签并使用它代替 $ .

对象大小示例也可以使用常规标签完成:
msg:   db "Enter a digit "
msgend:
Length equ msgend - msg
Length2 equ $ - msg ; Length2 = Length

newline: db 0xA,0xD
Length3 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, msgend/ jb .loop 在循环的底部。

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

不太明显的例子:
times 4  dd $

组装与此相同(但不创建符号表条目或与现有名称冲突):
here:    times 4 dd here

times 4 dd $ , $不会为每个双字更新到自己的地址,它仍然是行首的地址。 (单独在一个文件中尝试它并十六进制转储平面二进制文件:它都是零。)

但是一个 %rep块在 $ 之前被扩展, 所以
%rep 4
dd $
%endrep

确实产生 0, 4, 8, 12 (对于本示例,从输出位置 0 在平面二进制中开始。)
$ nasm -o foo  rep.asm  && hd foo
00000000 00 00 00 00 04 00 00 00 08 00 00 00 0c 00 00 00

手动编码跳跃位移:

正常直通 call is E8 rel32 , 计算相对于指令结束的位移。 (即在指令执行时相对于 EIP/RIP,因为 RIP 保存了下一条指令的地址。RIP 相关寻址模式也以这种方式工作。)一个双字是 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块在同一个源文件中。见 What's the real meaning of $$ in nasm .

到目前为止,最常见的用途是 times 510-($-$$) db 0/ dw 0xAA55将(使用 db 0)一个引导扇区填充到 510 字节,然后添加引导扇区签名以生成 512 字节。 ( The NASM manual explains how this works )

关于assembly - $ 在 NASM 中究竟是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47494744/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com