Re: intelligent disassembly



pete@xxxxxxxxxxxxxxxxxx writes:

In article <y93d4u7c36s.fsf@xxxxxxxxxxxxxxxxxxxx>
ara@xxxxxxxxxxxxxxxxxxxx "Allan Adler" writes:

I wrote a boot sector program to copy all of the upper memory area to
the floppy. The floppy was prepared by filling it entirely with 0's
before writing the program to the boot sector.

What do you mean by "entirely"? And what tool did you use to do
this?

I wrote a C program in Linux that writes 18 x 80 x 2 x 512 consecutive 0's
to /dev/fd0. Executing
dd if=/dev/fd0 of=flop bs=512
produces a file flop with 18 x 80 x 2 x 512 bytes, all of them null.

A 1.44MB dos floppy has 18 sectors per track (you mention
below that you are writing 16) and I think dos accesses the disk
on alternate sides/heads before moving to the next track (this is
after all a DOS newsgroup). The track/sector layout you are
using might be opaque to dd?

I originally wrote 32 sectors per track for 24 tracks and that worked as
well as 16 sectors for 48 tracks. However, precisely because I don't know
how dd understands the sides/heads, tracks and sectors, I decided that
16 sectors, starting at sector 1 with head 0 for tracks 1 through 48
would be safer. Some earlier experiments seem to show that even if one writes,
say, 8 tracks starting at track 15 of track 1 with head 1, the write will
be done and will wrap to the next track but the return code in AH will be 4,
indicating sector not found.

I'm glad to learn that DOS accesses the full track on both sides/heads before
going to the next track. I didn't know that and don't know how Linux does it.

The boot sector program copies the upper memory area (0xA0000 to 0xFFFFF)
to sectors 1-16 of tracks 1-48 on side 0 (i.e. head = 0) of the floppy.

Just so long as dd understands this...

I'm still trying to find out what dd understands. But at the very least it
should send sectors in their entirety. It is also likely that sectors 1-18
on a given side of a given track will be consecutive. It's also likely
that track n side 0 will be copied before track n+1 side 0. And that's all
I'm assuming.

You could use od -x of course (but I guess you know this :)

I should have known it. Thanks.

The sense in which the program doesn't seem to work is that, without
exception, the bytes written are all FFh. It is inconceivable that
the upper memory area consists entirely of FF's since the screen itself
has various characters on it, including the 128 a's, b's and c's, and their
ascii codes should be part of upper memory.

All those FFs look to me symptomatic of "error reading disk"...

I'm confused. It is writing to the disk, not reading it. The return code
in AX is 0x0010, which indicates that the write was successful and 0x10
sectors were written. The content of AH after lahf is 46, which shows the
carry flag is 0, another indication that the write was successful.

I don't think there should be any obstacle to reading memory when I've
already demonstrated that I can write to 0xb800:0000, but it is at least
conceivable that there is some problem reading memory.

In an earlier version of the program, I accidentally had the line
add ax,#0x400
instead of
add ax,#0x200
and this did result in the last 24 writes producing stuff other than FFh,
but I don't think that counts.

On the contrary; those last 24 writes would have been of data
starting at 0x00000 as the address wrapped beyond 1MB -- the fact
that you are seeing non-FF bytes there (the first of these writes
would have been the start of the interrupt vector table) suggests
that your program is operating "correctly".

Thanks for explaining that.

Here is the boot sector program. If anyone has any idea what is wrong with
the program, please let me know. The assembler is as86 and the linker is
ld86.
[snip]

The logic and all numbers seem reasonable, though without seeing
what dsk_do_rw actually does it's impossible to say that the code
is correct. Provided that this routine (and 'wout' too) preserve
all the important registers, it should be OK.

Thanks very much for looking over my code.

Here is the code for dsk_do_rw and wout.

dsk_do_rw: or ah,#0 ; 0=read, 1=write, 2=read-only test
dsk_wrflag equ *-1 ; byte data area is the immediate
dsk_do_int13:
push bp
mov bp,#5 ;number of tries
dsk_do_int13a: pusha
int 0x13
jnc dsk_io_exit
dec bp ;does not affect the carry
jz dsk_io_exit
xor ax,ax ;reset disk controllers
int 0x13
popa
dec bp
jmp dsk_do_int13a
dsk_io_exit: mov bp,sp ;do not touch any flags
lea sp,(bp+16) ;an ADD would touch flags
pop bp ;do not touch any flags
ret
; write the word in AX in hex
wout: xchg ah,al
call bout
xchg ah,al
call bout
ret
; write the byte in AL in hex
bout: push ax
push cx
push ax
mov cx,#0x204
shr al,cl
bout1: add al,#'0
cmp al,#'9
jbe bout2
add al,#'A-'0-10
bout2: call putc
dec ch
jz bout4
pop ax
and al,#0xF
jmp bout1
bout4: pop cx
pop ax
ret
; write the character in AL in teletype mode
; all registers are preserved
putc: push bx
push ax
mov ah,#14
xor bh,bh
cmp al,#10 ;test for new-line
jne putc2
mov al,#13 ;get <cr>
int 0x10
mov al,#10
putc2: int 0x10
pop ax
pop bx
ret

