0

eax を介して asm proc から long int を返そうとし、後で dx:ax を介して試みました。Cのprintfが必要な320Lとは異なる番号を出力するため、両方ともうまくいきませんでした。

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

yc:

#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;
}

set 関数は機能します (配列は必要に応じて正確に見えます)。get 関数も機能し、asm で 320L をフェッチしますが、C に渡すと何かがおかしいです。

コンパイル エラーや警告はありません。ボーランド C++ 5.02

4

1 に答える 1

2

386 bcc では AX:DX を 16 ビット モードで使用します。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 ビットの戻り値が必要です。あなたはレジスター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; }

生成されたアセンブリを見て、コンパイラがこの長い値を返すために何をするかを確認してください。

于 2012-12-18T03:43:38.863 に答える