Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 如何在地址计算中使用标签_Delphi_Assembly_X86 64 - Fatal编程技术网

Delphi 如何在地址计算中使用标签

Delphi 如何在地址计算中使用标签,delphi,assembly,x86-64,Delphi,Assembly,X86 64,我有以下内联汇编代码片段: procedure Foo; asm //..... @partialloop: shr rdx,1 //every instruction is 4 bytes lea r11,[rip + (7*4)+(@partial-@offset)] @offset: sub r11,rdx xor r8,r8 jmp r11

我有以下内联汇编代码片段:

procedure Foo;
asm
//.....
@partialloop: shr rdx,1              //every instruction is 4 bytes
              lea r11,[rip + (7*4)+(@partial-@offset)]
@offset:      sub r11,rdx
              xor r8,r8
              jmp r11                //do a partial loop
@loop64:      mov [rcx],rax
@partial:     mov [rcx+08H],rax
//....
end;
编译器不接受以下语法:

E2105内联汇编程序语法错误

创建偏移量、ptr或@的使用没有帮助


我需要使用什么语法来进行编译?

它不起作用,因为不需要这个构造。 编译器不允许这些构造以防止代码中出现逻辑错误

以下代码段实际上是正确的:

@partialloop: shr rdx,1              //every instruction is 4 bytes
              lea r11,[rip + @partial + (7*4)] //r11= end of the loop
@offset:      sub r11,rdx            //step back as needed
              xor r8,r8              //only do a single iteration
              jmp r11                //do a partial loop
@loop64:      mov [rcx],rax
@partial:     mov [rcx+08H],rax
//....
end;
表达式:[rip+@partial+4*7]的计算结果如下:

在执行此指令后撕开IP。 @部分撕裂和该标签之间的距离。 7*4除其他外的附加偏移量 在计算中使用@标签始终会产生偏移量,而不是绝对值。jmp@标签总是转换为相对跳转,而不是绝对jmp

如果编译器允许,原始语句当然也是正确的:

lea r11,[rip + (7*4)+(@partial-@offset)]
r11 = rip($6B74FB) + 28 + @partial($0C) - @offset(0)  

但是因为RIP已经等于@offset的绝对地址,所以没有必要包含它两次

它不起作用,因为不需要这种构造。 编译器不允许这些构造以防止代码中出现逻辑错误

以下代码段实际上是正确的:

@partialloop: shr rdx,1              //every instruction is 4 bytes
              lea r11,[rip + @partial + (7*4)] //r11= end of the loop
@offset:      sub r11,rdx            //step back as needed
              xor r8,r8              //only do a single iteration
              jmp r11                //do a partial loop
@loop64:      mov [rcx],rax
@partial:     mov [rcx+08H],rax
//....
end;
表达式:[rip+@partial+4*7]的计算结果如下:

在执行此指令后撕开IP。 @部分撕裂和该标签之间的距离。 7*4除其他外的附加偏移量 在计算中使用@标签始终会产生偏移量,而不是绝对值。jmp@标签总是转换为相对跳转,而不是绝对jmp

如果编译器允许,原始语句当然也是正确的:

lea r11,[rip + (7*4)+(@partial-@offset)]
r11 = rip($6B74FB) + 28 + @partial($0C) - @offset(0)  

但是因为RIP已经等于@offset的绝对地址,所以没有必要包含它两次

标签地址是可重新定位的,并且是可用的

可重定位表达式表示在链接时需要重定位的值,而绝对表达式表示不需要重定位的值。通常,引用标签、变量、过程或函数的表达式是可重定位的,因为这些符号的最终地址在编译时是未知的

进一步:

内置汇编程序允许您对绝对值执行任何操作,但它将对可重定位值的操作限制为常量的加减

可以将标签地址可重定位值添加到常量,但不能从常量中减去可重定位值。也不能同时添加两个可重定位的值


简言之,这是不可能做到的

标签地址是可重新定位的,并且是可用的

可重定位表达式表示在链接时需要重定位的值,而绝对表达式表示不需要重定位的值。通常,引用标签、变量、过程或函数的表达式是可重定位的,因为这些符号的最终地址在编译时是未知的

进一步:

内置汇编程序允许您对绝对值执行任何操作,但它将对可重定位值的操作限制为常量的加减

可以将标签地址可重定位值添加到常量,但不能从常量中减去可重定位值。也不能同时添加两个可重定位的值


简言之,这是不可能做到的

你说的是链接时间数学,这是不可能的。在常规程序集(如NASM)中可能出现的情况是,表达式涉及当前asm输入文件中定义的标签之间的差异。最终地址直到链接时才知道,但汇编器知道其差异。e、 g.mov ecx,label2-在我刚刚用yasm做的测试中,label1组装成b9 22 00 mov ecx,0x22。汇编程序知道当前编译单元的确切内存布局;它的工作是将字节组装到输出文件中,因此它必须知道这一点@PeterCordes是的,在这种情况下,在一个连续的块中,应该可以确定这两个标签之间的常量差。然而,Delphi编译器通常将这些值视为可重新定位的,并且不允许这样的操作。这不是NASM,也不是YASM——规则是不同的。谁知道编译器作者有什么保留意见?我不知道。@PeterCordes可以想象,编译器希望保留重新排列代码布局的自由。例如,跟随jmp的标签没有理由跟随它在内存中的前一条指令,因为执行永远不应该以增量的方式通过—编译器可能出于任何原因想要重新定位该代码段。魔鬼代言人,当然,我没有证据表明这确实发生了,但似乎规则允许它可能发生。我只是指出,这不是根本不可能的,只是

