程序集 - 为什么 strtol 会破坏 %rcx 寄存器?
Assembly - Why strtol clobbers %rcx register?
上下文:
Linux64.
GCC 4.8.2(带 -O3 -march=native)
我左手下的x86_64 abi,在第21页打开。
C代码:
int main (int argc, char ** argv) {
printf("%d %s\n", atoi(argv[2]),argv[1] );
}
汇编代码:
(注意编译器自己用strtol替换了atoi)
...
movl , %edx
movq 16(%rsi), %rdi
movq 8(%rsi), %rbx
xorl %esi, %esi
call strtol
movl $.LC0, %edi
movq %rbx, %rdx
movl %eax, %esi
xorl %eax, %eax
call printf
xorl %eax, %eax
popq %rbx
...
问题:
%rcx
应保留给第 4 个输入整数参数。
strtol
有3个输入参数(分别是寄存器%rdi
、%rsi
、%rdx
)和一个return、%eax
.
为什么 %rcx
被破坏了?
此代码不会成功:
...
movl , %edx
movq 16(%rsi), %rdi
movq 8(%rsi), %rcx <-- look I replaced with %ecx
xorl %esi, %esi
call strtol
movl $.LC0, %edi
movq %rcx, %rdx <-- look I replaced with %ecx
movl %eax, %esi
xorl %eax, %eax
call printf
xorl %eax, %eax
popq %rbx
...
谢谢
在每个调用约定中,我知道有一些寄存器可以被调用的函数修改,一些不能修改。
在 32 位程序中,ecx 可以被修改,而 ebx 不能被修改 - 或者,更准确地说 - 必须在返回之前重新存储。对于 64 位程序,这条规则似乎是相同的。
确实大部分函数修改了大部分寄存器;出于这个原因,您发布的代码末尾有一个 "popq %rbx",因为函数不能修改 rbx。 rcx 可能会被修改,而 strtol 显然会这样做!
上下文:
Linux64.
GCC 4.8.2(带 -O3 -march=native)
我左手下的x86_64 abi,在第21页打开。
C代码:
int main (int argc, char ** argv) {
printf("%d %s\n", atoi(argv[2]),argv[1] );
}
汇编代码:
(注意编译器自己用strtol替换了atoi)
...
movl , %edx
movq 16(%rsi), %rdi
movq 8(%rsi), %rbx
xorl %esi, %esi
call strtol
movl $.LC0, %edi
movq %rbx, %rdx
movl %eax, %esi
xorl %eax, %eax
call printf
xorl %eax, %eax
popq %rbx
...
问题:
%rcx
应保留给第 4 个输入整数参数。
strtol
有3个输入参数(分别是寄存器%rdi
、%rsi
、%rdx
)和一个return、%eax
.
为什么 %rcx
被破坏了?
此代码不会成功:
...
movl , %edx
movq 16(%rsi), %rdi
movq 8(%rsi), %rcx <-- look I replaced with %ecx
xorl %esi, %esi
call strtol
movl $.LC0, %edi
movq %rcx, %rdx <-- look I replaced with %ecx
movl %eax, %esi
xorl %eax, %eax
call printf
xorl %eax, %eax
popq %rbx
...
谢谢
在每个调用约定中,我知道有一些寄存器可以被调用的函数修改,一些不能修改。
在 32 位程序中,ecx 可以被修改,而 ebx 不能被修改 - 或者,更准确地说 - 必须在返回之前重新存储。对于 64 位程序,这条规则似乎是相同的。
确实大部分函数修改了大部分寄存器;出于这个原因,您发布的代码末尾有一个 "popq %rbx",因为函数不能修改 rbx。 rcx 可能会被修改,而 strtol 显然会这样做!