Let's Code MS DOS 0x29: Extended Memory XMS

Поделиться
HTML-код
  • Опубликовано: 6 окт 2024
  • In the previous episode we learned how to use Expanded Memory even down to the original IBM PC. From the IBM AT and other 286 machines onwards we can use Extended Memory instead. It doesn't require any additional hardware and allows you to use more than 640K of memory in real mode MS DOS programs.
    Support me on Patreon: / root42
    Support me on Ko-Fi: ko-fi.com/root42
    Support me on PayPal: paypal.me/Arne...
    Support me on RUclips: / @root42
    Music: A Little Wonder by Spino2006
    Source Code: codeberg.org/r...

Комментарии • 36

  • @deimos13710
    @deimos13710 2 месяца назад +21

    I need this video 35 years ago

  • @robertsundling
    @robertsundling 3 месяца назад +5

    This really brought me back to the early 90’s! Good stuff. This is exactly how I had to do things before I could afford tools to program in protected mode. Thanks for this trip down memory lane-pun intended. By the way, don’t forget to add 1023 to the number of bytes you’re allocating (when calculating total_size) before dividing by 1024, since 320*200 isn’t divisible by 1024. (You’re technically 512 bytes short there, with N_FRAMES 35.) 😃

    • @root42
      @root42  3 месяца назад +1

      Yeah, I think I fixed that in the final code. You have to round up to the next kilobyte due to the way XMS allocations work.
      EDIT: Yes, I did:
      total_size = ((long)N_FRAMES * 320 * 200) / 1024 + 1;
      The +1 fixes that exact issue.

  • @Kelimion
    @Kelimion 2 месяца назад +1

    Stumbled across this the other day, and I'm glad I did. What a blast from the past. Such a criminally underrated video series, shared with a community of fellow greybeards and would-be greybeards.

  • @richardericlope3341
    @richardericlope3341 2 месяца назад +2

    Very nostalgic.
    I used to develop a gamedev library that extended qbasic and it had some nice XMS based sprite routines.
    ie, Load all assets to XMS, then fetch when needed. It was fast enough for tilebased games and you never need to map memory(unlike EMS), once you finish setting it up.
    I can just call xmsSprite(....) and it would just do it like conventional RAM. You still have to pass an XMS handle as argument but that was it.
    I temember it still worked on Windows 98 SE.

    • @root42
      @root42  2 месяца назад +2

      Really for qbasic interpreter? Amazing. Or did you do it for QuickBasic compiler (still amazing).

    • @richardericlope3341
      @richardericlope3341 2 месяца назад +1

      @@root42 It should work with both. The library is made for qb45 but the assembly can be parsed to opcodes by an app we made so that it can be callable by "call absolute".
      Does your channel allow for external links? The library was on github (not mine).

    • @root42
      @root42  2 месяца назад

      Not sure about external links. Just try!

  • @karlfoley
    @karlfoley 2 месяца назад +1

    Remember authoring a memory management course years ago. By forcing VGA to mono mode you were able to extend the 640KB limit to 700KB+ by including the VGA colour memory into the memory map

  • @AlexanderWeurding
    @AlexanderWeurding 2 месяца назад +2

    Thanks! Erg bedankt voor het delen!

  • @LeoOno
    @LeoOno 2 месяца назад

    wow, this is so nostalgic :) !

  • @alexloktionoff6833
    @alexloktionoff6833 2 месяца назад +1

    286 has LOADALL bug, which lets to setup segment registers and address full 16MB registers so XMS possible without standard protected mode enter/exit. Also there is a double trap trick for faster 286 protection mode exit.

    • @root42
      @root42  2 месяца назад +1

      Do you have a link for the bug? Would be an interesting read.
      The faster PM exit is indeed an improvement, but IIRC it is still not as fast as 386 PM/RM switch.

    • @alexloktionoff6833
      @alexloktionoff6833 2 месяца назад +1

      @@root42 Im trying to post the link, by tube removes my comment. You can find it in google by searching LOADALL 80286.

    • @alexloktionoff6833
      @alexloktionoff6833 2 месяца назад

      @@root42 you can find it by searching LOADALL 20286

    • @alexloktionoff6833
      @alexloktionoff6833 2 месяца назад

      you can find it by searching LOADALL 286

    • @root42
      @root42  2 месяца назад

      Ah yes, I think I read about it once. IIRC it‘s an undocumented opcode.

  • @maxmuster7003
    @maxmuster7003 2 месяца назад +1

    On 80386+ i like to use the 16 bit BIG real mode with DS,ES,FS,GS=4 gb and CS,SS=64 kb + A20 gate on. With VBE 2/3 bios we can write directly into the linear framebuffer with 32 bit data and 32 bit addresses using instructions with operand size prefix(hex 66) + addresss size prefix(hex 67). The 16 bit Big mode allows to use 16 bit DOS and BIOS function and himem.sys.

    • @root42
      @root42  2 месяца назад +1

      That’s a good idea. Saves a lot of switching.

    • @maxmuster7003
      @maxmuster7003 2 месяца назад

      @@root42 Here is the routine:
      072A:0100 FA CLI
      072A:0101 E470 IN AL,70
      072A:0103 0C80 OR AL,80
      072A:0105 E670 OUT 70,AL
      072A:0107 6631C0 XOR EAX,EAX
      072A:010A 8CC8 MOV AX,CS
      072A:010C A36D01 MOV [016D],AX
      072A:010F 66C1E004 SHL EAX,04
      072A:0113 6689C3 MOV EBX,EAX
      072A:0116 A3B201 MOV [01B2],AX
      072A:0119 A3BA01 MOV [01BA],AX
      072A:011C 66C1C810 ROR EAX,10
      072A:0120 A2B401 MOV [01B4],AL
      072A:0123 A2BC01 MOV [01BC],AL
      072A:0126 6631C0 XOR EAX,EAX
      072A:0129 B8A801 MOV AX,01A8
      072A:012C 6601C3 ADD EBX,EAX
      072A:012F C706A0012700 MOV WORD PTR [01A0],0027
      072A:0135 66891EA201 MOV [01A2],EBX
      072A:013A 9C PUSHF
      072A:013B 0F0116A001 LGDT [01A0]
      072A:0140 8CD2 MOV DX,SS
      072A:0142 0F20C0 MOV EAX,CR0
      072A:0145 0C01 OR AL,01
      072A:0147 0F22C0 MOV CR0,EAX
      072A:014A EA50010800 JMP 0008:0150
      -ucs:150 l1F
      072A:0150 B81000 MOV AX,0010
      072A:0153 8ED0 MOV SS,AX
      072A:0155 B81800 MOV AX,0018
      072A:0158 8ED8 MOV DS,AX
      072A:015A 8EC0 MOV ES,AX
      072A:015C 8EE0 MOV FS,AX
      072A:015E 8EE8 MOV GS,AX
      072A:0160 0F20C0 MOV EAX,CR0
      072A:0163 6683E0FE AND EAX,-02
      072A:0167 0F22C0 MOV CR0,EAX
      072A:016A EA70013407 JMP 0734:0170
      -ucs:170 l2F
      072A:0170 8ED2 MOV SS,DX
      072A:0172 9D POPF
      072A:0173 31C9 XOR CX,CX
      072A:0175 E464 IN AL,64
      072A:0177 2402 AND AL,02
      072A:0179 E0FA LOOPNZW 0175
      072A:017B 751A JNZ 0197
      072A:017D B0D1 MOV AL,D1
      072A:017F E664 OUT 64,AL
      072A:0181 31C9 XOR CX,CX
      072A:0183 E464 IN AL,64
      072A:0185 2402 AND AL,02
      072A:0187 E0FA LOOPNZW 0183
      072A:0189 75EE JNZ 0179
      072A:018B B0DF MOV AL,DF
      072A:018D E660 OUT 60,AL
      072A:018F 31C9 XOR CX,CX
      072A:0191 E464 IN AL,64
      072A:0193 2402 AND AL,02
      072A:0195 E0FA LOOPNZW 0191
      072A:0197 E470 IN AL,70
      072A:0199 247F AND AL,7F
      072A:019B E670 OUT 70,AL
      072A:019D FB STI
      072A:019E C3 RET
      -dcs:1A0 l8
      072A:01A0 00 00 00 00 00 00 00 00- ........
      -dcs:1A8 l8
      072A:01A0 -00 00 00 00 00 00 00 00 ........
      -dcs:1B0 l8
      072A:01B0 FF FF 00 00 00 9A 00 00- ........
      -dcs:1B8 l8
      072A:01B0 -FF FF 00 00 00 92 00 00 ........
      -dcs:1C0 l8
      072A:01C0 FF FF 00 00 00 92 FF FF- ........

    • @maxmuster7003
      @maxmuster7003 2 месяца назад

      After we find a VBE modenumber in the modelist of function 4F00 we can get the mode specific information with function 4F01 to check the resolution and if there is an address of the linear framebuffer. If we find the linear address we can add to the mode number hex 4000 to switch into the graphic mode for using the linear framebuffer.
      ----
      And if we want to use a refreshrate controlled graphic mode(VBE 3 only) we need a CRT table and to add hex 800 to the mode number. But we have to normalize the pixelclock before we can switch into this refreshrate controlled graphic mode.
      Example CRT table for 1024x768 with 100hz refreshrate using 19" CRT monitor with 96khz capacity:
      ;--------------------------------------
      CRTC DW 1456 ; horizontal Total in Pixel
      HORIANF DW 1122 ; horizontal Sync-Start in Pixel
      HORIEND DW 216 ; horizontal Sync-End in Pixel
      VERTOTA DW 814 ; vertical Total in Lines
      VERTANF DW 768 ; vertical Sync-Start in Lines
      VERTEND DW 42 ; vertical Sync-End in Lines
      DOIFLAG DB 04h ; Flag (interlaced,doubleScan,polarity)
      PIXCLOC DD 118309000 ; Pixel clock in hz
      REFRATE DW 10000 ; Refresh-Rate in 0.01 hz
      ;---------------------
      DB 40 dup (0)
      ;--------------------------------------
      Public (costfree) documentation from vesa. org(register/login):
      EEDIDguideV1.pdf
      vbe3.pdf

  • @arlandi
    @arlandi 2 месяца назад

    interesting to see this run on PCem or 86box. thanks for the video.

    • @root42
      @root42  2 месяца назад

      pcem and 86box emulate a real PC, so the results would probably look exactly like the real thing. DOSBox is peculiar, as it first and foremost emulates DOS, and only little bits of the PC, for performance reason.

  • @klausschmidt982
    @klausschmidt982 2 месяца назад

    total noob at asm and dos programming here: you first initialize the far pointer to the main XMS procedure from the returned segment and offset stored in es and bx respectively. Then you call this function using call es:[XMSPtr] but before that you overwrite es with ds which I don’t understand because I don’t how it ended up in ds.

    • @root42
      @root42  2 месяца назад +2

      Variables in Turbo C are always referenced as DS:[var] in inline assembly by default. However XMS requires DS to be loaded with different things. So we will use ES:[var] instead. But you can’t mov es, ds. That’s forbidden, so we take the long way around by first saving the state of ds: mov cx,ds and push cx. Then mov es,cx loads the value of ds into es. This allows us to call xmsptr via the data segment value in ES.

  • @breedband
    @breedband 2 месяца назад

    Vielen Dank

  • @djtomoy
    @djtomoy 2 месяца назад +1

    Why?

    • @maxmuster7003
      @maxmuster7003 2 месяца назад

      Without a memory manager we can only use 640 kb in the first mb RAM. The newest XMS-driver himem.sys can work with 4 giga byte of memory. So we can use the free memory above the first mega byte too to store pictures, sound, tables, routines of mashine code any data that we want in the XMS memory. We begin to load the data from the slow hdd at first into the main memory and use the XMS driver to store it in the XMS memory. Now we can get the data from the XMS driver very fast from memory to memory. Additional we can make a ram disk driver that based of XMS memory terminate and stay resident in the XMS memory.

    • @djtomoy
      @djtomoy 29 дней назад +1

      @@maxmuster7003 just get some more ram sticks and use them, easy

  • @WhiteFalconus
    @WhiteFalconus Месяц назад

    Have you managed to run any XMS functions from withing the BC/TC IDE or is that completely impossible? I have been using XMS for decades but always had to quit the IDE and run from DOS. When I try it in the IDE, I get no free XMS memory and the program crashes.

    • @root42
      @root42  Месяц назад

      TurboC would be fine IIRC. But Borland C++ reserves all XMS memory for itself. You do some tricks to allocate some memory beforehand and then free it afterwards.

    • @WhiteFalconus
      @WhiteFalconus Месяц назад

      @@root42 Oh, that sucks, I have always stayed with BC++ and dont want to leave it. I guess from now on I wont be able to run stuff from the IDE whenever I use XMS. Or when you say tricks, did you mean there is a way around that?

    • @root42
      @root42  Месяц назад

      A friend on the DOSReloaded forum wrote a small tool for himself that reserves a variable amount of MB in XMS, and prints the handle. Then after Borland C has started, he runs the same program again (e.g. from a shell) with this handle as a parameter, and it will free the memory. And then you have free XMS memory in Borland C. :)

    • @WhiteFalconus
      @WhiteFalconus Месяц назад

      @@root42 Nice trick! Will have to try that, thanks :)

    • @WhiteFalconus
      @WhiteFalconus Месяц назад

      @@root42 It works, what a cool trick, thank you!

  • @IExSet
    @IExSet 2 месяца назад

    Wow, i just cought video which not liked yet ! 😂