为简单起见,语言规则不允许。他们大概不想让标签在当前编译单元中定义与否有任何关系。我还认为一些读者可能有兴趣了解它在NASM中的工作原理。我很高兴你删除了关于不知道内存布局的措辞,因为这并不能解释这种情况。re:重新排列代码:你是说在内联asm块中?这似乎极不可能。您可以将一个标签地址放入寄存器中,并根据需要对其进行偏移,以计算跳转到大小相等的指令序列的中间。语法限制并不会阻止您了解指令将如何组装和执行疯狂的操作。除非有很多其他规则禁止内联asm中的很多内容,否则编译器无法在不理解的情况下将内联asm安全地分解为单独的块。你说的是链接时间数学,这是不可能的。在常规程序集(如NASM)中可能出现的情况是,表达式涉及当前asm输入文件中定义的标签之间的差异。最终地址直到链接时才知道,但汇编器知道其差异。e、 g.mov ecx,label2-在我刚刚用yasm做的测试中,label1组装成b9 22 00 mov ecx,0x22。汇编程序知道当前编译单元的确切内存布局;它的工作是将字节组装到输出文件中,因此它必须知道这一点@PeterCordes是的,在这种情况下,在一个连续的块中,应该可以确定这两个标签之间的常量差。然而,Delphi编译器通常将这些值视为可重新定位的,并且不允许这样的操作。这不是NASM,也不是YASM——规则是不同的。谁知道编译器作者有什么保留意见?我不知道。@PeterCordes可以想象,编译器希望保留重新排列代码布局的自由。例如,跟随jmp的标签没有理由跟随它在内存中的前一条指令,因为执行永远不应该以增量的方式通过—编译器可能出于任何原因想要重新定位该代码段。魔鬼代言人,当然,我没有证据表明这确实发生了,但似乎规则允许它潜在地发生。我只是指出,这并不是根本不可能的,只是为了简单起见,语言规则不允许。他们大概不想让标签在当前编译单元中定义与否有任何关系。我还认为一些读者可能有兴趣了解它在NASM中的工作原理。我很高兴你删除了关于不知道内存布局的措辞,因为这并不能解释这种情况。re:重新排列代码:你是说在内联asm块中?这似乎极不可能。您可以将一个标签地址放入寄存器中,并根据需要对其进行偏移,以计算跳转到大小相等的指令序列的中间。语法限制并不会阻止您了解指令将如何组装和执行疯狂的操作。除非有许多其他规则禁止内联asm中的大量内容,否则编译器无法在不理解的情况下将内联asm安全地分解为单独的块。RIP relative的语法在不同风格的asm中经常混淆/不明确,原因请解释。在NASM语法中,标签只是一个符号,其值恰好是一个地址,而不是使用myvar eq 0x123定义的内容。因此,写入[rip+标签]使用绝对地址作为偏移量。在NASM语法中,您可以编写[rel label+7*4],如果使用默认的rel指令,则只需编写[label+7*4]。您可能需要编写[rip+@partial+7*4]来更清楚地说明它只是一个标签的偏移量,而不是地址数学。说到地址数学,正如我对J的答案所评论的,NASM在减去非外部标签方面没有问题。Delphi是否允许您编写mov ecx、@partial-@offset?该语言必须根据标签是否在当前编译单元中定义来接受/拒绝此类表达式,这可能是因为他们认为标签更容易混淆,而不是有用。@PeterCordes,不,不是这样。E2105内联汇编程序语法error@PeterCordes不,没有。根据我在回答中的引用,规则非常明确。RIP relative的语法在不同的ASM风格中经常混淆/模棱两可,原因请解释。在NASM语法中,标签只是一个符号,其值恰好是一个地址,而不是使用myvar eq 0x123定义的内容。因此,写入[rip+标签]使用绝对地址作为偏移量。在NASM语法中,您可以编写[rel label+7*4],如果使用默认的rel指令,则只需编写[label+7*4]。你可能想写[rip+@partial+7*4]来更清楚地说明它只是一个标签的偏移量,而不是地址数学
em减去非外部标签。Delphi是否允许您编写mov ecx、@partial-@offset?该语言必须根据标签是否在当前编译单元中定义来接受/拒绝此类表达式,这可能是因为他们认为标签更容易混淆,而不是有用。@PeterCordes,不,不是这样。E2105内联汇编程序语法error@PeterCordes不,没有。根据我答案中的参考资料,规则非常清楚。手工组装并用db语句SNO编写。如果你想让它运行得更快,为什么不呢?哦,你的意思是在delphi之外使用Masm,然后复制粘贴。类似的东西就可以了。手工组装它,然后用db语句编写它。如果你想让它运行得更快,为什么不呢?哦,你的意思是在delphi之外使用Masm,然后复制粘贴。类似的东西就可以了。