gpt4 book ai didi

c - 深入 assembly

转载 作者:太空宇宙 更新时间:2023-11-04 03:05:20 28 4
gpt4 key购买 nike

c 中的函数:

PHPAPI char *php_pcre_replace(char *regex,   int regex_len,
char *subject, int subject_len,
zval *replace_val, int is_callable_replace,
int *result_len, int limit, int *replace_count TSRMLS_DC)
{
pcre_cache_entry *pce; /* Compiled regular expression */

/* Compile regex or get it from cache. */
if ((pce = pcre_get_compiled_regex_cache(regex, regex_len TSRMLS_CC)) == NULL) {
return NULL;
}

....
}

它的组装:

php5ts!php_pcre_replace:
1015db70 8b442408 mov eax,dword ptr [esp+8]
1015db74 8b4c2404 mov ecx,dword ptr [esp+4]
1015db78 56 push esi
1015db79 8b74242c mov esi,dword ptr [esp+2Ch]
1015db7d 56 push esi
1015db7e 50 push eax
1015db7f 51 push ecx
1015db80 e8cbeaffff call php5ts!pcre_get_compiled_regex_cache (1015c650)
1015db85 83c40c add esp,0Ch
1015db88 85c0 test eax,eax
1015db8a 7502 jne php5ts!php_pcre_replace+0x1e (1015db8e)

php5ts!php_pcre_replace+0x1c:
1015db8c 5e pop esi
1015db8d c3 ret

c函数调用pcre_get_compiled_regex_cache(regex, regex_len TSRMLS_CC)对应1015db7d~1015db80将3个参数入栈调用。

但我的疑问是,在这么多的寄存器中,编译器是如何决定使用eaxecxesi的(这是特殊的,因为它在使用前已经恢复了,为什么?)作为携带到堆栈的中间体?

c 中一定有一些隐藏的指示告诉编译器这样做,对吧?

最佳答案

不,没有隐藏的指示。

这是生成 80x86 指令的典型策略,被许多编译器实现使用,C 和其他。例如,1980 年代的英特尔 Fortran-77 编译器在启用优化时会做同样的事情。

优先使用 eaxecx 可能是避免使用 esiedi 的产物,因为这些寄存器不能直接用于加载字节操作数。

为什么不是 ebxedx?好吧,许多代码生成器更喜欢在评估复杂结构评估时保存中间指针,也就是说,根本没有太多理由。编译器只是寻找两个可用的寄存器来使用并覆盖它们以缓冲值。

为什么不像这样重用 eax 呢?:

   push    esi
mov eax,dword ptr [esp+2Ch]
push eax
mov eax,dword ptr [esp+8]
push eax
mov eax,dword ptr [esp+4]
push eax

因为这会导致流水线停止等待 eax 完成之前的内存周期,自 80586 以来的 80x86 秒(可能是 80486——太久远了,我无法确定)。

x86 架构是一个奇怪的野兽。每个寄存器,虽然被 Intel 提升为“通用”,但都有其怪癖(例如,cx/ecxloop 指令相关联,并且 eax:edx 与乘法指令相关联)。这与优化执行以避免缓存未命中和管道停顿的特殊方法相结合,通常会导致代码生成器生成难以理解的代码,而代码生成器会将所有这些因素都考虑在内。

关于c - 深入 assembly ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6079543/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com