How can i do a reverse line feed?
Let's say i have the following code:
.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.
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.
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.
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)
At 0x2 is different because of a 2 byte difference in size between the two compared files...
Hi,
I made a subroutine and modified your program to call it.
see the attachment.
Cheers,
Steve N.
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.
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
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;
}
}