x86汇编代码混淆
x86 assembly code confusion
我们刚刚开始关于汇编的话题,我已经在这个问题上停留了最长的时间。鉴于以下情况,我必须将汇编代码转换为 C 代码:
C代码:
int foo(int *a, int n, int val) {
int i;
for (i = _________; ____________________________ ; i =___________) {
;
}
return i;
}
程序集:
// what I've gathered so far
foo()
:
foo:
pushl %ebp
movl %esp,%ebp
movl 8(%ebp),%ecx // ecx: a
movl 16(%ebp),%edx // edx: val
movl 12(%ebp),%eax // eax: n
decl %eax // n = n--
js .L3 // if n < 0 goto done
.L7: // loop
cmpl %edx,(%ecx,%eax,4) // I don't understand how you would compute the
// address for (%ecx,%eax,4) I know it would be %ecx + %eax*4 = %ecx + eax << 2
jne .L3 // if (%ecx, %eax, 4) != val goto done (?)
decl %eax // n = n--
jns .L7 // if (n >= 0) jump to loop
.L3: // done
movl %ebp,%esp
popl %ebp
ret
我不知道如何弄清楚我正在初始化什么以及循环体是什么。我假设 i = n 因为 n 作为更新。似乎有两个条件,一个是 n > 0,另一个是 cmpl 行。如果我对代码的理解不正确,请纠正我,非常感谢有关此问题的任何线索。
我本可以做一些偏离 1 的错误,但基本上是这样的:
int foo(int *a, int n, int val) {
int i;
for (i = n - 1; i >= 0 && a[i] == val; i = i - 1) {
;
}
return i;
}
i
是%eax
寄存器;它从 n - 1
循环到 0。 cmpl
索引访问 (%ecx,%eax,4)
以字节为单位寻址 - 这相当于 a[i]
,因为 ia32 上 int
的大小是4字节。因此寻址的 4 个字节与 val
.
进行比较
隐式返回%eax
。
另请注意,js
表示 < 0
,而 jns
>= 0
.
另一种写法:
i = n;
i --; // decl %eax
if (i < 0) {
goto L3; // js .L3
}
L7:
if (a[i] != val) // cmpl %edx,(%ecx,%eax,4)
goto L3; // jne .L3
i --; // decl %eax
if (i >= 0)
goto L7; // jns .L7
L3:
return i;
使用预处理器的替代方案:
#define _________ n - 1
#define ____________________________ i >= 0 && a[i] == val
#define ___________ i + 1
int foo(int *a, int n, int val) {
int i;
for (i = _________; ____________________________ ; i =___________) {
;
}
return i;
}
当然,您只能将其用于娱乐或取笑新程序员;-)
我们刚刚开始关于汇编的话题,我已经在这个问题上停留了最长的时间。鉴于以下情况,我必须将汇编代码转换为 C 代码:
C代码:
int foo(int *a, int n, int val) {
int i;
for (i = _________; ____________________________ ; i =___________) {
;
}
return i;
}
程序集:
// what I've gathered so far
foo()
:
foo:
pushl %ebp
movl %esp,%ebp
movl 8(%ebp),%ecx // ecx: a
movl 16(%ebp),%edx // edx: val
movl 12(%ebp),%eax // eax: n
decl %eax // n = n--
js .L3 // if n < 0 goto done
.L7: // loop
cmpl %edx,(%ecx,%eax,4) // I don't understand how you would compute the
// address for (%ecx,%eax,4) I know it would be %ecx + %eax*4 = %ecx + eax << 2
jne .L3 // if (%ecx, %eax, 4) != val goto done (?)
decl %eax // n = n--
jns .L7 // if (n >= 0) jump to loop
.L3: // done
movl %ebp,%esp
popl %ebp
ret
我不知道如何弄清楚我正在初始化什么以及循环体是什么。我假设 i = n 因为 n 作为更新。似乎有两个条件,一个是 n > 0,另一个是 cmpl 行。如果我对代码的理解不正确,请纠正我,非常感谢有关此问题的任何线索。
我本可以做一些偏离 1 的错误,但基本上是这样的:
int foo(int *a, int n, int val) {
int i;
for (i = n - 1; i >= 0 && a[i] == val; i = i - 1) {
;
}
return i;
}
i
是%eax
寄存器;它从 n - 1
循环到 0。 cmpl
索引访问 (%ecx,%eax,4)
以字节为单位寻址 - 这相当于 a[i]
,因为 ia32 上 int
的大小是4字节。因此寻址的 4 个字节与 val
.
隐式返回%eax
。
另请注意,js
表示 < 0
,而 jns
>= 0
.
另一种写法:
i = n;
i --; // decl %eax
if (i < 0) {
goto L3; // js .L3
}
L7:
if (a[i] != val) // cmpl %edx,(%ecx,%eax,4)
goto L3; // jne .L3
i --; // decl %eax
if (i >= 0)
goto L7; // jns .L7
L3:
return i;
使用预处理器的替代方案:
#define _________ n - 1
#define ____________________________ i >= 0 && a[i] == val
#define ___________ i + 1
int foo(int *a, int n, int val) {
int i;
for (i = _________; ____________________________ ; i =___________) {
;
}
return i;
}
当然,您只能将其用于娱乐或取笑新程序员;-)