Author Topic: combining multiple asm files, mouse position  (Read 14714 times)

Offline lukassevc

  • Jr. Member
  • *
  • Posts: 5
combining multiple asm files, mouse position
« on: March 28, 2019, 10:02:08 PM »
Hi! I am Lukas and I have a problem, I am writing my own OS using NASM and my emulator in QEMU. I have my bootloader and i want to use that bootloader only to call function from other file to start all my OS because bootloader's width is only 512  bytes with 2 bytes for telling BIOS to boot from it. When I try %include "first.asm", compiler told me that he can't found first.asm which was in the same folder. Second is that I want to read a mouse position or mouse move ( how much it does move from previous position), I know that in application ( for example on MS-DOS ) it is do by using INT 33h, but I think that without another OS it won't work , so my question is how to do it ( I have USB mouse ).

PS: Sorry for mistakes, if any, I am not from english speaking country.

Offline fredericopissarra

  • Full Member
  • **
  • Posts: 373
  • Country: br
Re: combining multiple asm files, mouse position
« Reply #1 on: March 29, 2019, 03:30:32 PM »
PS: Sorry for mistakes, if any, I am not from english speaking country.

I am not from an english speaking country as well (Brazil)... ;)

Hi! I am Lukas and I have a problem, I am writing my own OS using NASM and my emulator in QEMU. I have my bootloader and i want to use that bootloader only to call function from other file to start all my OS because bootloader's width is only 512  bytes with 2 bytes for telling BIOS to boot from it. When I try %include "first.asm", compiler told me that he can't found first.asm which was in the same folder.

Did you try to declare the symbol as extern and link the object files? %include should work, but you can say to NASM where to find the include files with -I option...

Second is that I want to read a mouse position or mouse move ( how much it does move from previous position), I know that in application ( for example on MS-DOS ) it is do by using INT 33h, but I think that without another OS it won't work , so my question is how to do it ( I have USB mouse ).

INT 0x33 only works with there is a mouse driver installed (old MS-DOS), this is not part of ROM-BIOS. You have to deal with the keyboard controller (yep... both are serial devices) or directly with USB via the Platform Controller Hub memory mapped address space for this device (not easy)...

if you are confortable reading portuguese, I have an article showing how to do it...

Offline fredericopissarra

  • Full Member
  • **
  • Posts: 373
  • Country: br
Re: combining multiple asm files, mouse position
« Reply #2 on: March 29, 2019, 04:09:32 PM »
Here's the attempt to translate my article to english (making it brief)... The text is abour PS/2 mouse (USB or not it works!) and uses the old Turbo C 2.01, which is easy to transpose to real mode asm...

The PS/2 Mouse is attached to IRQ12, so we need a handler:

Code: [Select]
#define CLAMP(x,_min,_max) \
{ \
  if ((x) < (_min)) (x) = (_min); else \
  if ((x) > (_max)) (x) = (_max); \
}
 
/* Screen max x-pos and x-pos (starting from 0). */
#define MAXX 79
#define MAXY 24
 
/* For testing purposes I'm using (39,12) as the initial coordinates.
   the middle of the text mode 3 screen. */
char buttons;
int mouse_x = 39;
int mouse_y = 12;
int mouse_ok = 0; // if we have all 3 above data ready, 1 - otherwise, 0.
static int first_time = 1;
 
void interrupt irq12isr(void)
{
  /* mouse will provide coordinates and
     button status, one by one, each time it requests an
     interruption... We'll store in this buffer...
     buffer[1] is x-delta, buffer[2] is y-delta and buffer[0] are the buttons. */
  static char buffer[3];
  static int pos = 0;
 
  /* I don't know why, but we must discard the first data. */
  if (first_time)
  {
    first_time = 0;
    inportb(0x60);
    goto exit_isr;
  }
 
  buffer[pos++] = inportb(0x60);
  if (pos == 3)
  {
    pos = 0;
 
    /* I want just the button states... */
    buttons = buffer[0] & 7;
 
    /* Divide delta by to to make delta less sensible. */
    mouse_x += buffer[1] / 2;
    mouse_y -= buffer[2] / 2;
 
    /* We don't want the mouse cursor out of the screen,
       won't we? */
    CLAMP(mouse_x, 0, MAXX);
    CLAMP(mouse_y, 0, MAXY);
 
    mouse_ok = 1;
  }
 
exit_isr:
  /* Sends EOI to the PICs */
  outportb(0xa0, 0x20);
  outportb(0x20, 0x20);
}

