You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Delphi中跨内联汇编块访问已声明的标签?

解决Delphi内联汇编跨块访问标签的问题

汇编语言通常比高级语言更快。比如我在Delphi里测试过一个重复10亿次的空循环:Delphi编写的循环耗时60亿个x64 CPU周期,而汇编实现的相同循环仅耗时20亿个周期。

当需要高性能操作时,我会优先用汇编编码,但有时不得不插入高级语言代码。我尝试把汇编块拆分,中间执行高级代码后再回到汇编循环,结果报错了。

测试代码如下:

program Test;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  Sysutils;

var
  f, i: int64;

begin
  asm
    rdtsc
    mov dword ptr f[0], eax
    mov dword ptr f[4], eax
    mov eax, 1000
    @loop:
    sub eax, 1
  end;
  WriteLn('Hello, World!');
  asm;
    jnz @loop
    rdtsc
    mov dword ptr i[0], eax
    mov dword ptr i[4], eax
  end;
  ReadLn; // Allow user to read output
end.

预期是打印1000次Hello, World!,但编译时报错:

E2003: Undeclared identifier: '@loop' at line 23 (23:1)

问题本质是:Delphi的内联汇编中,单个@开头的局部标签仅在当前asm块内有效,无法跨块访问。

解决方案

利用Delphi的全局标签机制,在Pascal代码中声明全局标签,即可在多个汇编块之间共享引用:

修改后的代码:

program Test;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  Sysutils;

// 声明全局Pascal标签
label
  loop_label;

var
  f, i: int64;

begin
  asm
    rdtsc
    mov dword ptr f[0], eax
    mov dword ptr f[4], edx  // 修正rdtsc的使用:高32位存在edx中
    mov eax, 1000
    @loop_label:  // 在汇编中用@+标签名定义全局标签的位置
    sub eax, 1
  end;
  WriteLn('Hello, World!');
  asm
    jnz @loop_label  // 跨汇编块引用全局标签
    rdtsc
    mov dword ptr i[0], eax
    mov dword ptr i[4], edx  // 同样修正此处的rdtsc存储错误
  end;
  ReadLn;
end.

说明

  • 在Pascal代码段中用label关键字声明全局标签,标签名可自定义;
  • 在汇编块中定义标签时,需要在标签名前加@前缀,格式为@标签名:;
  • 在其他汇编块中引用该标签时,同样使用@标签名的格式,即可实现跨块访问;
  • 顺便修正了原代码中rdtsc指令的使用错误:该指令将时间戳低32位存入eax,高32位存入edx,原代码两次存储eax会导致时间戳数据错误。

内容的提问来源于stack exchange,提问作者JOrE

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 23:50:20