$ NAS如何在NASM中工作?

时间:2017-11-26 09:34:03

标签: assembly x86 nasm

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

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

1 个答案:

答案 0 :(得分:12)

$发出其出现的行的字节(如果有)之前的当前位置的地址。 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在此位置使用$进行评估,而不是在后期评估$ { {1}}指令或其他内容。但NASM mov ecx, glen当场评估;使用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

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

不太明显的例子:

jb .loop

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

times 4  dd $

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

但是$块在%rep之前展开,所以

$

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

0

手动编码跳跃位移:

正常直接call is E8 rel32,相对于指令的 end 计算位移。 (即,在执行指令时相对于EIP / RIP,因为RIP保存下一条指令的地址.RIP相对寻址模式也是这样工作的。)dword是4字节,因此在$ nasm -o foo rep.asm && hd foo 00000000 00 00 00 00 04 00 00 00 08 00 00 00 0c 00 00 00 伪 - 使用一个操作数的指令,结尾的地址是dd。您当然可以在 next 行上添加标签并使用它。

$+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

如果偏移错误,objdump会将符号部分设为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. 。前2个调用指令中的相对位移相差5,因为func+8长度为5个字节且它们具有相同的实际目标,相同的相对位移。请注意,反汇编程序负责将rel32添加到调用指令的地址,以显示绝对目标地址。

您可以使用call rel32对短db target - ($+1)jmp的偏移进行编码。 (但要注意:jcc不对,因为当你将操作码和置换作为同一db 0xEB, target - ($+1)伪的多个参数时,指令的结尾实际为$+2指令。)

相关: db是当前部分的开头 ,因此$$是您当前部分的距离。但这仅在当前文件中,因此链接两个放置$ - $$内容的文件与同一源文件中有两个.rodata块不同。请参阅What's the real meaning of $$ in nasm

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