message db "Enter a digit ", 0xA,0xD
Length equ $- message
Run Code Online (Sandbox Code Playgroud)
它用于获取字符串的长度吗?
它在内部如何运作?
Pet*_*des 13
$
是发出它出现的行的字节(如果有)之前的当前位置的地址. 本手册的第3.5节没有详细介绍.
$ - msg
就像在做here - msg
,即当前位置(在字符串末尾)和字符串开头之间的字节距离.(另请参阅本教程中有关NASM标签和指令的内容resb
)
(相关:$
除了使用.
(句点)的 GAS之外,大多数其他x86汇编程序也使用相同的方式.MMIX汇编程序使用@
,具有正确的语义含义).
为了更好地理解它,可能有助于了解当你弄错时会发生什么: 在NASM中,内存中彼此相邻的标签会导致打印问题.这个人用过
HELLO_MSG db 'Hello, World!',0
GOODBYE_MSG db 'Goodbye!',0
hlen equ $ - HELLO_MSG
glen equ $ - GOODBYE_MSG
Run Code Online (Sandbox Code Playgroud)
导致hlen
包括两个字符串的长度.
EQU
立即评估右侧,达到恒定值.(在一些像FASM这样的汇编程序中,equ
是一个文本替换,你必须用它glen = $ - GOODBYE_MSG
来评估$
这个位置,而不是$
在后面的mov ecx, glen
指令或其他东西中equ
进行评估.但是NASM的评估是在现场; %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
Run Code Online (Sandbox Code Playgroud)
你可以放在Length equ msgend - msg
任何地方,或mov ecx, msgend - msg
直接.(有时在某些东西的末尾有一个标签很有用,例如cmp rsi, msgend
/ jb .loop
在循环的底部.
顺便说一句,它通常是CR LF,而不是LF CR.
times 4 dd $
Run Code Online (Sandbox Code Playgroud)
汇编与此相同(但不创建符号表条目或与现有名称冲突):
here: times 4 dd here
Run Code Online (Sandbox Code Playgroud)
在times 4 dd $
,$
不会更新到每个双字的自己的地址,它仍然是该行的起始地址.(在文件中单独尝试并使用hexdump平面二进制文件:它全部为零.)
但是%rep
之前的块已经扩展$
,所以
%rep 4
dd $
%endrep
Run Code Online (Sandbox Code Playgroud)
确实产生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
Run Code Online (Sandbox Code Playgroud)
正常直接call
是E8 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
Run Code Online (Sandbox Code Playgroud)
反汇编输出(来自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.
Run Code Online (Sandbox Code Playgroud)
如果你得到错误的偏移,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 0
/ dw 0xAA55
垫(有db 0
)引导扇区出510个字节,然后添加引导扇区签名,使512个字节.(NASM手册解释了这是如何工作的)
归档时间: |
|
查看次数: |
1833 次 |
最近记录: |