【问题标题】:C++ external assembly: where is error in my code?C++ 外部程序集:我的代码中的错误在哪里?
【发布时间】:2015-02-03 15:38:43
【问题描述】:

main.cpp

// 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

【问题讨论】:

  • 那里发生了什么?我们不是编译器,输出是什么?预期的输出?怎么了?
  • 没错,请告诉我们会发生什么以及您预期会发生什么。
  • @DimitriMockelyn,“我们不是编译器”很酷!
  • 这也不是内联汇编,它只是普通的 x86 汇编代码。
  • 你在哪里退出L1循环?

标签: c++ assembly x86


【解决方案1】:

此代码基于 Kip Irvine 汇编手册(第 6 版)中的 MS-DOS 的 16 位示例,并明确为 Borland C++ 5.01 和 TASM 4.0 编写(参见第 13.4 章“在 Real 中链接到 C/C++ -地址模式”)。

16 位模式的指针由一个段和一个偏移量组成,通常写为segment:offset。这不是将由处理器计算的真实内存地址。您可以在 32 位寄存器 (EDI) 中加载 segment:offset 并将值存储到内存中。所以

...
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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-12
    • 1970-01-01
    • 1970-01-01
    • 2015-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多