The MASM Forum

Miscellaneous => 16 bit DOS Programming => Topic started by: bugthis on August 21, 2024, 11:21:11 PM

Title: How can i do a reverse line feed? (jump the cursor to the previous line.)
Post by: bugthis on August 21, 2024, 11:21:11 PM
How can i do a reverse line feed?

Let's say i have the following code:
Code (asm) Select
.MODEL SMALL, C
.STACK 128

.DATA
STR1   DB "Hello World!", 13, 10, "$"
; Uncomment one of the following two lines:
; REV_LF DB 8Dh, 13, "$"     ; 8Dh character Reverse Line Feed didn't work
; REV_LF DB 1Bh, 7, 13, "$"  ; ESC-7 didn't work
STR2   DB "Hello in the Matrix!", 13, 10, "$"

.CODE
START:  MOV AX, @DATA
        MOV DS, AX

        ; print STR1
        MOV DX, OFFSET STR1
        MOV AH, 09h
        INT 21h

        ; do a reverse line feed
        MOV DX, OFFSET REV_LF
        MOV AH, 09h
        INT 21h

        ; print STR2
        MOV DX, OFFSET STR2
        MOV AH, 09h
        INT 21h

        MOV AH, 4Ch
        INT 21h
END START

STR2 should overwrite the output of STR1.
Thus a working REV_LF is required.
One REV_LF must be uncommented.

For REV_LF i tried to use character 8Dh:
https://unicode-explorer.com/c/008D (https://unicode-explorer.com/c/008D)

and ESC+7, which should be if I am not mistaken "1Bh, 7"
https://www.ibm.com/docs/en/zos/2.4.0?topic=descriptions-col-remove-reverse-line-feeds (https://www.ibm.com/docs/en/zos/2.4.0?topic=descriptions-col-remove-reverse-line-feeds)

But no variant works.
In both variants i get this output:
Hello World!
Hello in the Matrix!

I did not get this:
Hello in the Matrix!

So how can i jump back to the previous line with the cursor?

EDIT:
According to:
https://en.wikipedia.org/wiki/C0_and_C1_control_codes#C0_controls (https://en.wikipedia.org/wiki/C0_and_C1_control_codes#C0_controls)
8Dh is the same as 1Bh, 4Dh (ASCII M). So the 7 on the IBM page doesn't seem to be correct. At least it doesn't seem to be standard compliant.
So i tried this:
REV_LF DB 1Bh, 4Dh, 13, "$"  ; ESC-M didn't work
But that didn't work either.
Title: Re: How can i do a reverse line feed? (jump the cursor to the previous line.)
Post by: _japheth on August 22, 2024, 12:19:07 AM
Quote from: bugthis on August 21, 2024, 11:21:11 PMBut that didn't work either.

IIRC, for ESC-sequences to work in DOS the ANSI.SYS driver must have been loaded in config.sys.
Title: Re: How can i do a reverse line feed? (jump the cursor to the previous line.)
Post by: FORTRANS on August 22, 2024, 12:27:32 AM
Hi,

  As _japheth says, load ANSI.SYS in your CONFIG.SYS to
use escape commands.

  Or use the BIOS interrupts.

INT 10,02, Set Cursor Position

  Sets the cursor's position.  If the page is the active page
the display is updated.

INPUT AH = 2
      BH = Page Number
      DH = Row (0 is top row)
      DL = Column (0 is leftmost column)

OUTPUT Cursor position changed

Note: DH, DL = 0, 0 = Upper Left

INT 10,03, Get Cursor Status

  Read current cursor position and configuration.

INPUT AH = 3
      BH = Page Number

OUTPUT DH = Row of cursor (0 is top row)
      DL = Column (0 is leftmost column)
      CH = Top line of cursor in character cell
      CL = Bottom line.

Regards,

Steve N.
Title: Re: How can i do a reverse line feed? (jump the cursor to the previous line.)
Post by: bugthis on August 22, 2024, 01:30:58 AM
Thanks to both of you.

ANSI.SYS was loaded (in this case NANSI.SYS from FreeDOS).
But I still found a solution.
I had to change the following line from:

REV_LF DB 1Bh, 4Dh, 13, "$"  ; ESC-M didn't work even when ANSI.SYS is loaded
to:
REV_LF DB 1Bh, "[1A", 13, "$"  ; This works with ANSI.SYS loaded.
With this small change it works. I don't know what else is done by [1A, apart from [ defining the start of the ESC sequence in the string and the number standing for the number of lines to go back. I found this solution in the assembly language book I'm working with. I think I'll compare the hexdump of the two solutions.

