Problem with far pointers (16 bit real mode)

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
drunkenfox
Member
Member
Posts: 46
Joined: Tue Mar 13, 2012 10:46 pm

Problem with far pointers (16 bit real mode)

Post by drunkenfox »

I currently have a real mode c "kernel" (it's only in its early stage) that i compile with watcom's toolchain. The kernel gets loaded with cs being 0x800, which matches the linker script's segments and offset definitions. I skimmed through watcom's manual and used the __segment modifier as so:

Code: Select all

__segment screen = 0xb800;
char __based(void)* scrptr = 0;

while (scrptr < 80 * 25) {
      *(screen:>scrptr) = '!';
      scrptr += 2;
}
Dissasembly:

Code: Select all

                 mov     ds:word_911E, 0B800h
seg000:1014                 xor     ax, ax
seg000:1016                 mov     ds:word_911C, ax
seg000:1019                 jmp     short loc_9023
seg000:101B ; ---------------------------------------------------------------------------
seg000:101B
seg000:101B loc_901B:                               ; CODE XREF: sub_9000+35j
seg000:101B                 cmp     ds:word_911C, 7D0h
seg000:1021                 jnb     short loc_9037
seg000:1023
seg000:1023 loc_9023:                               ; CODE XREF: sub_9000+19j
seg000:1023                 mov     bx, ds:word_911C
seg000:1027                 mov     es, ds:word_911E
seg000:102B                 mov     byte ptr es:[bx], 21h ; '!'
seg000:102F                 inc     bx
seg000:1030                 inc     bx
seg000:1031                 mov     ds:word_911C, bx
seg000:1035                 jmp     short loc_901B
-which fills the screen as intended with exclamation marks. However, this code just doesn't do anything and seems to get the IP register lost in memory as any following code doesn't get executed:

Code: Select all

char __far* text = 0xb8000;

while (i < 80 * 25) {
      text[i] = '?';
      i += 2;
}
Disassembly yields the following:

Code: Select all

loc_9037:                               ; CODE XREF: sub_9000+21j
seg000:1037                                         ; sub_9000+53j
seg000:1037                 mov     ax, ds:word_8008    [just a zero in the datasegment]
seg000:103A                 cmp     ax, 7D0h
seg000:103D                 jge     short loc_9055
seg000:103F                 mov     bx, 912h
seg000:1042                 mov     es, bx
seg000:1044                 assume es:nothing
seg000:1044                 mov     bx, es:0
seg000:1049                 add     bx, ax
seg000:104B                 mov     byte ptr [bx], 3Fh ; '?'
seg000:104E                 add     ds:word_8008, 2
seg000:1053                 jmp     short loc_9037
Is there a way to get the far pointer method to work like the segment offset method? I want to be able to use subscripts, especially when I start doing heavy lifting in non-text modes.
;goodbye OS, hello BIOS
mov eax, FFFFFFF0h
jmp eax
alexfru
Member
Member
Posts: 1112
Joined: Tue Mar 04, 2014 5:27 am

Re: Problem with far pointers (16 bit real mode)

Post by alexfru »

This looks strange. AFAIK, far pointers must be initialized using the MK_FP(seg, ofs) macro as the initializer. It should come from <dos.h>.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Problem with far pointers (16 bit real mode)

Post by Combuster »

I remember that you have to actually use it that way in Turbo C or it wouldn't work. IIRC it expands to 0xb8000000 rather than 0x000b8000 to match an explicit segment and offset word.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
drunkenfox
Member
Member
Posts: 46
Joined: Tue Mar 13, 2012 10:46 pm

Re: Problem with far pointers (16 bit real mode)

Post by drunkenfox »

alexfru wrote:This looks strange. AFAIK, far pointers must be initialized using the MK_FP(seg, ofs) macro as the initializer. It should come from <dos.h>.
Yes, that worked. Thank you.
;goodbye OS, hello BIOS
mov eax, FFFFFFF0h
jmp eax
Post Reply