0

But it just prints an empty string, unless I set the address to something like 0x00 or 0x20, then it prints some ascii characters . Also I am new to assembly and x86 segmentation so I barely know if I am doing things right .

INT 10H 1300H: Display String

 Expects: AX    1300H
          BH    video page
          BL    video attribute
          CX    length of string
          DH,DL row,column to start writing
          ES:BP address of start of text to write
          ──────────────────────────────────────────────────────────────────
 Returns: (none)

So far my code is:

            // Stack Segment

            new MovInstruction_Register16Bit_Immediate16Bit(Register8086.AL, offset),
            new MovInstruction_Segment16Bit_RegisterImmediate16Bit(Register8086.DL, Register8086.AL),
            new MovInstruction_Register16Bit_Immediate16Bit(Register8086.AH, 0x00),
            new MovInstruction_Register16Bit_Immediate16Bit(Register8086.CH, size),

            // Extra Segment

            new MovInstruction_Register16Bit_Immediate16Bit(Register8086.BL, offset),
            new MovInstruction_Segment16Bit_RegisterImmediate16Bit(Register8086.AL, Register8086.BL),
            new MovInstruction_Register16Bit_Immediate16Bit(Register8086.BH, 0x00),

            // Main

            new MovInstruction_Register16Bit_Immediate16Bit(Register8086.AL, 0x1300),
            new MovInstruction_Register8Bit_Immediate8Bit(Register8086.BH, videoPage),
            new MovInstruction_Register8Bit_Immediate8Bit(Register8086.BL, videoAttribute),
            new MovInstruction_Register16Bit_Immediate16Bit(Register8086.CL, lengthOfString),
            new MovInstruction_Register8Bit_Immediate8Bit(Register8086.DH, row),
            new MovInstruction_Register8Bit_Immediate8Bit(Register8086.DL, column),
            //new MovInstruction_Register16Bit_Immediate16Bit(Register8086.CH, size),
            //new MovInstruction_Register16Bit_Immediate16Bit(Register8086.AH, offset),
            //new MovInstruction_Segment16Bit_RegisterImmediate16Bit(Register8086.AL, Register8086.AH),

And my disassembly is:

// Stack Segment

0x0000000000000000:  B8 00 7C    mov ax, 0x7c00
0x0000000000000003:  8E D0       mov ss, ax
0x0000000000000005:  BC 00 00    mov sp, 0
0x0000000000000008:  BD 01 00    mov bp, 1

// Extra Segment

0x000000000000000b:  BB 00 7C    mov bx, 0x7c00
0x000000000000000e:  8E C3       mov es, bx
0x0000000000000010:  BF 00 00    mov di, 0

// Main

0x0000000000000013:  B8 00 13    mov ax, 0x1300
0x0000000000000016:  B7 00       mov bh, 0
0x0000000000000018:  B3 4D       mov bl, 0x4d
0x000000000000001a:  B9 00 02    mov cx, 0x200
0x000000000000001d:  B6 00       mov dh, 0
0x000000000000001f:  B2 00       mov dl, 0
//0x0000000000000021:  BD 01 00    mov bp, 1
//0x0000000000000024:  BC 00 7C    mov sp, 0x7c00
//0x0000000000000027:  8E C4       mov es, sp
0x0000000000000029:  CD 10       int 0x10
  • Not all character are visible. For example the BELL character will not print. The tab character will add extra spaces. Normally when decompiling code the characters 0x00 to 0x20 you just display a period instead of the actual character. Your output looks very good. Been doing this for 45 years. – jdweng Oct 09 '22 at 09:22
  • I thought so too but, then: I tried to put the drive number from the DL register in memory at 7C00, I could not print it, Then I put the drive number to memory address 0x0 and printed from memory address 0x0 and there it was, it is something about the use of the segment registers that I am not doing right – Todor Yanev Oct 09 '22 at 09:24
  • Yeah it is something about the segment registers, if I put the drive number in address X for some reason I can only access it by additional zero to the address X0, it worked when I added the zero – Todor Yanev Oct 09 '22 at 09:34
  • You program uses a segment. The code is put at beginning of memory and increments. The stack point is put at end of memory and decrements. When you have a OS the operating system loads the application and assigns memory to the program. As part of the loading the stack segment are assigned so they do not conflict with other programs in a multi-user environment. You are just learning and the basics so you have a better understanding when you study OS. – jdweng Oct 09 '22 at 09:35
  • I corrected typos : 8086 is 20 bit addressing 0xFFFFF is maximum address. The segment register is the upper 16 bits. Each memory location can be addresses 65,000 different ways. ES : 0000 Ax : 0010 is same as ES : 0001 : Ax : 0001. Both are memory 0x00010 – jdweng Oct 09 '22 at 09:51
  • You did not use the DS segment register. If you are moving data the default is the DS, If you want to use another segment register you have to specify. If you are use ES than you have to load the ES, – jdweng Oct 09 '22 at 11:45
  • The BIOS interrupt does not say anything about using Data Segment. The way I understand it is, and I am probably wrong, the whole thing is a hierarchical pyramid where the top is the (S)tack (S)egment which contains master offset (S)tack (P)ointer and slave offset (B)ase (P)ointer, then there is the (E)xtra (S)egment offsetted by (D)estination (I)ndex the (D)ata (S)egment offsetted by (S)ource (I)ndex the (C)ode (S)egment offsetted by (I)instruction (P)ointer – Todor Yanev Oct 09 '22 at 12:43
  • You are correct about the DS. You cannot change the SS. When the OS load the program the SS:SP is assigned. You can only use memory that was allocated when the program was loaded. The BL should be a 1 so after you write nothing overwrites the data. Then will move the cursor to the end of your message. – jdweng Oct 09 '22 at 20:26
  • Is you program a "com" or an "exe"? You have to be careful of how you use memory. If you need memory the best thing is to use the existing stack space and make sure when you exit to restore the SP to same location when you program started. If you are familiar with the way c language passes parameters to a method you should do similar in assembly code. – jdweng Oct 09 '22 at 20:29