Thanks for the tip about the BIOS interrupt routine. I would actually like this solution better, but it would mean additional code, as I would first have to determine the cursor position and then calculate where the cursor should be placed. The ANSI solution is simpler and is sufficient for now. But I will certainly use the solution with the BIOS routines in another case.

BTW, since ANSI.SYS was mentioned. Is there an easy way to check in assembler if ANSI.SYS is loaded?

EDIT:
Okay, i did a hexdump comparison. See the screenshots.
I wonder what this z instead of x at address 0x02 and # instead of ! at address 0x44 means?

Strings only:
(https://i.postimg.cc/CdLbNVrj/text-only.png) (https://postimg.cc/CdLbNVrj)

All binary code as hex numbers:
(https://i.postimg.cc/2V1vs7Dy/hex-comparison.png) (https://postimg.cc/2V1vs7Dy)



Title: Re: How can i do a reverse line feed? (jump the cursor to the previous line.)
Post by: zedd151 on August 22, 2024, 06:50:36 AM
At 0x2 is different because of a 2 byte difference in size between the two compared files...
Title: Re: How can i do a reverse line feed? (jump the cursor to the previous line.)
Post by: FORTRANS on August 22, 2024, 07:51:51 AM
Hi,

   I made a subroutine and modified your program to call it.
see the attachment.

Cheers,

Steve N.
Title: Re: How can i do a reverse line feed? (jump the cursor to the previous line.)
Post by: FORTRANS on August 23, 2024, 01:16:18 AM
Hi,

Quote from: bugthis on August 22, 2024, 01:30:58 AMBTW, since ANSI.SYS was mentioned. Is there an easy way to
check in assembler if ANSI.SYS is loaded?

  Some reference information from "Undocumented DOS", Second
Edition, Andrew Schulman et. al., Addison Wesley, 1994.

QuoteNotes: COMMAND.COM 3.2 and 3.3 compare the INT 29h vector
against the INT 20h vector and assume that ANSI.SYS is installed
if the INT 29h segment is larger.

HTH,

Steve N.
Title: Re: How can i do a reverse line feed? (jump the cursor to the previous line.)
Post by: sinsi on August 23, 2024, 01:29:16 AM
Quote from: bugthis on August 22, 2024, 01:30:58 AMBTW, since ANSI.SYS was mentioned. Is there an easy way to check in assembler if ANSI.SYS is loaded?
Ralf Brown's Interrupt List
INT 2F - DOS 4.0+ ANSI.SYS - INSTALLATION CHECK

    AX = 1A00h
Return: AL = FFh if installed

Title: Re: How can i do a reverse line feed? (jump the cursor to the previous line.)
Post by: NoCforMe on August 26, 2024, 04:56:21 AM
Here's a program I wrote decades ago that shows all installed devices. You could modify it to search for a particular driver. It uses undocumented INT 21 function 52h.

/********************************
* SHOWDEVS.C
*
* 12/16/89 by me
********************************/

#include <stdio.h>
#include <dos.h>
#include <ctype.h>

struct SREGS segregs;
union REGS inregs,outregs;

main()
{
unsigned long far *devptr;
unsigned char far *nameptr;
char ioctl;

inregs.h.ah = 0x52; /* "Undocumented" (officially, at least) function */
int86x(0x21,&inregs,&outregs,&segregs);
segread (&segregs);
devptr = MK_FP (segregs.es, outregs.x.bx + 0x22);
devptr = *devptr;
printf("\nThe following devices are installed:\n\n");
printf(" address   type   name/# units\tIOCTL?\n-----------------------------------------\n");
while (FP_OFF (devptr) != 0xFFFF)
{
nameptr = (char far *)devptr;
if ((*(nameptr+5)&0x40)!=0)
ioctl='y';
else ioctl='n';
if ((*(nameptr+5)&0x80)!=0)
/* Character device: */
printf("%Fp   char.   %8.8Fs\t  %c\n",devptr,nameptr+10,ioctl);
/* Block device: */
else
printf("%Fp   block     [%c]\t  %c\n",devptr,*(nameptr + 10)+'0',ioctl);
devptr = *devptr;
}
}