2015-02-03 2 views
-4

main.cppC++ внешняя сборка: где ошибка в моем коде?

// Calls the external LongRandom function, written in 

// assembly language, that returns an unsigned 32-bit 

// random integer. Compile in the Large memory model. 

// Procedure called LongRandomArray that fills an array with 32-bit unsigned 

// random integers 

#include <iostream.h> 

#include <conio.h> 

extern "C" { 

      unsigned long LongRandom(); 

      void LongRandomArray(unsigned long * buffer, unsigned count); 

      } 

const int ARRAY_SIZE = 20; 

int main() 

{ 

    // Allocate array storage and fill with 32-bit 

    // unsigned random integers. 

    unsigned long * rArray = new unsigned long[ARRAY_SIZE]; 

    LongRandomArray(rArray,ARRAY_SIZE); 

    for(unsigned i = 0; i < 20; i++) 

    { 

    cout << rArray[i] << ','; 

    } 

    cout << endl; 

    getch(); 

    return 0; 

} 

LongRandom & LongRandomArray модуль Процедура (longrand.asm)

.model large 

.386 

Public _LongRandom 

Public _LongRandomArray 

.data 

seed dd 12345678h 

; Return an unsigned pseudo-random 32-bit integer 

; in DX:AX,in the range 0 - FFFFFFFFh. 

.code 

_LongRandom proc far, C 

     mov eax, 214013 

     mul seed 

     xor edx,edx 

     add eax, 2531011 

     mov seed, eax ; save the seed for the next call 

     shld edx,eax,16 ; copy upper 16 bits of EAX to DX 

     ret 

_LongRandom endp 

_LongRandomArray proc far, C 

ARG bufferPtr:DWORD, count:WORD 

; fill random array 

     mov edi,bufferPtr 

     mov cx, count 

L1: 

    call _LongRandom 

    mov word ptr [edi],dx 

    add edi,2 

    mov word ptr [edi],ax 

    add edi,2 

    loop L1 

    ret 

_LongRandomArray endp 

end 
+5

Что там происходит? Мы не компиляторы, какой результат? Ожидаемый результат? Что там не так? –

+0

Точно, пожалуйста, сообщите нам, что произойдет и что вы ожидали. – flodin

+0

@DimitriMockelyn, «Мы не компиляторы» - это круто! – ForceBru

ответ

0

Этот код основан на на 16-битной, например, для MS-DOS из сборки книги Кипа Ирвайна (6-е изд.) И явно написано для Borland C++ 5.01 и TASM 4.0 (см. Главу 13.4 «Связывание с C/C++ в режиме Real-Address»).

Указатели в 16-битовом режиме состоят из сегмента и смещения, обычно записываемого как segment:offset. Это не реальный адрес памяти, который будет рассчитан процессором. Вы можете не загрузить segment:offset в 32-битный регистр (EDI) и сохранить значение в памяти. Так

... 
mov edi,bufferPtr 
... 
mov word ptr [edi],dx 
... 

является неправильно. Вы должны загрузить сегментную часть указателя в регистре сегментов, например. ES, смещение в соответствующем общем 16-разрядном регистре, например. DI и, возможно, использовать сегмент переопределение:

... 
push es 
les di,bufferPtr   ; bufferPtr => ES:DI 
... 
mov word ptr es:[di],dx 
... 
pop es 
... 

ARG заменяет имя переменной с соответствующим [bp+x] операнда. Для этого вам нужен пролог (и эпилог). TASM вставляет правильную инструкцию, если заголовок PROC хорошо написан, что здесь не так. Взгляните на следующий рабочий функции:

_LongRandomArray PROC C FAR 
ARG bufferPtr:DWORD, count:WORD 
    push es 
    les di,bufferPtr 
    mov cx, count 
L1: 
    call _LongRandom 
    mov word ptr es:[di],dx 
    add di,2 
    mov word ptr es:[di],ax 
    add di,2 
    loop L1 
    pop es 
    ret 
_LongRandomArray ENDP 

скомпилировать код с BCC (не bcc32):

BCC -ml main.cpp longrand.asm 
Смежные вопросы