试图将 C 程序翻译成 x86 汇编
Trying to translate C program to reverse a number into x86 assembly
我正在尝试将以下程序转换为 x86 汇编 ( AT&T )。
#include <stdio.h>
int main()
{
int n = 123;
int reverse = 0;
while (n != 0)
{
reverse = reverse * 10;
reverse = reverse + n%10;
n = n/10;
}
printf("%d\n", reverse);
return 0;
}
它应该打印 321。
但是,使用下面的代码,我得到的是 0。
谁能告诉我我在这里做错了什么?
(我只粘贴了下面的相关部分。我确信初始化和打印工作正常。你可以看到 the whole thing here)
movl 3, %esi # int n
movl [=11=], %edi # int reverse
movl , %ebx # divisor
L1: # while n != 0
cmpl [=11=], %esi
je L2
# reverse = reverse * 10
imul , %edi
# reverse = reverse + n % 10
movl [=11=], %edx
movl %edi, %eax
idivl %ebx
addl %edx, %edi
# n = n / 10
movl %esi, %eax
movl [=11=], %edx
idivl %ebx
movl %eax, %esi
jmp L1
L2: # end while
movl %edi, %eax
也许我还没有完全理解 idivl 命令应该做什么。我知道它将 %edx:%eax 除以 %ebx,并将商存储在 %eax 中,将余数存储在 %edx 中。
# reverse = reverse + n % 10
movl [=10=], %edx
movl %edi, %eax ; <--- here
%edi
不是n
,根据上面的评论:
movl 3, %esi # int n
所以,它应该使用 %esi
,即 movl %esi, %eax
。
有时很高兴看到编译器生成的内容
int reverse(int x)
{
int r = 0;
while (x != 0)
{
r = r * 10;
r = r + x%10;
x = x/10;
}
return r;
}
和最短版本:
reverse:
xor eax, eax
mov esi, 10
.L2:
test edi, edi
je .L5
imul ecx, eax, 10
mov eax, edi
cdq
idiv esi
mov edi, eax
lea eax, [rdx+rcx]
jmp .L2
.L5:
ret
或最快的:
reverse:
xor eax, eax
test edi, edi
je .L4
mov esi, 1717986919
.L3:
lea ecx, [rax+rax*4]
mov eax, edi
imul esi
mov eax, edi
sar eax, 31
sar edx, 2
sub edx, eax
lea eax, [rdx+rdx*4]
add eax, eax
sub edi, eax
test edx, edx
lea eax, [rdi+rcx*2]
mov edi, edx
jne .L3
rep ret
.L4:
rep ret
如您所见,编译器与 99.99% 的编码器
相同good/better
我正在尝试将以下程序转换为 x86 汇编 ( AT&T )。
#include <stdio.h>
int main()
{
int n = 123;
int reverse = 0;
while (n != 0)
{
reverse = reverse * 10;
reverse = reverse + n%10;
n = n/10;
}
printf("%d\n", reverse);
return 0;
}
它应该打印 321。
但是,使用下面的代码,我得到的是 0。 谁能告诉我我在这里做错了什么? (我只粘贴了下面的相关部分。我确信初始化和打印工作正常。你可以看到 the whole thing here)
movl 3, %esi # int n
movl [=11=], %edi # int reverse
movl , %ebx # divisor
L1: # while n != 0
cmpl [=11=], %esi
je L2
# reverse = reverse * 10
imul , %edi
# reverse = reverse + n % 10
movl [=11=], %edx
movl %edi, %eax
idivl %ebx
addl %edx, %edi
# n = n / 10
movl %esi, %eax
movl [=11=], %edx
idivl %ebx
movl %eax, %esi
jmp L1
L2: # end while
movl %edi, %eax
也许我还没有完全理解 idivl 命令应该做什么。我知道它将 %edx:%eax 除以 %ebx,并将商存储在 %eax 中,将余数存储在 %edx 中。
# reverse = reverse + n % 10
movl [=10=], %edx
movl %edi, %eax ; <--- here
%edi
不是n
,根据上面的评论:
movl 3, %esi # int n
所以,它应该使用 %esi
,即 movl %esi, %eax
。
有时很高兴看到编译器生成的内容
int reverse(int x)
{
int r = 0;
while (x != 0)
{
r = r * 10;
r = r + x%10;
x = x/10;
}
return r;
}
和最短版本:
reverse:
xor eax, eax
mov esi, 10
.L2:
test edi, edi
je .L5
imul ecx, eax, 10
mov eax, edi
cdq
idiv esi
mov edi, eax
lea eax, [rdx+rcx]
jmp .L2
.L5:
ret
或最快的:
reverse:
xor eax, eax
test edi, edi
je .L4
mov esi, 1717986919
.L3:
lea ecx, [rax+rax*4]
mov eax, edi
imul esi
mov eax, edi
sar eax, 31
sar edx, 2
sub edx, eax
lea eax, [rdx+rdx*4]
add eax, eax
sub edi, eax
test edx, edx
lea eax, [rdi+rcx*2]
mov edi, edx
jne .L3
rep ret
.L4:
rep ret
如您所见,编译器与 99.99% 的编码器
相同good/better