简体   繁体   中英

Using calloc in Turbo C++ In-Line Assembly

I use to code in 8086 assembly and in Turbo C++ and I decided to make some tests with in-line assembly but I got stuck with this problem:

This code works perfectly:

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

But this code simply doesn't work.

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

It compiles without errors but the image is displayed incorrectly. What's wrong?

The heap is in a different segment (evidently, given the size of the array). As proposed by @fuz, use lds . Additionally, use push ds and pop ds to allow the program to continue afterwards with the original data segment.

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

Depending on the memory model, you may also need to declare data as a 'far' pointer, and use far heap functions:

unsigned char far *data;

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

farfree(data);

Disclaimer: I'm not 100% sure about the proper way to load a far pointer into ds:si with Borland's inline assembly. You may need to use the debugger to work that out.

@fuz @klutz @Ruud Helderman

Hi guys: Thanks for your great help and sorry for this late reply :)

In fact, the solution is very simple: it's just need to replace lea si,data for lds si,[data] and of course preserve the DS register. The code will be something like this:

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
}

There is no need to use faralloc because faralloc is only needed when our array is bigger than 64K. And of course there is need to compile using the Large Model.

Well, I'm using Turbo C++ 3.0 because I have made a little shooter for Windows, Amiga, Atari and Spectrum and now I want to convert it to MS-DOS. As I'm a little lazy I don't want to code it in assembly from the root but use the C code from Atari version and use in-line assembly to handle the graphical stuff:). More info about my little game here: http://sardonic.planetaclix.pt/

Cheers, MadAxe

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM