Reputation: 701
So I'm writing a game in c++ for MS-DOS and I'm including some inline assembly for speed. This particular block of code would draw a star into the video memory (0A000h). The problem with my code is that it only draws one pixel in whatever color dh is set to. As far as I know mov dx, 00007h is equivalent to setting dh to 0 and dl to 7. What is wrong?
The equivalent C/C++ code (or at least my intention) is commented beside each line. My compiler is turbo C++ 3.0. I'm trying to only use 8086/8088 instructions.
Also I know how old MS-DOS is so don't tell me to write code for a newer compiler/operating system. Writing code for dos is kind of a hobby of mine.
pixelOffset = x + (y << 6) + (y << 8);
_asm {
mov ax, WORD PTR pixelOffset
mov di, ax
mov ax, 0A000h ;pointer to the video memory
mov es, ax
mov dx, 00007h ;indexed color 00 and 07
mov cx, 0000Fh ;indexed color white 0F
add ax, 2 ;pixelOffset += 2;
mov es:[di], dh ;videomem[pixelOffset] = BLACK;
add ax, 319 ;pixelOffset += 319;
mov es:[di], dh ;videomem[pixelOffset] = BLACK;
add ax, 1 ;pixelOffset += 1;
mov es:[di], dl ;videomem[pixelOffset] = LIGHT_GRAY;
add ax, 1 ;pixelOffset += 1;
mov es:[di], dh ;videomem[pixelOffset] = BLACK;
add ax, 317 ;pixelOffset += 317;
mov es:[di], dh ;videomem[pixelOffset] = BLACK;
add ax, 1 ;pixelOffset += 1;
mov es:[di], dl ;videomem[pixelOffset] = LIGHT_GRAY;
add ax, 1 ;pixelOffset += 1;
mov es:[di], cx ;videomem[pixelOffset] = WHITE;
add ax, 1 ;pixelOffset += 1;
mov es:[di], dl ;videomem[pixelOffset] = LIGHT_GRAY;
add ax, 1 ;pixelOffset += 1;
mov es:[di], dh ;videomem[pixelOffset] = BLACK;
add ax, 317 ;pixelOffset += 317;
mov es:[di], dh ;videomem[pixelOffset] = BLACK;
add ax, 1 ;pixelOffset += 1;
mov es:[di], dl ;videomem[pixelOffset] = LIGHT_GRAY;
add ax, 1 ;pixelOffset += 1;
mov es:[di], dh ;videomem[pixelOffset] = BLACK;
add ax, 319 ;pixelOffset += 319;
mov es:[di], dh ;videomem[pixelOffset] = BLACK;
}
Upvotes: 5
Views: 588
Reputation: 20057
There's no need to increment the base using ax
-- first; there's also the addressing mode with displacement only (also considered as absolute address)
mov es:[1001], dh
mov es:[1002], dl
mov es:[1535], cl
To make that more useful -- you can use that with offset, which could eg. work as the center of your star:
mov es:[di - WIDTH], ... ;; pixel / character above the current cursor
mov es:[di + WIDTH], ... ;; pixel / char below
mov es:[di + 1], ... ;; pixel right to the origin etc.
Using the segment override prefix es:
is costly. Instead I'd suggest using
mov ax, 0a000h
push ds
mov ds, ax
//
mov [di + offset], cl ;; this pays off when writing several pixels
//
pop ds ;; restore DS after you have copied your stuff
Upvotes: 0
Reputation: 539
The lea instruction also exist in 16 bit:
lea di,[di+1] ; substitute for "inc di" and/or "add di,1" , if we do not need a flag
Dirk
Upvotes: 0
Reputation: 1598
I think you have forgotten to update di after updating ax
add ax,1
mov di,ax ;don't forget this line
mov es:[di],dl
Upvotes: 5
Reputation: 121869
It doesn't look like you're ever incrementing "di", does it? Perhaps you meant "movsb"?
Upvotes: 3