6

I'm a beginner at 8086 assembly. I'm learning from an old early 90s book I found in a thrift store. I thought it might be fun to program like it's 1992.

Anyway I'm done with the book and now i've written a few programs at the command prompt on my old Win95 laptop.

I'm having issues with this one not working as intended after switching over to using the 'les' instruction. However it did work when I set up the ES and DI registers with the appropriate address manually.

;************************************
;   STACK SEGMENT
;************************************

TheStack SEGMENT STACK      ;STACK specifies the stack segment

    db 64 dup (THESTACK)    ;reserves 512 bytes for the stack

TheStack ENDS

;************************************
;   END STACK SEGMENT
;************************************

;************************************
;   DATA SEGMENT
;************************************

Data SEGMENT

BufAddr DD 0b8000000h

Data ENDS

;************************************
;   END DATA SEGMENT
;************************************

;************************************
;   CODE SEGMENT
;************************************

Code SEGMENT

assume CS:Code,DS:Data

MAIN PROC

Start: ;execution begins

    ;setup input for stosw
    les di, DWORD PTR BufAddr
    mov cx,0f4fh  ;cx contains the number of times stosw will loop
    cld

    ;draw smileys
    mov ax,0f01h ;0f is the text attribute for white on black, 01 is the hex code for a smiley
    rep stosw ;write it all to the buffer

   ;EXIT
    mov AH,4CH ;Setup the terminate dos process service 
    mov AL,0 ;ERRORLEVEL takes 0
    int 21H  ;return to dos

MAIN ENDP 

Code ENDS 

;************************************
;   END CODE SEGMENT
;************************************

END Start ;Start is the Main procedure

Okay, so this program is supposed to draw a bunch of smiley ascii characters in the command prompt window, but it's not working.

It does work when I replace the 'LES' line with the following lines of code.

mov bx,0b800h
mov es,bx
xor di,di

Doesn't the 'LES' instruction when used with the BufAddr variable accomplish the same thing as the previous three lines of code?

When I debug the compiled exe (I'm using MASM 6.11 as the compiler) I notice that the ES and DI registers are not being loaded with the correct values.

bad
  • 939
  • 6
  • 18
  • What values are being loaded into es and di instead of the correct values? – fuz Aug 19 '16 at 16:04
  • 6
    Try adding `mov ax, SEG data` and `mov ds, ax` statements at the start of your code. – Ross Ridge Aug 19 '16 at 16:13
  • Ross beat me to it. Although you have `assume CS:Code,DS:Data` in your assembly file, this does not actually set these segment registers. It gives a hint as to what they are suppose to hold. Since the assembler doesn't generate code to set the data segment up and point it at the segment `Data` you are forced to do it yourself. As Ross suggest `mov ax, SEG data` `mov ds, ax` should work. The reason your code doesn't work is because without properly initializing _DS_ at the start of your program the instruction `les di, DWORD PTR BufAddr` will load `BuffAddr` from the wrong memory location. – Michael Petch Aug 19 '16 at 16:19
  • 1
    `les di, DWORD PTR BufAddr` is the same as `les di, DWORD PTR [DS:BufAddr]` the default segment register for the memory load is _DS_ . If _DS_ is wrong then it will fail to load from the proper memory address, – Michael Petch Aug 19 '16 at 16:22
  • 1
    Note that `db 64 dup (THESTACK)` doesn't assemble for me. I'd suggest using `db 512 dup (?)` instead. – Ross Ridge Aug 19 '16 at 17:19
  • @Ross Ridge Sorry it was a typo. It was supposed to be `db 64 dup ("THESTACK")` – bad Aug 27 '16 at 03:31

1 Answers1

7

Before loading the segment and offset from RAM, you need to set the DS register to actually point to your data segment. By default, DS points to your PSP, which isn't the place you want it to point to.

fuz
  • 88,405
  • 25
  • 200
  • 352
  • I want ES to hold the value 0b800h, and DI to hold 0. B800:0000 is the address of the DOS refresh buffer. – bad Aug 19 '16 at 16:04
  • @Proughgrammor What values are loaded into ES and DI instead of the correct values? You mention that you saw wrong values being loaded, what were these? – fuz Aug 19 '16 at 16:06
  • 9FFFh is loaded into ES, and 20CDh is loaded into DI. – bad Aug 19 '16 at 16:08
  • @Proughgrammor Did you make sure that `DS` is loaded with the right segment when `main` starts? – fuz Aug 19 '16 at 16:12
  • 1
    Oops no! Maybe that's the issue. – bad Aug 19 '16 at 16:13
  • @Proughgrammor Tell me if that's the case so I can rewrite my answer. – fuz Aug 19 '16 at 16:16
  • 1
    Thanks, it works now, but I didn't have to swap the value of the variable around. Maybe the assembler does that on it's own? – bad Aug 19 '16 at 16:18
  • @Proughgrammor It appears that my original suspicion (that you need to swap the values around) was wrong. – fuz Aug 19 '16 at 16:32
  • 1
    Actually the value in DS points to the PSP, which in the EXE format executable is the wrong place. – Ross Ridge Aug 19 '16 at 16:53
  • 2
    _DS_ is a determinate value when the EXE begins running (after the DOS EXE loader is finished). It just doesn't happen to be a value that won't point to the correct location. As Ross points out that value DOS EXE loader stores into _DS_ is the Program Segment Prefix. – Michael Petch Aug 19 '16 at 17:37