2015-02-03 3 views
0

나는 어셈블러를 배우고있다. 이 코드 연습 :실행 대 디버그 = 어셈블러에서 다른 결과

ASM :

;------------------------------------------------------------------------- 
.586 

.MODEL flat, stdcall 
public srednia_harm 


OPTION CASEMAP:NONE 

INCLUDE include\windows.inc 
INCLUDE include\user32.inc 
INCLUDE include\kernel32.inc 

.CODE 

    jeden dd 1.0 

DllEntry PROC hInstDLL:HINSTANCE, reason:DWORD, reserved1:DWORD 

    mov eax, TRUE 
    ret 

DllEntry ENDP 

;------------------------------------------------------------------------- 
;------------------------------------------------------------------------- 


srednia_harm  PROC 

    push ebp 
    mov esp,ebp 

    push esi 
    mov esi, [ebp+8] ; address of array 
    mov ecx, [ebp+12] ; the number of elements 

    finit 
    fldz ; the current value of the sum - st(0)=0 

    mianownik: 
    fld dword PTR jeden ;ST(0)=1, ST(1)=sum 

    fld dword PTR [esi] ;loading of array elements - ST(0)=tab[i], ST(1)=1 ST(2)=suma 

    fdivp st(1), st(0) ; st(1)=st(1)/(st0) -> ST(0)=1/tab[i], ST(1)=suma 

    faddp st(1),st(0) ; st(1)=st(0)+st(1) -> st(0)=suma+1/tab[i] 

    add esi,4 
    loop mianownik 

    pop esi 
    pop ebp 
    ret 


srednia_harm ENDP 


;------------------------------------------------------------------------- 
;------------------------------------------------------------------------- 
;------------------------------------------------------------------------- 
;------------------------------------------------------------------------- 
;------------------------------------------------------------------------- 
;------------------------------------------------------------------------- 
END DllEntry 

DEF :

LIBRARY "biblioteka" 
EXPORTS 
srednia_harm 

C 번호 :

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Runtime.InteropServices; 

namespace GUI 
{ 
    unsafe class FunkcjeAsemblera //imports of assembler's function 
    { 
     [DllImport("bibliotekaASM.dll", CallingConvention = CallingConvention.StdCall)] 
     private static extern float srednia_harm(float[] table, int n); 

     public float wywolajTest(float[] table, int n) 
     { 
      float wynik = srednia_harm(table, n); 
      return wynik; 
     } 

    } 
} 

C 번호 : 나는이 코드를 실행하면

private void button6_Click(object sender, EventArgs e) 
     { 
      FunkcjeAsemblera funkcje = new FunkcjeAsemblera(); 
      int n = 4; 
      float[] table = new float[n]; 
      for (int i = 0; i < n; i++) 
       table[i] = 1; 
      float wynik = funkcje.wywolajTest(table, n); 
      textBox6.Text = wynik.ToString(); 
     } 

모든 것이 괜찮습니다. 결과는 내가 예상 한대로 4입니다. 하지만 그 코드를 이해하려고 했으므로 ASM 기능에 많은 중단 점을 설정했습니다. 그런 다음 문제가 시작되었습니다. Arrat은 정확하게 기억에 있어야하지만 seond 매개 변수는 손실됩니다. 주소가 메모리의 빈 필드를 가리 킵니다. 나는 많은 조합을 시도했다, 나는 개미를 바꿨다. 그것은 아직도 같았다. 몇 가지 조사를했지만 단서를 찾지 못했습니다. 어떻게하면 프로그램을 실행할 때 모든 것이 잘 작동하고 DEBUG에서는 불가능할 수 있습니까?

+4

디버그 및 릴리스의 컴파일러 출력이 다릅니다. 디버그 버전은 최적화가 해제 된 상태에서 컴파일되고 릴리스에는 최적화가 설정된 상태로 컴파일됩니다. 그들은 다른 기계 코드를 산출 할 다른 MSIL을 산출 할 것이다. –

+0

"하지만 seond 매개 변수가 손실됩니다." 언더 레이 변수가 다른 값을 갖고 있다고 말하는가? 디버그 빌드는 모든 변수를 0으로 강제하는 경향이있는 반면, 릴리스에서는 중복되는 경우이를 최적화 할 수 있습니다. –

+0

StdCall이라고 표시했지만 그 내용은 귀하가 작성한 내용이 아닙니다. 이 문제를 해결하려면 C 컴파일러를 사용하십시오. 또는 StdCall이 의미하는 바를 이해할 수 있도록 생성하는 어셈블리를 살펴보십시오. –

답변

1

좋아, 디버그 및 릴리스 모드에서 테스트했습니다. Properties-> Debug-> EnableNativeCodedebugging을 활성화했습니다. Step Into (F11)로 두 경우 모두 작동합니다. 'n'변수는 올바르게 액세스됩니다.

부적절한 PROC 설정이 문제였습니다. 위의 코드는 EBP를 기준으로 두 변수에 액세스하지만 스택을 정리하지 않습니다 (stdcall [호출 수신자가 스택을 정리하는 책임] @Wikipedia). 어떤 문제의 원인이되었다는 것을 아마

push  ebp 
mov   ebp,esp 
push  esi 
mov   esi,dword ptr [ebp+8] 
mov   ecx,dword ptr [ebp+0Ch] 
wait 
... 
add   esi,4 
loop  6CC7101F 
pop   esi 
leave  <-- restores EBP 
ret   8  <-- two params cleaned up 

나는 PROC를 변경 제안

srednia_harm PROC uses esi lpArr: DWORD, num: DWORD 
    mov esi, lpArr 
    mov ecx, num 
    ... 
    ret 
srednia_harm ENDP 

에 :

push  ebp 
mov   esp,ebp 
push  esi 
mov   esi,dword ptr [ebp+8] 
mov   ecx,dword ptr [ebp+0Ch] 
wait 
... 
add   esi,4 
loop  6CC7101F 
pop   esi 
pop   ebp 
ret   <-- two params not cleaned up 

다음

는 PROC 아래 제목으로 조립 된 코드입니다.

+0

Thx, 이제 작동 함;) 질문이 하나 더 있습니다. 부동 소수점 숫자를 보조 프로세서에서 레지스터로 이동할 수 있습니까? 나는 변수를 사용하여'var dd? '를 선언하고'fst [var]'를 시도했지만 결과는 다음과 같다 : _ GUI.exe에서'System.AccessViolationException '유형의 처리되지 않은 예외가 발생했습니다. – Bazzby

+0

var '제다이'를 '. 데이터'세그먼트에 넣습니다. 코드 세그먼트는 읽기 전용 일 수 있습니다. – zx485