【问题标题】:Using calloc in Turbo C++ In-Line Assembly在 Turbo C++ 内联汇编中使用 calloc
【发布时间】:2020-05-16 11:57:19
【问题描述】:

我曾经在 8086 汇编和 Turbo C++ 中编写代码,我决定使用内联汇编进行一些测试,但我遇到了这个问题:

这段代码完美运行:

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>

FILE *fp;

int regvga=0x13;
int regtxt=0x03;
int vgamem=0xA000;

unsigned char data[64000];

void main (void)
{

fp=fopen("pic1.dat","rb");
fread(data,64000,1,fp);
fclose(fp);

asm{
    mov ax,regvga
    int 0x10

    mov ax,vgamem
    mov es,ax

    cld
    mov cx,32000

    lea si,data
    mov di,0

    rep movsw
    }

getch();

asm{
    mov ax,regtxt
    int 0x10
    }
}

但是这段代码根本行不通。

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>

FILE *fp;

int regvga=0x13;
int regtxt=0x03;
int vgamem=0xA000;

unsigned char *data;

void main (void)
{

data=(char*)calloc(64000,sizeof(char));

fp=fopen("pic1.dat","rb");
fread(data,64000,1,fp);
fclose(fp);

asm{
    mov ax,regvga
    int 0x10

    mov ax,vgamem
    mov es,ax

    cld
    mov cx,32000

    lea si,data
    mov di,0

    rep movsw
    }

getch();

asm{
    mov ax,regtxt
    int 0x10
    }

free(data);
}

它编译没有错误,但图像显示不正确。怎么了?

【问题讨论】:

  • 您为哪个模型编译代码?我想问题是您没有使用适当的段选择器加载ds。我不知道正确的语法是什么,但请尝试将 lea si, data 替换为 lds si, data
  • 使用 Turbo 有什么理由吗?它在很久以前就停产了。
  • 只是为了排除它。如果将 unsigned char data[64000]; 替换为 unsigned char d[64000]; unsigned char *data = d; 会发生什么?
  • 你验证calloc真的成功了吗?它可能会返回NULL,以防堆不够大,无法分配一大块 64,000 字节。
  • @klutt 这是某些国家的课程。这不能怪学生。

标签: c assembly x86-16


【解决方案1】:

堆位于不同的段中(显然,考虑到数组的大小)。按照@fuz 的建议,使用lds。此外,使用push dspop ds 允许程序在之后继续使用原始数据段。

push ds
lds  si,data
mov  di,0
rep  movsw
pop  ds

根据内存模型,您可能还需要将data 声明为“远”指针,并使用远堆函数:

unsigned char far *data;

data = (char far *)farcalloc(64000,sizeof(char));

farfree(data);

免责声明:我不能 100% 确定使用 Borland 的内联汇编将远指针加载到 ds:si 的正确方法。您可能需要使用调试器来解决这个问题。

【讨论】:

    【解决方案2】:

    @fuz @klutz @Ruud Helderman

    大家好!感谢您的大力帮助,很抱歉回复晚了:)

    其实解决方法很简单:只需要​​将lea si,data 替换为lds si,[data],当然还要保留DS 寄存器。代码将是这样的:

    asm{
        mov ax,regvga
        int 0x10
    
        push ds
    
        mov ax,vgamem
        mov es,ax
    
        cld
        mov cx,32000
    
        lds si,[data]
        mov di,0
    
        rep movsw
    
        pop ds
    }
    

    没有必要使用 faralloc,因为只有当我们的数组大于 64K 时才需要使用 faralloc。当然也需要使用大模型进行编译。

    嗯,我使用的是 Turbo C++ 3.0,因为我已经为 Windows、Amiga、Atari 和 Spectrum 制作了一个小型射击游戏,现在我想将它转换为 MS-DOS。由于我有点懒惰,我不想从根目录开始在汇编中编写代码,而是使用 Atari 版本的 C 代码并使用内联汇编来处理图形内容:)。更多关于我的小游戏的信息在这里:http://sardonic.planetaclix.pt/

    干杯, 狂斧

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-03-26
      • 1970-01-01
      • 2013-07-23
      • 2013-11-26
      • 1970-01-01
      • 2019-03-14
      • 2017-11-01
      相关资源
      最近更新 更多