NASM 汇编程序:如何使用 EQU 对齐值,以获取标签后的下一个对齐边界而无需实际填充
NASM assembler : How to align values using EQU, to get the next alignment boundary after a label without actually padding
我想计算对齐地址。
'label' 应对齐 4 字节边界。
bits 32
mov eax, label
end: ; here is the end of program
align 4
label:
此 nasm 代码输出 8 个字节。
$ nasm -f bin test.nasm -o test.o
$ ndisasm -o 0x0 -b 32 test.o
00000000 B808000000 mov eax,0x8
00000005 90 nop
00000006 90 nop
00000007 90 nop
但实际上程序大小是5个字节。
是否可以在不扩展程序大小的情况下定义标签?
我希望将 'label' 定义为值 8,test.o 的文件大小将为 5.
我还尝试使用“$”变量计算地址,如下所示。
bits 32
mov eax, label
end: ; here is the end of program
label equ ( ($+3) & ~3 )
但是nasm不接受这个表达式。
$ nasm -f bin test.nasm -o test.o
test.nasm:4: error: `&' operator may only be applied to scalar values
这是意料之中的事情。 end
的绝对地址通常在链接之后才知道,因此地址的任何转换都必须由链接器计算。大多数系统上的链接器可以执行一些有限的运算(主要是加法和减法),汇编器通过在重定位 table 中插入适当的条目来请求这些运算。这就是为什么你可以做 mov eax, label+17
或 mov eax, label2-label1
之类的事情。但它不会像 &
那样进行完全任意的运算,并且没有重定位来对这样的表达式进行编码。
(我想既然我们在这里输出二进制,汇编程序对绝对地址有更多的了解;但它可能不是为了利用这种特殊情况而设计的。)
所以我认为你在这里不走运。您可以在 label
之前忍受额外的填充字节,或者您可以在运行时进行对齐,例如
mov eax, label+3
and eax, ~3
你应该只使用 align 4.
equ 在汇编时计算。所以在链接后它无法知道 $ 在运行时的对齐方式。此外,它给你的错误,
error: `&' operator may only be applied to scalar values
那是因为 ($+3) 不是标量值。连组装的时候都无法评价。
另一方面,align 4 会将对齐要求传递到目标文件中,链接器将正确对齐 label。如果你想验证这是正确的,你可以检查最终 executable.
上的名单(符号 table)
正如 Nate 所解释的那样,NASM 不会对地址进行任意数学运算,即使在制作平面二进制文件而不是仅仅将重定位写入 ELF 或 COFF 时也是如此 .o
/ .obj
.
NASM 在制作平面二进制文件时连接部分,但 不会为 .bss
.
发出任何字节
这个程序汇编成你想要的5字节机器码:
bits 32
mov eax, label
end: ; here is the end of program
section .bss
align 4 ; in the BSS where they don't end up in the file
label:
$ nasm -fbin foo.asm
$ ll foo
-rwxr-xr-x 1 peter peter 5 Dec 30 15:16 foo
$ ndisasm -b32 foo
00000000 B808000000 mov eax,0x8
我有点惊讶它起作用了; IDK,如果它是官方支持的,或者如果我很幸运。
它也适用于 YASM。
在 FASM 中,即使没有 section .bss
指令,它似乎也只是跳过了在文件末尾写入对齐填充。 (所以我得到了一个 6 字节的文件,因为我没有为 32 位平面二进制输出查找正确的 FASM 指令,所以它使用 66
操作数大小前缀来编码 mov eax, 8
16 位模式。)
我想计算对齐地址。 'label' 应对齐 4 字节边界。
bits 32
mov eax, label
end: ; here is the end of program
align 4
label:
此 nasm 代码输出 8 个字节。
$ nasm -f bin test.nasm -o test.o
$ ndisasm -o 0x0 -b 32 test.o
00000000 B808000000 mov eax,0x8
00000005 90 nop
00000006 90 nop
00000007 90 nop
但实际上程序大小是5个字节。 是否可以在不扩展程序大小的情况下定义标签? 我希望将 'label' 定义为值 8,test.o 的文件大小将为 5.
我还尝试使用“$”变量计算地址,如下所示。
bits 32
mov eax, label
end: ; here is the end of program
label equ ( ($+3) & ~3 )
但是nasm不接受这个表达式。
$ nasm -f bin test.nasm -o test.o
test.nasm:4: error: `&' operator may only be applied to scalar values
这是意料之中的事情。 end
的绝对地址通常在链接之后才知道,因此地址的任何转换都必须由链接器计算。大多数系统上的链接器可以执行一些有限的运算(主要是加法和减法),汇编器通过在重定位 table 中插入适当的条目来请求这些运算。这就是为什么你可以做 mov eax, label+17
或 mov eax, label2-label1
之类的事情。但它不会像 &
那样进行完全任意的运算,并且没有重定位来对这样的表达式进行编码。
(我想既然我们在这里输出二进制,汇编程序对绝对地址有更多的了解;但它可能不是为了利用这种特殊情况而设计的。)
所以我认为你在这里不走运。您可以在 label
之前忍受额外的填充字节,或者您可以在运行时进行对齐,例如
mov eax, label+3
and eax, ~3
你应该只使用 align 4.
equ 在汇编时计算。所以在链接后它无法知道 $ 在运行时的对齐方式。此外,它给你的错误,
error: `&' operator may only be applied to scalar values
那是因为 ($+3) 不是标量值。连组装的时候都无法评价。
另一方面,align 4 会将对齐要求传递到目标文件中,链接器将正确对齐 label。如果你想验证这是正确的,你可以检查最终 executable.
上的名单(符号 table)正如 Nate 所解释的那样,NASM 不会对地址进行任意数学运算,即使在制作平面二进制文件而不是仅仅将重定位写入 ELF 或 COFF 时也是如此 .o
/ .obj
.
NASM 在制作平面二进制文件时连接部分,但 不会为 .bss
.
发出任何字节
这个程序汇编成你想要的5字节机器码:
bits 32
mov eax, label
end: ; here is the end of program
section .bss
align 4 ; in the BSS where they don't end up in the file
label:
$ nasm -fbin foo.asm
$ ll foo
-rwxr-xr-x 1 peter peter 5 Dec 30 15:16 foo
$ ndisasm -b32 foo
00000000 B808000000 mov eax,0x8
我有点惊讶它起作用了; IDK,如果它是官方支持的,或者如果我很幸运。
它也适用于 YASM。
在 FASM 中,即使没有 section .bss
指令,它似乎也只是跳过了在文件末尾写入对齐填充。 (所以我得到了一个 6 字节的文件,因为我没有为 32 位平面二进制输出查找正确的 FASM 指令,所以它使用 66
操作数大小前缀来编码 mov eax, 8
16 位模式。)