Now, we need to initialize the Interrupt vector 0x12, send commands to the mouse so it will generate interrupt requests, unmask the secondary PIC IRQ 12... Below, mouse_uninit() is listed as well...
Code: [Select]
static void interrupt (far *oldisr)(void);
 
void mouse_init(void)
{
  unsigned char kbdc_cw;
 
  disable();
  mask_irqs();
 
  // Adjust the new ISR for IRQ 12 on vector 0x74.
  oldisr = getvect(0x74);
  setvect(0x74, irq12isr);
 
  // Disable primary and auxiliar devices on KBDC.
  kbdc_wait(1, 0); outportb(0x64, 0xad);
  kbdc_wait(1, 0); outportb(0x64, 0xa7);
 
  // Turn on IRQ12 on KBDC.
  kbdc_wait(1, 0); outportb(0x64, 0x20);
  kbdc_wait(0, 0); kbdc_cw = inportb(0x60) | 2;
  kbdc_wait(1, 0); outportb(0x64, 0x60);
  kbdc_wait(1, 0); outportb(0x60, kbdc_cw);
 
  // Now we can re-enable the keyboard...
  kbdc_wait(1, 0); outportb(0x64, 0xae);
 
  // ... and enable mouse (auxiliar device).
  kbdc_wait(1, 0); ourtporb(0x64, 0xa8);
 
  // Configure mouse...
  mouse_write(0xff);    // reset and waits for 0xaa.
  while (mouse_read() != 0xaa);
 
  mouse_write(0xf6);    // puts mouse on default mode.
  while (mouse_read() != 0xfa); // waits for ACK.
 
  mouse_write(0xf4);   // enable mouse streamming mode...
  while (mouse_read() != 0xfa); // waits for ACK.
 
  kbdc_wait(1, 0);    // Waits for mouse readiness...
 
  unmask_irqs();
  enable();
}

void mouse_uninit(void)
{
  unsigned char kbdc_cw;
 
  disable();
 
  // Mask IRQ 12.
  outportb ( 0xa1, inportb ( 0xa1 ) | ( 1 << 4 ) );
 
  // Desable mouse.
  mouse_write ( 0xf5 );
  while ( mouse_read() != 0xfa ); // Ack
 
  // Disable auxiliary device.
  kbdc_wait ( 1, 0 ); outportb ( 0x64, 0xa7 );
 
  // Disable IRQ12 on KBDC.
  kbdc_wait ( 1, 0 ); outportb ( 0x64, 0x20 );
  kbdc_wait ( 0, 0 ); kbdc_cw = ( inportb ( 0x60 ) & ~2 );
  kbdc_wait ( 1, 0 ); outportb ( 0x64, 0x60 );
  kbdc_wait ( 1, 0 ); outportb ( 0x60, kbdc_cw );
 
  // Set the old IRQ 12 vector 0x74...
  setvect ( 0x74, oldvect );
 
  enable();
}
The mask_irqs() and unmask_irqs() just masks (disable) and unmasks (enable), respectively, IRQ 1 (keyboard) and IRQ 12 (mouse). enable() and disable() are "CLI" and "STI" instructions.

Here are mouse_read(), mouse_write() and kbdc_wait() routines:
Code: [Select]
/* buffer = 0 (output) or 1 (input).
   auxiliary = 0 (keyboard), 1 (mouse). */
void kbdc_wait(int buffer, int auxiliary)
{
  int count = 0;
 
  // tries 65536 times...
  while (--count)
    if (!buffer)
    {
      // Exit if we have output data.
      if (inportb(0x64) & (auxiliary ? 0x21 : 0x01))
        break;
    }
    else
      // Input is free?
      if (!(inportb(0x64) & 0x02))
        break;
}

void mouse_write(unsigned char data)
{
  kbdc_wait(1, 0); outportb(0x64, 0xd4);
  kbdc_wait(1, 0); outportb(0x60, data);
}
 
unsigned char mouse_read(void)
{ kbdc_wait(0, 1); return inportb(0x60); }
Here a test program fragmetn to test it:
Code: [Select]
void cursor(int x, int y, int draw)
{
  char far *ptr = MK_FP(0xb800, 160*y+2*x+1);
  *p = draw ? 0xf0 : 7;
}

