Heather Kordinak Heather Kordinak - 28 days ago 10
C Question

What is the difference between these two forms of inline assembler in C?

Background: I've been tasked with writing a data collection program for a Unitech HT630, which runs a proprietary DOS operating system that can run executables compiled for 16-bit MS DOS, albeit with some restrictions. I'm using the Digital Mars C/C++ compiler, which seems to be working very well.

For some things I can use standard C libraries, but other things like drawing on the screen of the unit require assembly code. The assembly examples given in the device's documentation are different from how I was taught to use inline assembly code in C/C++. For reference,

BYTE
in the examples below is of type
unsigned char
.

Sample of the example code I was given:

#include <dos.h>

/* Set the state of a pixel */
void LCD_setpixel(BYTE x, BYTE y, BYTE status) {
if(status > 1 || x > 63 || y > 127) {
/* out of range, return */
return;
}
/* good data, set the pixel */
union REGS regs;
regs.h.ah = 0x41;
regs.h.al = status;
regs.h.dh = x;
regs.h.dl = y;
int86(0x10, &regs, &regs);
}


How I was always taught to use inline assembly:

/* Set the state of a pixel */
void LCD_setpixel(BYTE x, BYTE y, BYTE status) {
if(status > 1 || x > 63 || y > 127) {
/* out of range, return */
return;
}
/* good data, set the pixel */
asm {
mov AH, 41H
mov AL, status
mov DH, x
mov DL, y
int 10H
}
}


Both forms seem to work, I haven't encountered a problem with either approach as of yet. Is one form considered better than the other for DOS programming? Does the
int86
function handle something for me that I am not handling myself in my own assembly code in the second example?

Thank you in advance for any help.

Answer

When you use the int86 function call, that is a C runtime library call which sets up the registers and issues a DOS interrupt function. Both methods are really the same with one exception, when you use inline assembler, the code is actually embedded into the object code when compiled and linked.

Inline assembly would be considered faster since you do not have the overhead involved in calling the C runtime library to invoke the DOS interrupt for you. The onus is on you to ensure there is enough stack space when using inline assembly, whereas the C Runtime library takes care of allocating stack space when setting up the registers prior to invoking the int86 function.

The int86 is a way to make it easier to invoke DOS interrupts. This was extremely popular among the old Borland Turbo C suite of compilers and on Microsoft, I am talking about old compilers before Win 3.1 came out.

Speaking of the interrupt 0x10, which is responsible for the video output, if I remember correctly, at the time, some BIOS's destroyed the bp register and the workaround was to do this:

__asm{
   push bp;
}
/* set up the registers */
int86(0x10, &regs, &regs);
__asm{
   pop bp;
}

You can find out the extensive BIOS functions on Ralph Brown's Interrupt List here. Also HelpPC v2.1 may help also, found here.

Comments