为什么下面的c函数与asm代码相同

为什么下面的c函数与asm代码相同,c,assembly,C,Assembly,有人能解释一下为什么下面的c代码等同于asm代码吗 void arith1(){ a=(b*10)+(5/(-e)); } 为什么我们要把b的值放在ecx寄存器中 neg esi ; $2 = -e cdq ASM代码: mov ecx, DWORD PTR _b imul ecx, 10 ; $1 = b * 10 mov esi, DWORD PTR _e neg esi ; $2 = -e mov e

有人能解释一下为什么下面的c代码等同于asm代码吗

void arith1(){
    a=(b*10)+(5/(-e));
}
为什么我们要把b的值放在ecx寄存器中

neg  esi    ; $2 = -e
cdq
ASM代码:

mov  ecx, DWORD PTR _b
imul ecx, 10             ; $1 = b * 10
mov  esi, DWORD PTR _e  
neg  esi                 ; $2 = -e
mov  eax, 5
cdq
idiv esi                 ; $3 = 5 / -e
add  ecx, eax            ; $4 = $1 + $3
mov  DWORD PTR _a, ecx   ; a = $4
将变量b移到ecx寄存器中

imul     ecx, 10    ; $1 = b * 10
将ecx寄存器乘以10。(b*10)

将变量e移到esi寄存器中

neg  esi    ; $2 = -e
cdq
对esi寄存器求反。(-e)

将5移到eax寄存器中

neg  esi    ; $2 = -e
cdq
将eax转换为四字(我想,不确定它的用途)

将eax除以esi(5/-e)

将eax添加到ecx(b*10)+(5/-e)

将ecx移动到变量a中(a=(b*10)+(5/-e))


唯一不直观的部分是imul和idiv指令将edx和eax寄存器组合起来形成64位值。高32位在imul指令后被丢弃,C不执行溢出检查。在除法之前,需要cdq指令(将双精度转换为四精度)将32位值转换为64位值。

它不是,它相当于
(b*10)+(5/-e)
C代码中应该有除法吗?或者这就是问题的基础?几乎任何其他的语域都可以使用。esi、edi、edx、ebp都可以工作,所以只选择了一个寄存器。当然不是edx,因为其中有一个干熄焦。。还有一个idiv。你真的在问两个问题。第一个问题的答案是:不是,而第二个问题是:为什么不是?此外,它是ecx寄存器,而不是ecx寄存器。处理器只有一个名为thusly的寄存器。双宽度乘法是单操作数形式,而不是此形式。此表格(imul r,imm)甚至不在英特尔手册中,而是imul r,r,imm的缩写,其中两个r相同。需要cdq,因为idiv中使用的edx中可能存在任何旧垃圾。xor edx,edx在这种情况下也能正常工作(5是肯定的)
add  ecx, eax   ; $4 = $1 + $3
mov  DWORD PTR _a, ecx  ; a = $4
mov  ecx, DWORD PTR _b
imul ecx, 10             ; edx:eax = b * 10
mov  esi, DWORD PTR _e  
neg  esi                 ; esi = -e
mov  eax, 5
cdq                      ; edx:eax = 5
idiv esi                 ; eax = 5 / -e
add  ecx, eax            ; ecx = b * 10 + 5 / -e
mov  DWORD PTR _a, ecx   ; store result to a