void main(void)
{
  int oldx = mouse_x;
  int oldy = mouse_y;
 
  clrscr();
  cputs("Hit any key to stop...");
 
  mouse_init();
 
  cursor(oldx, oldy, 1);  // show cursor.
  while (!kbhit())
    if (mouse_ok)
    {
      cursor(oldx, oldy, 0);  // hide cursor
      cursor(oldx = mouse_x, oldy = mouse_y, 1); // show cursor.
      mouse_ok = 0; // we're done until next update...
    }
 
  mouse_uninit();
}

The result is in the attachment (GIF animated)...

I hope it helps!

Offline debs3759

  • Global Moderator
  • Full Member
  • *****
  • Posts: 224
  • Country: gb
    • GPUZoo
Re: combining multiple asm files, mouse position
« Reply #3 on: March 29, 2019, 05:06:37 PM »
I recommend checking the source code for ctmouse (CuTe Mouse), a compact mouse driver written in asm. It's not written for nasm, but shouldn't be hard to translate if you know enough to write an OS.

CuteMouse 1.9.1 https://mirrors.pdp-11.ru/_commodore64/sta.c64.org/dosprg/cutemouse191.zip
CuteMouse 2.1b4 (with added wheel support) https://mirrors.pdp-11.ru/_commodore64/sta.c64.org/dosprg/cutemouse21b4.zip
My graphics card database: www.gpuzoo.com

Offline lukassevc

  • Jr. Member
  • *
  • Posts: 5
Re: combining multiple asm files, mouse position
« Reply #4 on: March 29, 2019, 05:23:39 PM »
PS: Sorry for mistakes, if any, I am not from english speaking country.

I am not from an english speaking country as well (Brazil)... ;)

Hi! I am Lukas and I have a problem, I am writing my own OS using NASM and my emulator in QEMU. I have my bootloader and i want to use that bootloader only to call function from other file to start all my OS because bootloader's width is only 512  bytes with 2 bytes for telling BIOS to boot from it. When I try %include "first.asm", compiler told me that he can't found first.asm which was in the same folder.

Did you try to declare the symbol as extern and link the object files? %include should work, but you can say to NASM where to find the include files with -I option...

Second is that I want to read a mouse position or mouse move ( how much it does move from previous position), I know that in application ( for example on MS-DOS ) it is do by using INT 33h, but I think that without another OS it won't work , so my question is how to do it ( I have USB mouse ).

INT 0x33 only works with there is a mouse driver installed (old MS-DOS), this is not part of ROM-BIOS. You have to deal with the keyboard controller (yep... both are serial devices) or directly with USB via the Platform Controller Hub memory mapped address space for this device (not easy)...

if you are confortable reading portuguese, I have an article showing how to do it...

When you talked about declaring symbol as extern, I tested it and it works ( NASM compiler didn't throw any error ) also using %include "first.asm" and using -I and path to first.asm, it worked too! But it NASM from that two files made one file which contains my bootloader and also my first.asm so it wasn't bootloader and OS it was one file that contains that two files, can you please tell me how I can make separate file for bootloader and separate file for OS or how to link two or more bin ( which are output files for my project ) files? And about that mouse, i will first learn more assembler and I first try make CLI OS and once in future I will try to make GUI OS. Also when You told me that you are from Brazil, I am from Slovakia, it is in middle Europe, near Poland ( from south of Poland ), Austria ( from east of Austria ) and Ukraine ( from west of Ukraine )!   
« Last Edit: March 29, 2019, 05:36:26 PM by lukassevc »

Offline debs3759

  • Global Moderator
  • Full Member
  • *****
  • Posts: 224
  • Country: gb
    • GPUZoo
Re: combining multiple asm files, mouse position
« Reply #5 on: March 30, 2019, 12:51:53 AM »
Check out my FAT12 boot sector code. It will be easy to change to FAT16 (in fact, that should free up a few bytes for extra code) or whatever file system you are using.. It is self documenting (comments in English, but all are descriptive). All code is open source, so you are free to pick out any parts that you find useful.

https://forum.nasm.us/index.php?topic=2265.0
My graphics card database: www.gpuzoo.com