2012-12-18 85 views
0

嘗試從asm proc通過eax返回一個long int,然後通過dx:ax嘗試。兩者都不適用於我,因爲C printf打印的數字不是所需的320L。8086/386 asm with bcc5:從asm proc返回long int

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確實使用AX:DX在16位模式;不知道大約32位。

但看看你的代碼!

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

您正在加載包含結果的DX寄存器,然後彈出堆棧到它,吹散了它的價值。 DX不必通過簡單的程序(例如在DOS ISR中)通過push/pop來保存。

編輯

好吧,我看你固定在上面的代碼中的問題。下一個問題很可能是你聲明

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

然後期待32位返回值。您提到printf正在推送AX寄存器。這意味着您正在編譯爲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

關於pop dx,是的,我遺漏了代碼(在你評論之前將它編輯出來)。仍然無關緊要。 printf打印一個奇怪的數字,而不是320L。 「您可以通過在printf使用的模式下編譯爲程序集並進行檢查來驗證。」你可以解釋嗎? – ckid

+0

'EAX'自從386. – caf

+0

@Gene以來就以32位模式存在。我在「調用_get ..」ax = 140h之後,在CPU窗口(c代碼的彙編形式)中查看了turbo調試器中的c代碼。這很棒。之後,編譯器確實「推斧」,並給予printf其餘的變量。 – ckid