1 Answers1

0
    WriteString ws = new WriteString(
            videoPage: 0x00,
            videoAttribute: 0x4D,
            lengthOfString: 512,
            row: 0,
            column: 0,
            offset: 0x7C0, <------ This works !
            size: 0x0
            );

    AssemblyEditor assemblyEditor;

    assemblyEditor = new MicroLinker(
        new SaveDriveNumber(0x7C00),
        ws
        );

And this does not

        WriteString ws = new WriteString(
                videoPage: 0x00,
                videoAttribute: 0x4D,
                lengthOfString: 512,
                row: 0,
                column: 0,
                offset: 0x7C00,
                size: 0x0
                );

        AssemblyEditor assemblyEditor;

        assemblyEditor = new MicroLinker(
            new SaveDriveNumber(0x7C00),
            ws
            );
  • An 8086 machine has 640K of RAM at beginning of 1M memory. The stack was set to top of 640K and moved down. EPROM was at the top of the 1M. In between the the stack and the RAM was the hardware I/O including the monitor cards. The OS was loaded at beginning of RAM and programs were loaded after the OS. I still have all my DOS manuals, and assembly code books. – jdweng Oct 09 '22 at 09:49
  • @jdweng: That's the size of the address-space in an IBM-PC. Not all 8086 machines actually had a full 1MiB of RAM. Also, apparently different BIOSes load an MBR bootloader with different initial SS:SP. (So you shouldn't assume its location when you load another sector from disk, in case the location you pick happened to be where the stack is.) An MBR bootloader is loaded at linear address 0x7C00, and using space right *below* that for your stack is a common recommendation. Or [Which value should be used for SP for booting process?](https://stackoverflow.com/q/10598802) have other ideas. – Peter Cordes Oct 09 '22 at 17:31
  • Thus `SS=0`/`SP=7C00` is sensible. But `SS=07C0/SP=0` like in the question will lead to the stack wrapping on the first push to `07C0:FFFE`, linear address `0x17bfe`. But for static data addressing, `ES=DS=07C0` puts the first byte of the MBR at offset `0`. See also [Boot loader doesn't jump to kernel code](https://stackoverflow.com/a/32705076) - Michael Petch's general tips for (legacy BIOS) bootloaders. – Peter Cordes Oct 09 '22 at 17:32
  • @PeterCordes : All 8086 had 1M memory address. The max RAM was 640K (could be less). The SS was always set to the MAX RAM location of the machine. Read my comment in OP posting. The bootloaded was EPROM at top of 1M. A 8086 micro when reset loaded the ES register with the value at 0xFFFFC where there was EPROM. The IP was reset to zero So the start of the program was inside the EPROM (bootloader). Then the INT were loaded starting at 0x00000. The INTs initially were pointed to interrupt handlers inside the EPROM. – jdweng Oct 09 '22 at 23:36
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Oct 13 '22 at 00:05