2017-10-12 136 views
0

你們能告訴我我在哪裏弄錯了嗎?使用MSVC內嵌程序集計算-2xy - 3z

我需要在inline-assembly -2xy-3z中計算它。

int solution(int x, int y, int z) 
{ 
    x=4; 
    y=5; 
    z=2; 
    int result; 
    __asm 
    { 
     mov eax, -2 
     imul [x] 
     imul [y] 
     mov ebx, eax 
     mov eax, -3 
     imul [z] 
     sub eax, ebx 


     mov [result], eax  ; 
    } 
     assert(result == -2*x*y – 3*z); 
     printf("solution_for_grade_6(%d, %d,**strong text** %d) = %d\n", x, y, z, result); 
return result; 
+0

什麼處理器你寫的asm? 另外,運行代碼時會得到什麼樣的錯誤? 更多信息可幫助他人更快地獲得答案。 –

+0

它用於IA-32。我沒有得到一個錯誤,它運行但沒有發生在窗口上。 – konstantin97

+1

我看到的唯一錯誤是'sub eax,ebx'應該是'add eax,ebx',因爲你乘以-3,並且已經做了否定。你可以用'3'而不是'-3'來倍數,並保持'sub eax,ebx'的原樣。 –

回答

1

這是我的第五溶液(返回一個32位的值;我已刪除第四和第三錯誤/ UN優化的解決方案);它只使用一個IMUL;注意,這兩個ABS(X)& & ABS(Y)他們不能>(1 < < 14)-1,ABS(Z)必須<(1 < < 29):

__asm 
{ 
/* INPUT: EAX= X    */ 
/*   EDX= Y    */ 
/*   EBX= Z    */ 
/* TEMP: EDX     */ 
/* OUTPUT: EAX= -2*xy-3*z)  */ 

NEG EAX 

IMUL EDX   /* EDX:EAX=-x*y */ 

ADD EAX,EAX  /* EAX=-2*x*y */ 

LEA EDX,[EBX+EBX] 
ADD EDX,EBX 
SUB EAX,EDX  /* EAX=-2*x*y-z*3 */ 

MOV [RESULT],EAX 
} 

這是我的第二個解決方案(返回一個64位的值);它只使用一個IMUL;現在進行了優化。注意abs(X)& & abs(Y)它們不能>(1 < < 30)-1。我推測,因此,在這種情況下,是一個64位整數:

__asm 
{ 
/* INPUT: EAX= X    */ 
/*   EDX= Y    */ 
/*   EBX= Z    */ 
/* TEMP: ESI, EDI    */ 
/* OUTPUT: EDX:EAX= -(2*xy+3*z) */ 

IMUL EDX 

ADD EAX,EAX 
ADC EDX,EDX /* EDX:EAX=2*xy */ 

MOV ESI,EBX 
ADD ESI,ESI 
SBB EDI,EDI /* EDI:ESI=2*z */ 

ADD ESI,EBX 
ADC EDI,EDI /* EDI:ESI=3*z */ 

ADD EAX,ESI 
ADC EDX,EDI /* EDX:EAX=2*xy+z*3 */ 

NOT EAX 
NOT EDX 

ADD EAX,1 
ADC EDX,0 /* EDX:EAX=-(2*xy+z*3) */ 

LEA ESI,[RESULT] 
MOV [ESI],EAX 
MOV [ESI+4],EDX 
} 

但請記住,每兩個產品有更多然後64位的結果;在彙編(返回一個96位值):

; -2xy-3z=-(2*xy+3*z) 

; INPUT: EAX= X 
;  EDX= Y 
;  ECX= Z 

; TEMP: EDI, ESI, EBP 

; OUTPUT: EBX:EDX:EAX= -(2*xy+3*z) 

IMUL EDX 

ADD EAX,EAX 
RCL EDX,1 
SBB EBX,EBX ;EBX:EDX:EAX=2*xy 

MOV ESI,ECX 
ADD ESI,ESI 
SBB EDI,EDI 
MOV EBP,EDI ;EBP:EDI:ESI=z*2 

ADD ESI,ECX 
ADC EDI,EDI 
ADC EBP,EBP ;EBP:EDI:ESI=z*3 

ADD EAX,ESI 
ADC EDX,EDI 
ADC EBX,EBP ;EBX:EDX:EAX=2*xy+z*3 

NOT EAX 
NOT EDX 
NOT EBX 

ADD EAX,1 
ADC EDX,0 
ADC EBX,0 ;EBX:EDX:EAX=-(2*xy+z*3) 
+0

但是,如果您在獨立功能中使用它,則必須在此代碼之前/之後保存/恢復EBX,ESI,EDI和EBP寄存器... –

+0

不要使用push/pop來保存/恢復inline-asm語句。讓編譯器爲你做,如果需要的話。 (它可能不會在內聯到一個已經保存/恢復這些regs的函數之後,但是當這段代碼運行時它們沒有任何有價值的東西)。 –

+0

'add edi,edi'比'shl edi,1'更有效率,並將CF設置完全相同。 –