Loading disk sector into memory (AT&T)

34 Views Asked by At

I want to load a sector into a memory address starting at (0xD000). I use index addressing to complete disk load with 0x13 BIOS interrupt. Using 16bit mode, BIOS, AT& Syntax assembly.

I am having difficulty visualising how I would use these functions to iterate over multiple bytes to continuously print out HEX numbers, to see what is stored in the disk sector. I understand I'd use a register such as 'cx' to create a counter and a loop function. Should I use 'jmp' or 'loop' calls for this?

read_sector:  
    movw    $disk_address_packet, %si
    movw    $1, 2(%si)
    movw    $0xD000, 4(%si)
    movw    $1, 8(%si)
    movb    $0x42, %ah
    movb    (boot_device), %dl
    int     $0x13
    jc      read_failed
    
    movb    (0xD000), %al             # Check for non-empty bytes
    cmpb    $0, %al
    je      read_failed

I found this function to read bytes and output as HEX

cons_write_hex:
    movw    $4, %cx
    movb    $0x0E, %ah
    
hexloop:
    rol     $4, %bx             # rotate left 4 bits
    movw    %bx, %si
    and     $0x000F, %si
    movb    HexChars(%si), %al
    int     $0x10
    loop    hexloop
    ret
1

There are 1 best solutions below

0
Sep Roland On
movw    $0xD000, 4(%si)
movw    $1, 8(%si)

In the disk_address_packet, if it isn't already the case, then make sure the far pointer at 4(%si) is valid. Possibly you might still need to insert the segment value:

movw    $0xD000, 4(%si)
movw    %ds, 6(%si)       # far pointer is %ds:0xD000
movw    $1, 8(%si)

I found this function to read bytes and output as HEX

That particular code outputs hexadecimal words, so 2 bytes together!
For just bytes it would look like this:

; IN (%bl)
cons_write_hex:
    movw    $2, %cx
    movb    $0x0E, %ah
hexloop:
    rol     $4, %bl             # rotate left 4 bits
    movw    %bx, %si
    and     $0x000F, %si
    movb    HexChars(%si), %al
    int     $0x10
    loop    hexloop
    ret

... how I would use these functions to iterate over multiple bytes to continuously print out HEX numbers, to see what is stored in the disk sector.

There's more than one solution to this task, but a loop that can hexdumps an entire 512-bytes sector could be written like this:

  movb    $0x0E, %ah          # BIOS.Teletype
  xorw    %bx, %bx            # have %bh permanently zero
  movw    $0xD000, %si        # where the 512 bytes are in memory
hexloop:
  movb    (%si), %bl          # load current byte
  shr     $4, %bl             # get high nibble into the low 4 bits
  movb    HexChars(%bx), %al  # fetch hexadecimal digit (char)
  int     $0x10
  movb    (%si), %bl          # load current byte again
  and     $15, %bl            # keep only low nibble
  movb    HexChars(%bx), %al  # fetch hexadecimal digit (char)
  int     $0x10
  movb    $' ', %al           # interject a space char for readability
  int     $0x10
  incw    %si                 # point at next byte
  cmpw    $0xD200, %si
  jb      hexloop             # addresses that are below 0xD200
                              # fall inside the sector, so go repeat

I understand I'd use a register such as 'cx' to create a counter and a loop function. Should I use 'jmp' or 'loop' calls for this?

As you can see, I have neither used the %cx register nor the loop instruction1 in the above loop. In general it is best to abstain from using the loop instruction and instead rely on conditional jumps like I showed.

1 Terminology: it's not a function, nor is it a call. jmp and loop are instructions.