为什么 rax 和 rdi 在这种情况下工作相同? [英] Why does rax and rdi work the same in this situation?
问题描述
我已经制作了这个代码:
全局字符串;int strlen(const char *string);力量:异或 rcx, rcx重试:cmp 字节 [rdi + rcx], 0结果包括 rcxjmp重试结果:mov rax, rcx回复
这就是我测试它的方式:
#include int main(int argc, char **argv){char* bob = argv[1];printf("%i\n", strlen(bob));返回0;}
这是一个有效的 strlen,这里没问题,但我注意到我可以在没有它的情况下为 rax
切换重试块第一行中的 rdi
改变任何东西,我不知道这是否是正常行为.我应该保留哪些值?
只是运气不好.
GCC 8,未经优化,使用 rax
作为中间位置将 argv[1]
移动到 bob
并将后者移动到 strlen
的第一个参数中:
推送 rbpmov rbp, rsp子 rsp, 32mov DWORD PTR [rbp-20], edi ;argcmov QWORD PTR [rbp-32], rsi ;argvmov rax, QWORD PTR [rbp-32] ;argvmov rax, QWORD PTR [rax+8] ;argv[1]mov QWORD PTR [rbp-8], rax;bob = argv[1]mov rax, QWORD PTR [rbp-8]mov rdi, rax调用 strlen ;strlen(bob)mov esi, eaxmov edi,偏移平面:.LC0移动轴,0调用 printf移动轴,0离开回复
这只是运气不好,这不是记录在案的行为,事实上如果您使用字符串文字会失败一个>:
printf("%i\n", strlen("bob"));mov edi,偏移平面:.LC1call strlen ;这里没有RAXmov esi, eaxmov edi,偏移平面:.LC0移动轴,0调用 printf
指定如何将参数传递给函数的文档是您的操作系统 ABI,在此答案中阅读更多内容.><小时>
当优化被禁用时,GCC 生成大量使用寄存器的愚蠢"代码,这简化了调试(GCC 引擎和编译的程序)并且本质上模仿了初学者:首先从内存中读取变量,然后放入第一个空闲寄存器(解决了一个问题),然后将其复制到正确的寄存器中(另一个没有了),最后进行调用.
GCC 刚刚选择了第一个空闲寄存器,在这个简单的程序中没有寄存器压力并且 rax
总是被选择.
I have made this code :
global strlen
; int strlen(const char *string);
strlen:
xor rcx, rcx
retry:
cmp byte [rdi + rcx], 0
je result
inc rcx
jmp retry
result:
mov rax, rcx
ret
And this is how I test it :
#include <stdio.h>
int main(int argc, char **argv)
{
char* bob = argv[1];
printf("%i\n", strlen(bob));
return 0;
}
This is a working strlen, no problem here but I've noticed that I can switch the rdi
in the first line of the retry block for a rax
without it changing anything, I don't know if this is normal behavior.
which of those values should I keep ?
It's just bad luck.
GCC 8, without optimisations, uses rax
as an intermediary location to move argv[1]
to bob
and to move the latter into the first parameter of strlen
:
push rbp
mov rbp, rsp
sub rsp, 32
mov DWORD PTR [rbp-20], edi ;argc
mov QWORD PTR [rbp-32], rsi ;argv
mov rax, QWORD PTR [rbp-32] ;argv
mov rax, QWORD PTR [rax+8] ;argv[1]
mov QWORD PTR [rbp-8], rax ;bob = argv[1]
mov rax, QWORD PTR [rbp-8]
mov rdi, rax
call strlen ;strlen(bob)
mov esi, eax
mov edi, OFFSET FLAT:.LC0
mov eax, 0
call printf
mov eax, 0
leave
ret
This is just bad luck, it's not a documented behaviour, in fact it fails if you use a string literal:
printf("%i\n", strlen("bob"));
mov edi, OFFSET FLAT:.LC1
call strlen ;No RAX here
mov esi, eax
mov edi, OFFSET FLAT:.LC0
mov eax, 0
call printf
The document specifying how to parameters are passed to function is your OS ABI, read more in this answer.
GCC generates "dumb" code that uses the registers a lot when the optimisations are disabled, this eases the debugging (both of the GCC engine and the program compiled) and essentially mimics a beginners: first the variable is read from memory and put in the first free register (one problem solved), then it is copied in the right register (another one gone) and finally the call is made.
GCC just picked up the first free register, in this simple program there is no registers pressure and rax
is always picked up.
这篇关于为什么 rax 和 rdi 在这种情况下工作相同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!