Is it important that you record the contents of 0xa0000 to 0xfffff
at boot time? If not it would be a whole lot easier to write a
small prog in (e.g.) C to dump the said contents to a file. Off
the top of my head (hence untried/untested) and with zero error
checking (for brevity):

Of course ROM won't be affected by anything that the operating systems will
do, so in that sense it won't matter. My goal is to examine all the BIOSes
for the system and all the devices. By capturing the upper memory area to
a file, I can write programs to locate and study them. Gilluwe's chapter on
designing adapters is pretty helpful, although there are a few details I
don't fully understand. I considered writing a C program to look at the
memory area but I am afraid that Linux will either refuse to let me do it
and cause a segmentation fault or else will show me something else and let
me think I'm looking at the memory areas. I would try your C program out
under FREEDOS but I have never succeeded in installing djgpp under FREEDOS
and have never succeeded in installing it as a cross-compiler from Linux to
DOS. I'm interested in accomplishing both of these some time, but at the
moment I find it conceptually simpler and more educational to try to do it
with a boot sector program. Merely having done as much as I've done with
this is far beyond anything I've been able to do before. Krishnakumar's
article changed my life.

I just tried another experiment. I wrote a C program under Linux to write
256 blue D's to sector 1 of track 1 (a blue D is 0x44 0x1F) after zapping
the diskette with 0's. Then I wrote a boot sector program that calls
dsk_do_rw with AH=2 to write that blue D sector to 0xb800:0300. If it
works properly, I should see 256 blue D's on the screen when I boot from
this floppy. Well, I just tried it and it didn't work. Anyway, the basic
idea is that this kind of experiment should make it possible to test whether
I can read from diskette to memory (although I don't really doubt this) and
also, by exploiting writes to the screen buffer to explore the geometry
of the diskette, as seen from /dev/fd0. I'll keep at it. The simplest
thing to do is to write enough blue D's to the diskette so that some of them
do wind up at sector 1 of track 1 of side 0, wherever that is from the
point of view of /dev/fd0. Then I can start cutting back on them until the
blue D's stop showing up. Then I'll know what bytes of /dev/fd0 are occupied
by sector 1, track 1, side 0. I just modified the program so that dx=0x100.
This caused a smiley face to appear in the upper left corner of the screen
at bootup and the speaker to play a note which didn't stop until I rebooted.

Another thing to try with the attempts to capture the upper memory area is
to follow each write to the diskette with a call to dsk_do_rw with AH=4,
which verifies the write.
--
Ignorantly,
Allan Adler <ara@xxxxxxxxxxxxxxxxxxxx>
* Disclaimer: I am a guest and *not* a member of the MIT CSAIL. My actions and
* comments do not reflect in any way on MIT. Also, I am nowhere near Boston.
.



Relevant Pages

  • Why all the futzing with boot loaders
    ... Now apt-get dist-upgrade _removes_ a working GRUB and installs a non- working LILO; ... BIOS VolumeID Device ... Reading boot sector from /dev/hda1 ... Secondary loader: 19 sectors. ...
    (Debian-User)
  • Re: SFFDC and blksize_size
    ... > I have been writing a block driver for SSFDC compliant SMC cards. ... NFTL etc. you can just fill in new sectors ... But we could certainly make use of request merging ... send the line "unsubscribe linux-kernel" in ...
    (Linux-Kernel)
  • Re: disk repair w/ XP?
    ... from bad sectors. ... I have a HP desktop PC w/ W98 that will not boot up. ... and when it identifies errors in the boot sector ... plug it into my laptop and I can read files from ...
    (microsoft.public.windowsxp.basics)
  • Re: low-level HD formatting
    ... modern drives anyway. ... India says that "boot sectors" may still be infected after any ... They dont actually do a true low level format, ... Wont do a damned thing about a virus in the MBR or the partition boot sector either. ...
    (comp.sys.ibm.pc.hardware.storage)
  • Re: COFF
    ... >> sectors off the disk - the first sector of the hard disk will be the ... If you want to quickly disassemble a boot sector (they're pretty small, ...
    (comp.programming)