2012-12-18 4 views
0

에서 long int를 반환하면 asm proc에서 eax를 통해 long int가 반환되고 나중에 dx : ax를 통해 시도되었습니다. C printf가 필요한 320L과 다른 번호를 인쇄 할 때 둘 다 나를 위해 작동하지 않았습니다.8086/386 asm with bcc5 : asm proc

x.asm :

.model SMALL 
.stack 100h 
.code 
.386 
; extern int get_buffered_long(long int **arr, int num_of_elements, int i); 
;         [BP+4]  [BP+6]    [BP+8] 
PUBLIC _get_bufferred_long 
_get_bufferred_long PROC NEAR 
     push BP 
     mov BP,SP 
     push SI 
     push DI 
     push BX 
     call locate_slot    
     ;mov EAX, DWORD PTR [DI]  ;something here doesn't work. the way i return a long int to borland C, or other issue. 
     mov ax,[DI] 
     mov dx,[DI+2] 
     pop BX 
     pop DI 
     pop SI 
     pop BP 
     ret 
_get_bufferred_long ENDP 
; extern void set_bufferred_long(long int *arr[], int buff_size, int i,long int value); 
;          [BP+4]  [BP+6]  [BP+8]  [BP+10] 
PUBLIC _set_bufferred_long 
_set_bufferred_long PROC NEAR 
    push BP 
    mov BP,SP 
    pushad 
    call locate_slot 
    mov EAX,[BP+10] 
    mov DWORD PTR [DI],EAX 
    popad 
    pop BP 
    ret 
_set_bufferred_long ENDP 
; helper function that makes DI point to the slot wanted. 
locate_slot PROC NEAR 
    calc_slot: 
     mov SI,[BP+4] 
     mov AX,[BP+8] 
     mov BX,[BP+6] 
     xor DX,DX 
     div BX 
    locate_slot_in_array: 
     shl AX,1 
     add SI,AX 
     mov DI,[SI] 
     shl DX,2 
     add DI,DX 
     ret 
locate_slot ENDP 
end 

y.c :

#include "stdio.h" 
#include "stdlib.h" 

extern int get_bufferred_long(long int**,int,int); 
extern void set_bufferred_long(long int**,int,int,long int); 

int main(){ 
    long int **arr; 
    int i,j,n,m; 
    n = 5; 
    m = 4; 
    arr=(long int**)malloc(n*sizeof(long int*)); 
    for(i=0; i < n; i = i + 2) arr[i] = malloc(m*sizeof(long int)); 
    for(i=1; i < n; i = i + 2) arr[i] = malloc(m*sizeof(long int)); 
    for(i=0; i < n; i++) 
     for(j=0; j < m; j++) 
      set_bufferred_long(arr, m, i*m+j, i*100+j*10); 

    printf("get_bufferred_long(arr, %d, %d) = %ld\n", m, 14, get_bufferred_long(arr,m, 14)); 
    return 0; 
} 

설정 기능 (배열에 필요한 정확히 같은 모양) 작동합니다. get 함수도 작동합니다. asm에서 320L을 가져 오지만, C에 전달되면 뭔가 잘못되었습니다.

컴파일 오류 또는 경고가 없습니다. borland C++ 5.02

+0

아마도 툴 체인을 15 년 전에 출시 된 것보다 조금 더 업그레이드했다고 생각 했습니까? gcc는 비어 있고 음성은 없지만 Visual C++ Express는 최소한 비어 있지 않습니다. 죽은 기술을 개발할 좋은 이유가 있기를 바랍니다. – paxdiablo

+0

@paxdiablo : uni hw, overpowered. – ckid

답변

2

음, 386 bcc에서는 16 비트 모드에서 AX : DX를 사용합니다. 32 비트 정도는 모르겠다.

하지만 코드를 살펴보십시오.

... 
    mov dx,[DI+2] 
    mov ax,[DI] 
    mov dx,[DI+2] 
    pop DX 
    ... 

DX 레지스터에 결과를로드 한 다음 스택을 팝핑하여 값을 날려 버립니다. DX는 간단한 절차 (예 : DOS ISR에서만)에서 푸시/팝으로 저장하지 않아도됩니다. 좋아

편집

난 당신이 코드에서 위의 문제를 해결을 참조하십시오. 다음 문제는 선언 할 가능성이 높습니다.

/* After execution, return value is assumed to be in AX. */ 
extern int get_bufferred_long(long int**,int,int); 

그런 다음 32 비트 반환 값이 필요합니다. printfAX 레지스터를 밀고 있다고 언급했습니다. 이것은 16 비트 코드로 컴파일한다는 것을 의미합니다. 16 비트 코드에서 32 비트 반환 값을 원하면 반환 값 long을 선언하고 DX:AX에 배치해야합니다.

/* After execution, return value is assumed to be in DX:AX reg pair. */ 
extern long get_bufferred_long(long int**,int,int); 

당신은 -S 옵션을 사용하여 어셈블리에 작은 프로그램을 컴파일하여 올바른 반환 규칙을 확인할 수 있습니다. 예를 들면 다음과 같습니다.

long val(void) { return 0x12345678L; } 

컴파일러가이 긴 값을 반환하는지 확인하려면 생성 된 어셈블리를 살펴보십시오.

+0

에 대해 팝업 dx, 예, 실수로 코드에 남겨진 내용 (주석을 달기 전에 게시물을 편집했습니다). 여전히 중요하지 않습니다. printf는 320L이 아닌 이상한 숫자를 출력합니다. "printf가 사용중인 모드에서 어셈블리로 컴파일하고 검사하여이를 확인할 수 있습니다." 설명 할 수 있니? – ckid

+0

'EAX'는 386 이후 32 비트 모드로 존재했습니다. – caf

+0

@Gene. "call _get .."ax = 140h 다음에 CPU 창 (C 코드의 어셈블리 형식)에서 터보 디버거의 c 코드를 보았습니다. 그것은 위대하다. 그 후 컴파일러는 "push ax"와 나머지 변수들을 printf에 넘겼습니다. – ckid