简体   繁体   中英

How to jump between floppy sectors in assembly? - use of NASM call far and retf?

I am new to programming in asm. I am trying to create a floppy that prints a message on the boot sector, jumps to sector 35 and prints the date, then jumps back to the boot sector and prints a prompt. I am having trouble (I think) jumping between the sectors... I had everything printing fine when it was all on the boot sector and I haven't changed the actual printing code. What I am getting currently is the first line of the message and then the date and prompt never print. The code is below; I am using NASM:

For the boot sector:

org 0x7c00 ;load to appropariate MBR location

start:
  call cls  ;call routine to clear screen
  call dspmsg   ;call routine to display message

  mov ah,02h ;read disk sectors into memory
  mov al,1 ;number of sectors to read/write (must be nonzero)
  mov ch,1 ;cylinder number (0...79)
  mov cl,18 ;sector number (1...18)
  mov dh,0 ;head number (0...1)
  mov dl,0 ;drive number (0...3, 0 for floppy)
  mov bx, 0x1000
  mov es,bx
  mov bx,0x0000
  int 13h

  call word 0x1000:0x0000

  push cs
  pop ds

  call dspmsg2

  jmp $

%macro dsp 3
mov ah,13h ;function 13h (Display String)
mov al,1 ;Write mode is one
mov bh,0 ;Use video page of zero
mov bl,0AH ;Attribute
mov cx,%1 ;Character string length
mov dh,%2 ;position on row
mov dl,0 ;and column 28
push ds ;put ds register on stack
pop es ;pop it into es register
lea bp,%3 ;load the offset address of string into BP
int 10H
%endmacro

cls:             
  mov ah,06h    ;function 06h (Scroll Screen)
  mov al,0  ;scroll all lines
  mov bh,0AH    ;Attribute (light green on black)
  mov ch,0  ;Upper left row is zero
  mov cl,0  ;Upper left column is zero
  mov dh,24 ;Lower left row is 24
  mov dl,79 ;Lower left column is 79
  int 10H   ;BIOS Interrupt 10h (video services)
  ret

msg: db 'OS321, made by CHRISTINE MCGINN (c) 2011'

dspmsg: 
  dsp 40,0,[msg]
  ret

msg2: db '$'

dspmsg2:
;Display a message
dsp 1,2,[msg2]
ret

times 510-($-$$) db 0   ;Pad remainder of boot sector with 0s
dw 0xAA55 ;done setting the MBR

Then on sector 35:

org 0x0000

push cs
pop ds 

  call date
  call cvtmo
  call cvtday
  call cvtcent
  call cvtyear

  call time
  call cvthrs
  call cvtmin
  call cvtsec
  call dsptimedate

  retf

%macro dsp 3
mov ah,13h ;function 13h (Display String)
mov al,1 ;Write mode is one
mov bh,0 ;Use video page of zero
mov bl,0AH ;Attribute
mov cx,%1 ;Character string length
mov dh,%2 ;position on row
mov dl,0 ;and column 28
push ds ;put ds register on stack
pop es ;pop it into es register
lea bp,%3 ;load the offset address of string into BP
int 10H
%endmacro

%macro cvt 3
mov bh,%1 ;copy contents of %1 to bh
shr bh,1
shr bh,1
shr bh,1
shr bh,1
add bh,30h ;add 30h to convert to ascii
mov [tmdtfld + %2],bh
mov bh,%1
and bh,0fh
add bh,30h
mov [tmdtfld + %3],bh
%endmacro

date:
;Get date from the system
mov ah,04h   ;function 04h (get RTC date)
int 1Ah     ;BIOS Interrupt 1Ah (Read Real Time Clock)
ret

;CH - Century
;CL - Year
;DH - Month
;DL - Day

cvtmo:
;Converts the system date from BCD to ASCII
cvt dh,9,10
ret

cvtday:
cvt dl,12,13
ret

cvtcent:
cvt ch,15,16
ret

cvtyear:
cvt cl,17,18
ret

time:
;Get time from the system
mov ah,02h
int 1Ah
ret

;CH - Hours
;CL - Minutes
;DH - Seconds

cvthrs:
;Converts the system time from BCD to ASCII
cvt ch,0,1
ret

cvtmin:
cvt cl,3,4
ret

cvtsec:
cvt dh,6,7
ret

tmdtfld: db '00:00:00 00/00/0000'

dsptimedate:
;Display the system time
dsp 19,1,[tmdtfld]
ret

times 512-($-$$) db 0   ;Pad remainder of sector with 0s

Thank you for any help you can offer!

You've pose the question in a confusing way. You seem to have two problems:

1) Reading arbitrary sectors from the floppy

2) Having programs in each sector that do something (eg, print a string)

I'd organize my program as a floppy driver ("call floppy_read_sector(x)") [which might use the bios to do most of the dirty work, but that's an implementation detail), and as as set of seperate position-independent code blocks that did the various tasks as subroutines.

Your boot sector code should contain the floppy driver and the high level logic to read sector(n), call the subroutine in the buffer you read the sector into, and then do the next sector. (You don't have a lot of room so I don't know if you can squeeze all this into the boot sector. Welcome to assembly language programming where counting bytes is important).

Then you have to organize the construction of the floppy disk somehow. Usually in a world in which one creates bootable floppies, you are allowed to build much more complicated programs to fill them up. Exercise left to the reader.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM