China DOS Union

-- Unite DOS · Advance DOS · Grow DOS --

Union site: www.cn-dos.net Forum site: www.cn-dos.net/forum
DOS stands for freedom, openness and progress. Let us work hard, learn from the openness and GNU spirit of FreeDOS and Linux, and together build and grow a free GNU GPL world!

中国DOS联盟论坛
The time now is 2026-08-01 16:35
中国DOS联盟论坛 » DOS开发编程 & 发展交流 (开发室) » My simple tutorial on DJGPP! [Original] View 1,758 Replies 2
Original Poster Posted 2004-05-19 00:00 ·  中国 河北 唐山 联通
中级用户
★★
疯狂的流浪者
Credits 276
Posts 56
Joined 2003-09-25 00:00
22-year member
UID 10329
Gender Male
Status Offline
Tutorial for Beginners on DJGPP
by xy_god
homepage:http://www.xygod.pc5.org
_____________________________________________________________________________________
Since I started using LINUX, I've had enough of WINDOWS, but many developments still can't do without DOS. It's really helpless! I've long heard that FREEDOS is completely compatible with MSDOS and follows the GPL license, so I made up my mind to get rid of WINDOWS and installed FREEDOS! The development tools can't use the original commercial things like TURBO C anymore. I'll use a pure GNU platform! Okay, replace TURBO C with DJGPP, and also replace MASM and TASM with NASM! What about the editor? Using EDIT is really unpleasant, so I replaced it with the DOS version of VIM, which is also a GNU tool! I'm sorry, but the Chinese platform still has to use UCDOS because it seems there's no GPL-licensed Chinese DOS platform yet. Fortunately, UCDOS is free, so there won't be pirated software in my system, and I don't have the feeling of being a thief! ^-^
OK, all this is done, but facing DJGPP and NASM, I suddenly feel I know nothing. When I wrote code with TURBO C and MASM, calling interrupts, interactive programming, etc., now I don't know how to do it anymore. Oh, it's just like when I first came into contact with LINUX! I had to go to http://delorie.com/djgpp to look, it's all in English. I forced myself to read it! Finally, I found some user guides and understood them, basically able to solve the above problems! Think about it, so many people like me must also be having the same headache, so I wrote this to share with everyone. It's not a translation because I don't have the patience to translate those wordy things. I'll write a tutorial according to my understanding. But big shots don't need to read it!
Also, this tutorial assumes that you have certain knowledge of turbo c or other C/C++ under DOS, and have done some interrupt calls, interrupt resident programs, video memory mapping operations, and mixed programming of C/C++ and ASM!
OK, enough nonsense. This tutorial is divided into the following four parts:
1 How to call interrupts;
2 How to write data to VIDEO RAM;
3 How to write an interrupt resident program;
4 How to call an assembly function written by NASM;
5 Related licenses, disclaimers, and others
_____________________________________________________________________________________
1 How to call interrupts:
Calling real-mode interrupts in DJGPP is very similar in form to using the INT86 call interrupts in TURBO C. Look at the following example (from http://delorie.com/djgpp):
#include

void main(void){
__dpmi_regs r;

r.x.ax = 0x13;
r.d.ebx = 0x10000;
r.h.cl = 4;
r.h.dh = 5;

__dpmi_int(0x10, &r);
}

__dpmi_regs is a structure containing all the registers used by 80386. If you want to use 8-bit registers, you can do it like this __dpmi_regs.h.xx (xx can be ah, al, bh, bl, etc. registers). If you want to use 16-bit registers, you can do it like this __dpmi_regs.x.xx (replace h with x). If you want to use 32-bit registers, replace h with d!
The above code is to call int10 interrupt and set the display mode to 0x13 (320*200 256).
When the interrupt is executed, the __dpmi_regs type parameter passed to __dpmi_int will contain the new values of the registers. You can detect these new values to analyze the execution of the interrupt! Note that these interrupt calls are all in real mode!
_____________________________________________________________________________________
2 How to write data to VIDEO RAM:
There are two methods to write data to VIDEO RAM. These two methods each have advantages and disadvantages. You need to choose according to the situation!
The first method:
The following is the code:
#include

void main(void){
char *screen;

__dpmi_regs r;

r.x.ax = 0x13;
r.d.ebx = 0x10000;
r.h.cl = 4;
r.h.dh = 5;

__dpmi_int(0x10, &r);/*Set to 0x13 display mode*/

if (__djgpp_nearptr_enable() == 0) return 0; /* It may happen */
screen = 0xa0000 + __djgpp_conventional_base;
screen = 4;/*Set a point in the upper left corner of the screen to red*/
__djgpp_nearptr_disable();
}
This example draws a red point in the upper left corner of the screen. This method has the following two disadvantages:
After calling some specific DPMI procedures, you must recalculate the near pointer value of video ram!
It can't be used under windows NT (at least it can't be used under XP, but it's okay under pure DOS)!
Therefore, this method is generally not recommended!

The following is the second method:
#include
#include

int main(){
int x=0,y=0;
char * screen;
__dpmi_regs r;

r.x.ax = 0x13;

__dpmi_int(0x10, &r);

_farsetsel(_dos_ds);
_farnspokeb(0xA0000, 4);
return 1;
}

This example draws a red point in the upper left corner of the screen. It also has a disadvantage that it's a little slower than the first method. But it's safer. It's said that it can be used under NT (but my verification under XP is very bad), and it doesn't need to recalculate the VIDEO RAM pointer. In the Allegro library, this method is used, so its speed is also relatively good, so this method is recommended!
_____________________________________________________________________________________
3 How to write an interrupt resident program:
Here's a program, translated from the DJGPP user guide. Not much to say, look at the program, the comments are very clear!
#include
#include
#include
#include

#define LOCK_VARIABLE(x) _go32_dpmi_lock_data((void *)&x,(long)sizeof(x));
#define LOCK_FUNCTION(x) _go32_dpmi_lock_code(x,(long)sizeof(x));


#define TIMER 8/*The clock interrupt 8 occurs every 18.2 ms*/

int counter = 0;/*Initial value of the counter*/

void TickHandler(void){/*New clock interrupt handler*/
counter++;
}


int main(void)
{
/*Structure containing interrupt address (selectorffset) information*/
_go32_dpmi_seginfo OldISR, NewISR;

printf("Going to link the new interrupt handler to the old interrupt handler..\n";
getkey();

/*Lock functions and variables*/
LOCK_FUNCTION(TickHandler);
LOCK_VARIABLE(counter);

/*Write the old interrupt address into the OldISR structure variable*/
_go32_dpmi_get_protected_mode_interrupt_vector(TIMER, &OldISR);

/*NewISR points to the address of function TickHandler*/
NewISR.pm_offset = (int)TickHandler;
NewISR.pm_selector = _go32_my_cs();

/*Link the address pointed to by NewISR to the address of interrupt 8*/
_go32_dpmi_chain_protected_mode_interrupt_vector(TIMER,&NewISR);

while (!kbhit())
printf("%d\n",counter);

printf("Restoring the original clock interrupt.。。。。。\n";

/*Restore the original clock interrupt*/
_go32_dpmi_set_protected_mode_interrupt_vector(TIMER, &OldISR);

return 0;
}
_____________________________________________________________________________________
4 How to call an assembly function written by NASM:
The following example is written by myself. There are three files in total:
Save the following code as asm.asm:






; ---------------------------------------------------------------------------
; Prototype declaration: unsigned int AddFour(unsigned int x);
; Returns: x + 4
; ---------------------------------------------------------------------------

x_AddFour equ 8

_AddFour__FUi:
push ebp
mov ebp, esp

mov eax,
add eax, 4

mov esp, ebp
pop ebp
ret
Save the following code as c.c:
#include

extern unsigned int AddFour(unsigned int);

int main(void)
{
printf("AddFour(4) = %i\n", AddFour(4));
return 0;
}
Save the following code as maker.bat:
@echo off

nasm -f coff asm.asm

gcc -o c.exe c.c asm.o

c.exe

Finally, enter maker. If it's successful, it will output: AddFour(4) =8. The reason for failure may be that your NASM may be too old, or it's not 32-bit NASM (non-32-bit NASM doesn't recognize the coff object file format), or other unimaginable reasons.
_____________________________________________________________________________________
5 Related licenses, disclaimers, and others
This document is written by me referring to some documents on http://delorie.com/djgpp. A considerable part is directly from those documents, so I only retain the copyright of the Chinese translation, but you can freely reprint and modify it!
Since I really haven't used DJGPP for a long time and haven't had time to study carefully, I can't guarantee that the relevant content in this document is absolutely correct. If it causes some disastrous consequences to you, I won't be responsible!
If you have any questions, please contact me by email. My email is: xy_god@163.com
You can also leave a message on my homepage. My homepage is: http://www.xygod.pc5.org
Finally, I wish you a happy time! ^-^
临河居士
http://www.xygod.pc5.org
Floor 2 Posted 2004-05-20 00:00 ·  中国 黑龙江 哈尔滨 联通
中级用户
★★
Credits 226
Posts 51
Joined 2004-04-16 00:00
22-year member
UID 22666
Gender Male
Status Offline
Great dedication, give it a thumbs up!
Floor 3 Posted 2006-02-17 16:57 ·  中国 广东 佛山 三水区 电信
初级用户
Credits 28
Posts 10
Joined 2006-02-13 11:10
20-year member
UID 50286
Status Offline
Good job, upvote!!!1
Forum Jump: