arr访问绝对地址_Mach-O 64位格式不支持32位绝对地址。NASM访问阵列

首先,与macho64输出格式提防NASM臭虫与64位绝对寻址(NASM 2.13.02+) ,并用在08年2月11日NASM RIP-相对。建议不要使用64位绝对寻址,因此即使对于有缺陷的NASM 2.13.02及更高版本,此答案也应该有效。(错误不会导致此错误,它们会导致在运行时使用错误的地址。)

[data_items + edi*4]是32位寻址模式。即使[data_items + rdi*4]只能使用32位绝对位移,所以它也无法工作。请注意,使用地址作为32位(符号扩展)立即类似cmp rdi, data_items也是一个问题:只mov允许64位立即数。

OS X上的64位代码根本不能使用32位绝对寻址。可执行文件加载在4GiB以上的基址上,因此标签地址只是简单的不适合32位整数,具有零或符号扩展名。RIP相对寻址是最佳/最有效的解决方案,无论您是否需要它与位置无关1。

在NASM中,default rel文件顶部将使所有[]内存操作数更喜欢RIP相对寻址。另请参见NASM手册中的第3.3节“有效地址 ”。default rel                     ; near the top of file; affects later instructionsmy_func:

...

mov   ecx, [data_items]         ; uses the default: RIP-relative

;mov  ecx, [abs data_items]     ; override to absolute [disp32], unusuable

mov   ecx, [rel data_items]     ; explicitly RIP-relative

但只有在没有涉及其他寄存器的情况下才能使用 RIP 相关,因此对于索引静态数组,首先需要在寄存器中获取地址。使用RIP相对lea rsi, [rel data_items]。lea   rsi, [data_items]    ; can be outside the loop

...

mov   eax, [rsi + rdi*4]

或者您可以add rsi, 4在循环内部使用更简单的寻址模式mov eax, [rsi]。

请注意,这mov rsi, data_items将用于将地址输入寄存器,但您不希望这样,因为它的效率较低。

从技术上讲,数组+ -2GiB内的任何地址都可以工作,所以如果你有多个数组,你可以相对于一个公共基地址寻址其他数组,只用一个指针绑定一个寄存器。例如lea rbx, [arr1]/ ... / mov eax, [rbx + rdi*4 + arr2-arr1]。 相对寻址错误 - Mac 10.10提到Agner Fog的“优化装配”指南有一些数组寻址的例子,包括一个使用__mh_execute_header作为参考点的例子。(该问题中的代码看起来像是另一种尝试将这个32位Linux示例从PGU书籍移植到64位OS X,同时首先学习asm。)

需要注意的是在Linux,与位置相关的可执行文件加载在虚拟地址空间的低32位,所以你会看到像代码mov eax, [array + rdi*4]或mov edi, symbol_name在Linux实例或编译器输出http://gcc.godbolt.org/。 gcc -pie -fPIE将在Linux上制作与位置无关的可执行文件,并且是许多最新发行版的默认设置,但不是Godbolt。

这对MacOS没有帮助,但是我提到它以防任何人对他们在其他操作系统中看到的代码感到困惑,或者为什么AMD64架构师[disp32]在x86-64上根本不允许寻址模式。

而BTW,更喜欢在64位代码中使用64位寻址模式。例如,使用[rsi + rdi*4],而不是[esi + edi*4]。您通常不希望将指针截断为32位,并且需要额外的地址大小前缀才能进行编码。

脚注1: OS X支持64位绝对寻址,但仅限于位置相关的可执行文件(非PIE)。ld: warning: PIE disabled. Absolute addressing (perhaps -mdynamic-no-pic) notallowed in code signed PIE, but used in _main from main.o. To fix this warning,don't compile with -mdynamic-no-pic or link with -Wl,-no_pie

因此,链接器检查是否使用了任何64位绝对重定位,如果是,则禁用创建与位置无关的可执行文件。为了安全起见,PIE可以从ASLR中受益。我认为共享库代码总是必须在OS X上与位置无关; 我不知道是否允许跳转表或其他指针作为数据的情况(即由动态链接器修复),或者如果您不是在制作与位置相关的可执行文件,则需要在运行时初始化它们。

mov r64, imm64更大(10字节)并且不快于lea r64, [RIP_rel32](7字节)。

因此,您可以使用mov rsi, qword data_items而不是相对于RIP运行的LEA,它可以在代码缓存和uop缓存中占用更少的空间。在Sandybridge-family(http://agner.org/optimize/)上,64位immediates也有一个uop-cache fetch惩罚:他们需要2个周期来从uop缓存行而不是1来读取。

x86还有一种mov从64位绝对地址加载/存储的形式,但仅适用于AL / AX / EAX / RAX。见http://felixcloutier.com/x86/MOV.html。你也不想要这个,因为它比它更大而且不快mov eax, [rel foo]。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值