我不明白这是什么问题,因为结果正确,但是其中有些错误,我不明白。
1。这是我必须转换为C的x86代码:
%include "io.inc"
SECTION .data
mask DD 0xffff, 0xff00ff, 0xf0f0f0f, 0x33333333, 0x55555555
SECTION .text
GLOBAL CMAIN
CMAIN:
GET_UDEC 4, EAX
MOV EBX, mask
ADD EBX, 16
MOV ECX, 1
.L:
MOV ESI, DWORD [EBX]
MOV EDI, ESI
NOT EDI
MOV EDX, EAX
AND EAX, ESI
AND EDX, EDI
SHL EAX, CL
SHR EDX, CL
OR EAX, EDX
SHL ECX, 1
SUB EBX, 4
CMP EBX, mask - 4
JNE .L
PRINT_UDEC 4, EAX
NEWLINE
XOR EAX, EAX
RET
2。我转换后的C代码,当我输入0时会输出正确的答案,但是我的代码中有些错误,我不明白这是什么:
#include "stdio.h"
int main(void)
{
int mask [5] = {0xffff, 0xff00ff, 0xf0f0f0f, 0x33333333, 0x55555555};
int eax;
int esi;
int ebx;
int edi;
int edx;
char cl = 0;
scanf("%d",&eax);
ebx = mask[4];
ebx = ebx + 16;
int ecx = 1;
L:
esi = ebx;
edi = esi;
edi = !edi;
edx = eax;
eax = eax && esi;
edx = edx && edi;
eax = eax << cl;
edx = edx >> cl ;
eax = eax || edx;
ecx = ecx << 1;
ebx = ebx - 4;
if(ebx == mask[1]) //mask - 4
{
goto L;
}
printf("%d",eax);
return 0;
}
if(ebx != mask[1]) //mask - 4
{
goto L;
}
// JNE暗示一个!=
Assembly AND是按位C &
,不是逻辑&&
。 (与OR相同)。所以你想要eax &= esi
。
((使用&=
“化合物赋值”使C甚至look就像x86样式的2运算符asm,所以我建议这样做。)
也不是按位翻转,不布尔化为0/1。在C中为edi = ~edi;
阅读手册,了解https://www.felixcloutier.com/x86/not之类的x86指令,以及~
和!
之类的C运算符,以检查它们是否不是您想要的。https://en.cppreference.com/w/c/language/expressionshttps://en.cppreference.com/w/c/language/operator_arithmetic
您应该在调试器中单步执行C和asm,以便您注意到first的差异,并知道要修复的指令/ C语句。不要只运行整个过程,而只看一个数字即可得出结果!调试器对于asm非常有用;不要浪费你的时间。
CL是ECX的低字节,而不是单独的C变量。您可以在C中的uint32_t
和uint8_t
之间使用并集,或仅使用eax <<= ecx&31;
,因为您没有将CL与ECX分开编写的任何内容。 (x86移位掩盖了它们的计数;该C语句可以编译为shl eax, cl
。https://www.felixcloutier.com/x86/sal:sar:shl:shr)。 ECX的低5位也是CL的低5位。
SHR
是逻辑右移,不是算术运算,因此至少对于unsigned
,您需要使用int
而不是>>
。但实际上只是将其用于所有内容。
您处理EBX完全错误;这是一个指针。
MOV EBX, mask
ADD EBX, 16
类似于unsigned int *ebx = mask+4;
dword的大小为4个字节,但是C指针数学运算根据类型的大小进行缩放,因此+1
是整个元素,而不是1个字节。因此16个字节是4个双字= 4个unsigned int
元素。
MOV ESI, DWORD [EBX]
这是使用EBX作为地址的负载。如果您在调试器中单步调试asm,这应该很容易看出:这不仅是复制值。
CMP EBX, mask - 4
JNE .L
这是NASM语法;它在数组开始之前与dword的address进行比较。实际上,这是一个相当正常的do {} while循环的底部。 (Why are loops always compiled into "do...while" style (tail jump)?)
do { // .L
...
} while(ebx != &mask[-1]); // cmp/jne
它从mask
数组的末尾开始循环,当指针经过末尾时停止。
等效地,比较可以是ebx !-= mask - 1
。我用一元&
(地址)取消了[]
来写出来,以明确表示它是数组前一个元素的地址。
请注意,它在not相等时跳跃;您的if()goto
向后移动,仅在相等时跳转。这是一个循环。
unsigned mask[]
应该为static
,因为它在section .data
中,而不在堆栈中。而不是const
,因为它再次出现在.data
中,而不是.rodata
(Linux)或.rdata
(Windows))
这不影响逻辑,仅影响反编译的细节。
可能还有其他错误;我没有尝试检查所有内容。