3 ms·
> I am a little bit freaked out by that because the pointer to the buffer is set before the IOCTL call; the code knowingly sets a pointer to a buffer into what
by mmastrac 2y ago
> I am a little bit freaked out by that because the pointer to the buffer is set before the IOCTL call; the code knowingly sets a pointer to a buffer into what looks like its code area. Let's hope they knew they were done with that part of the code, or it's just another interesting bug to dissect.
This is common in code without segmentation protection. CODE and DATA are convention. You can just specify a function, then a small buffer, then another function. .COM files in particular were easier to write with CS and DS pointing to the same region of memory, assuming you could fit both your code and inline buffers in 64kB.
The code explains what they are doing. Even more interesting, they're using their own stack too:
; 1 - This program uses its own internal stack. The stack space provided
; by DOS is used as an input buffer for transfering IBMBIO and IBMDOS.
;
; SYS is linked with the CODE segment followed by the DATA segment. The
; last symbol in DATA is BUF. It marks the end end of data and the
; start of the BUFfer. The BUFfer extends from here to SP. The first
; 6.5Kb (13 sectors) in BUFfer are used for up to 12 sectors of the FAT
; or the directory. In Main, the remaining space is set
; as follows:
; cdBuf = SP - ( FAT_BUF + BUF )
;
- mbbrutman 2y agoI looked at the call before and after to see what they had set the buffer to, and they clearly set the buffer to point into what is code. The executable is only 5KB and it's tiny; they had plenty of space in the segment to use a different part of the segment without purposefully blasting their own code. While it's common, it was still a terrible practice. If whatever was filling in that buffer changed, they could be blasting more code than they intended. (As indicated in what I wrote, I know it was common if they wanted to reuse the space. Device drivers do something similar when they are done with their init code.)
- mmastrac 2y agoHere's the code from DOS 3.3. I am reasonably sure they didn't intend to overwrite code -- you're probably just seeing a weird artifact where the failure case is leaving a dangling random value that happens to point into valid code. My guess is that DS isn't being maintained across the failing call to the IOCTL and ends up pointing to the wrong segment. DOSOutFH DW ? ; fh of DOS destination DumpMem: MOV DX,OFFSET DG:BUF+512 ; get offset of bios start MOV CX,pDOS ; beginning of next guy SUB CX,DX ; difference is length JZ DumpDos ; no bios to move MOV BX,BIOSOutFH ; where to output MOV AH,Write INT 21h ; wham retc ; error CMP AX,CX ; Did it work? JNZ WRERR ; No DumpDos: MOV DX,pDOS ; beginning of dos MOV CX,pDOSEnd ; end of dos SUB CX,DX ; difference is length retz ; if zero no write MOV BX,DOSOutFH ; where to output MOV AH,Write INT 21h ; wham retc ; error CMP AX,CX ; Did it work? retz ; Yes, carry clear
- mbbrutman 2y agoWhere is that published? I was using Github for references on DOS 4 as 3.3 isn't there yet. (Thanks in advance!)
- mmastrac 2y agohttps://github.com/AR1972/DOS3.3/blob/master/SRC/CMD/SYS/SYS.ASM https://github.com/AR1972/DOS3.3/blob/master/SRC/CMD/SYS/SYS... Send me a note via email -- I might have some more pointers for you