反汇编 C 函数的 IA32 32 位 AT&T 汇编代码
Disassembling IA32 32 bit AT&T assembly code of a function in C
[已编辑]
有人可以向我解释一下我们如何在这个问题中通过相应的汇编代码的每一行来获取 M 和 N 的值吗?
我总是对 movl array2 部分感到困惑。
M和N是使用#define
定义的常量
#define M <some value>
#define N <some value>
int array1[M][N];
int array2[N][M];
int copy(int i, int j)
{
array1[i][j] = array2[j][i];
}
如果上述代码生成如下汇编代码:我们如何推导出常量M和N的值?
copy:
pushl %ebp
movl %esp, %ebp
pushl %ebx
movl 8(%ebp), %ecx
movl 12(%ebp), %ebx
leal (%ecx, %ecx, 8), %edx
sall , %edx
movl %ebx, %eax
sall , %eax
subl %ebx, %eax
sall , %eax
movl array2(%eax, %ecx, 4), %eax
movl %eax, array1(%edx, %ebx, 4)
popl %ebx
movl %ebp,%esp
popl %ebp
ret
您需要检查程序集的其他部分。比如你把M和N都定义为8,你会在程序集中发现如下
array1:
.zero 256
array2:
.zero 256
因为在我的机器上,int 是 4 个字节,8 乘以 8 是 64。而 64 * 4 = 256。示例程序集可以找到 here。
好的伙计们,经过大量研究,我找到了解决方案。如果我错了请纠正我。
所以逐步完成以下汇编:(为方便添加行号)
M 和 N 是使用#define
定义的常量
int array1[M][N];
int array2[N][M];
int copy(int i, int j)
{
array1[i][j] = array2[j][i];
}
copy:
1 pushl %ebp
2 movl %esp, %ebp
3 pushl %ebx
4 movl 8(%ebp), %ecx
5 movl 12(%ebp), %ebx
6 leal (%ecx, %ecx, 8), %edx
7 sall , %edx
8 movl %ebx, %eax
9 sall , %eax
10 subl %ebx, %eax
11 sall , %eax
12 movl array2(%eax, %ecx, 4), %eax
13 movl %eax, array1(%edx, %ebx, 4)
14 popl %ebx
15 movl %ebp,%esp
16 popl %ebp
ret
将%ebp
压入堆栈
%ebp
指向%esp
将%ebx
压入堆栈
%ecx
等于int i
(数组访问索引)
%ebx
等于int j
(数组访问索引)
%edx
等于 8 * %ecx + %ecx
或 9i
%edx
左二进制移位 2
后等于 36i
%eax
等于 %ebx 或 j
%eax
左二进制移位 4
后等于 16j
%eax
等于 %eax - %ebx = 16j - j = 15j
%eax
左二进制移位 2
后等于 60j
%eax
等于索引为 [4%ecx + %ebx] or [4i + 60j]
的 array2 元素
array1 的索引为 [ 4%ebx + %edx ] or [ 4j + 36i ]
的元素等于 %eax
或 [4i + 60j]
A swap of the two array elements done in 12 and 13 using %eax as
intermediary register.
%ebx
弹出
%esp
的旧值已恢复
%ebp
弹出
现在我们假设 array1[i][j]
的元素访问等于 4Ni + 4j
而array2[j][i]
的元素访问等于4Mj + 4i
。
(每个索引项中的 4 作为 int 是 4 个字节,i、j 是从起始数组位置开始的各个偏移量)
这是真的,因为 C 以行主要形式存储数组。
所以我们得到 M = 15 和 N = 9。
[已编辑] 有人可以向我解释一下我们如何在这个问题中通过相应的汇编代码的每一行来获取 M 和 N 的值吗?
我总是对 movl array2 部分感到困惑。
M和N是使用#define
定义的常量#define M <some value>
#define N <some value>
int array1[M][N];
int array2[N][M];
int copy(int i, int j)
{
array1[i][j] = array2[j][i];
}
如果上述代码生成如下汇编代码:我们如何推导出常量M和N的值?
copy:
pushl %ebp
movl %esp, %ebp
pushl %ebx
movl 8(%ebp), %ecx
movl 12(%ebp), %ebx
leal (%ecx, %ecx, 8), %edx
sall , %edx
movl %ebx, %eax
sall , %eax
subl %ebx, %eax
sall , %eax
movl array2(%eax, %ecx, 4), %eax
movl %eax, array1(%edx, %ebx, 4)
popl %ebx
movl %ebp,%esp
popl %ebp
ret
您需要检查程序集的其他部分。比如你把M和N都定义为8,你会在程序集中发现如下
array1:
.zero 256
array2:
.zero 256
因为在我的机器上,int 是 4 个字节,8 乘以 8 是 64。而 64 * 4 = 256。示例程序集可以找到 here。
好的伙计们,经过大量研究,我找到了解决方案。如果我错了请纠正我。
所以逐步完成以下汇编:(为方便添加行号)
M 和 N 是使用#define
定义的常量int array1[M][N];
int array2[N][M];
int copy(int i, int j)
{
array1[i][j] = array2[j][i];
}
copy:
1 pushl %ebp
2 movl %esp, %ebp
3 pushl %ebx
4 movl 8(%ebp), %ecx
5 movl 12(%ebp), %ebx
6 leal (%ecx, %ecx, 8), %edx
7 sall , %edx
8 movl %ebx, %eax
9 sall , %eax
10 subl %ebx, %eax
11 sall , %eax
12 movl array2(%eax, %ecx, 4), %eax
13 movl %eax, array1(%edx, %ebx, 4)
14 popl %ebx
15 movl %ebp,%esp
16 popl %ebp
ret
将
%ebp
压入堆栈%ebp
指向%esp
将
%ebx
压入堆栈%ecx
等于int i
(数组访问索引)%ebx
等于int j
(数组访问索引)%edx
等于8 * %ecx + %ecx
或9i
%edx
左二进制移位2
后等于 %eax
等于 %ebx 或j
%eax
左二进制移位4
后等于 %eax
等于%eax - %ebx = 16j - j = 15j
%eax
左二进制移位2
后等于 %eax
等于索引为[4%ecx + %ebx] or [4i + 60j]
的 array2 元素
array1 的索引为
[ 4%ebx + %edx ] or [ 4j + 36i ]
的元素等于%eax
或[4i + 60j]
36i
16j
60j
A swap of the two array elements done in 12 and 13 using %eax as intermediary register.
%ebx
弹出%esp
的旧值已恢复%ebp
弹出
现在我们假设 array1[i][j]
的元素访问等于 4Ni + 4j
而array2[j][i]
的元素访问等于4Mj + 4i
。
(每个索引项中的 4 作为 int 是 4 个字节,i、j 是从起始数组位置开始的各个偏移量) 这是真的,因为 C 以行主要形式存储数组。
所以我们得到 M = 15 和 N = 9。