Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > alt.os.development > #9391 > unrolled thread
| Started by | Rod Pemberton <NoHaveNotOne@bcczxcfre.cmm> |
|---|---|
| First post | 2016-04-03 17:36 -0400 |
| Last post | 2016-04-06 00:10 -0400 |
| Articles | 13 — 6 participants |
Back to article view | Back to alt.os.development
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: How to use BIOS int 13h ah=48h ? Rod Pemberton <NoHaveNotOne@bcczxcfre.cmm> - 2016-04-03 17:36 -0400
Re: How to use BIOS int 13h ah=48h ? bilsch <king621@comcast.net> - 2016-04-05 05:34 -0700
Re: How to use BIOS int 13h ah=48h ? "Benjamin David Lunt" <zfysz@fysnet.net> - 2016-04-05 12:53 -0700
THANKS FOR INFO & SUGGESTIONS bilsch <king621@comcast.net> - 2016-04-09 14:09 -0700
Re: THANKS FOR INFO & SUGGESTIONS "Mike Gonta" <mikegonta@gmail.com> - 2016-04-09 18:42 -0400
Re: THANKS FOR INFO & SUGGESTIONS Rod Pemberton <NoHaveNotOne@bcczxcfre.cmm> - 2016-04-10 04:02 -0400
Re: THANKS FOR INFO & SUGGESTIONS "Alexei A. Frounze" <alexfrunews@gmail.com> - 2016-04-10 01:31 -0700
Re: THANKS FOR INFO & SUGGESTIONS "Benjamin David Lunt" <zfysz@fysnet.net> - 2016-04-09 21:28 -0700
Re: THANKS FOR INFO & SUGGESTIONS bilsch <king621@comcast.net> - 2016-04-13 17:30 -0700
Re: THANKS FOR INFO & SUGGESTIONS Rod Pemberton <NoHaveNotOne@bcczxcfre.cmm> - 2016-04-13 22:09 -0400
Re: THANKS FOR INFO & SUGGESTIONS "wolfgang kern" <nowhere@never.at> - 2016-04-10 11:02 +0200
Re: THANKS FOR INFO & SUGGESTIONS "wolfgang kern" <nowhere@never.at> - 2016-04-10 13:31 +0200
Re: How to use BIOS int 13h ah=48h ? Rod Pemberton <NoHaveNotOne@bcczxcfre.cmm> - 2016-04-06 00:10 -0400
| From | Rod Pemberton <NoHaveNotOne@bcczxcfre.cmm> |
|---|---|
| Date | 2016-04-03 17:36 -0400 |
| Subject | Re: How to use BIOS int 13h ah=48h ? |
| Message-ID | <20160403173650.55074eb8@_> |
On Sun, 3 Apr 2016 03:52:01 -0700 bilsch <king621@comcast.net> wrote: > I've been trying to use int 13h to get the number of > sectors on the hard drive. FYI, not many people have posted here (alt.comp.bios) over the past 5 years or so, Bill. I saw your post on comp.lang.asm.x86. Why didn't you look at Int 13H, AH=41h, BX=55AAh, as I suggested? ... comp.lang.asm.x86 was a good place to post. alt.lang.asm and even comp.os.msdos.programmer would've been good places to post. alt.os.development is probably the best place. I've added AOD for replies. > From Ralph Brown List: > <code> > AH = 48h > DL = drive (80h-FFh) > DS:SI -> buffer for drive parameters > > Return: > CF clear if successful > AH = 00h > DS:SI buffer filled > CF set on error > AH = error code > > Buffer for drive parameters: > > Offset Size Description > 00h WORD (call) size of buffer > (001Ah for v1.x, 001Eh for v2.x, 42h for v3.0) > (ret) size of returned data > 02h WORD information flags (see #00274) > 04h DWORD number of physical cylinders on drive > 08h DWORD number of physical heads on drive > 0Ch DWORD number of physical sectors per track > 10h QWORD total number of sectors on drive > 18h WORD bytes per sector > > It seems to me, the following code would be the > correct way to call int 13h ah=48h: First, are you doing this in a boot loader at 7C00h, or attempting to call from DOS .com or .exe, or calling this from an emulator, or calling this while using Linux or Windows, or using v86 mode? If in a boot loader at 7C00h, you can call it. If in DOS as a .com or .exe, DOS may be redirecting the BIOS IVT interrupt to it's own routines. If using DOS, you should use DOS routines, not BIOS. If in an emulator, there could be a bug. If under another OS like Linux or Windows, you should not expect to be able to call it. If you're using v86 mode, you may have problems with the PM OS or monitor controlling the v86 mode. > sxbuf times 0x42 db 0 ;bufr for BIOS to fill Is this buffer actually before your code? Do you jump to the 'mov' instruction below? I.e., you're not executing the empty buffer are you? ... > mov si,sxbuf What segment value is in DS? It may be wise to make sure it is below 512KB. Early machines had only 512KB, while later ones have 640KB. Between 640KB and 1MB+64KB-16, you have BIOS ROMs, video cards, etc. Above 1MB, shouldn't be possible, unless you're using "unreal" mode. However, the BIOS can't use a DS with a limit allowing access above 1MB+64KB-16. I.e., your DS must be a 16-bit RM segment value below 1MB, actually need to be below 640KB or 512KB, and you must not be using the "unreal" mode to call the BIOS. > mov word [si], 0x42 > mov ah,0x48 > mov dl,0x80 ;bit 7 = hard drive > int 0x13 The buffer value is not necessarily 0x42. It might be some other value. You should call Int 13h, AH=41h, BX=55AAh to get the version number in register AH. The AH byte needs to be zero-extended to word AX and stored at DS:SI. You also need to check the supported function bitmap returned in register CX from Int 13h, AH=41h, BX=55AAh to determine if the 48h call is even supported. Also, it might be supported, but just not for your device. Yes, I see that you're attempting to use the most recent values for modern machines which should in theory work. However, each BIOS is different. It's better to implement it fully to get things working. Then, find out why the abbreviated version doesn't work. > And the following would be the correct way to read the sectors info: > > mov di,0x10 ;offset into sxbuf > getbuf: > mov ax,[sxbuf+di] Location +0x10 is a QWORD or 8 bytes. AH and AL are 1 byte (available in all modes) AX is two bytes (available in 16-bit mode) WORD EAX is four bytes (available in 32-bit mode) DWORD RAX is eight bytes (available int 64-bit mode) QWORD > inc di DI is not scaled by the size of AX like a C variable. I.e., 'inc di' increments DI by one (1). So, you're loading two bytes into AX, but moving DI by only one byte at a time ... You probably want another 'inc' instruction here. > cmp di,4 With two 'inc' instructions, you'd need ,8 here. > je done > jmp getbuf > <code> While you are loading AX with values, I don't see code to save or use AX within the loop. IIRC, you called a print loop in your CLAX post. > but it doesn't work. The call returns: > CF=1 (failed) > ah=01 (invalid parameter) > ax = 0000, 0000, 0000, 0000 I would assume that this is because the 0x42h in DS:SI buffer is not the correct value, or that DS:SI is not accessable by the BIOS, or that hard drive 80h is not actually present. Perhaps, you're attempting to access a floppy or USB device or CD-ROM/DVD-ROM? A floppy device can't be on 80h or higher. A USB device can only be 80h if it was the boot device and is being emulated by BIOS as a hard disk. IIRC, a CD-ROM or DVD-ROM can never be 80h, it must be secondary, e.g., 81h. Also, note that some BIOS calls need you to explicitly set CF via STC before being called. Another option would be that AH or other register is being corrupted somehow, e.g., use of a debugger or emulator. > I've tried variations, but none work. I've tried it on five > relatively new (last 5 years) computers - never works. > > How do you do it? I haven't, but some on alt.os.development have recently. There was a short competition, IIRC, which used Int 13h BIOS disk routines. I added AOD to the reply newsgroups. Other questions: What value does Int 13h, AH=41h, BX=55AAh return in in register CX? This word value has a bitmap which indicates which "IBM/MS INT 13 Extensions" are supported by the BIOS. Bit 1, 2, and 3 are listed as extended, removable, and enhanced, respectively. 48h is listed for all three. 48h description is as an extension, so, I'd suspect bit 1 to be set. What value does Int 13h, AH=41h, BX=55AAh return in in register AH? This byte value should be filled in to the first word of the DS:SI buffer for Int 13h, AH=48h. Int 13h, AH=48h, indicates that some BIOSes need word at DS:[SI+2] set to 0000h. So, you should set both the version number word and clear the next word in 'sxbuf'. Is your DS:SI buffer placed below 1MB, preferably below 640K or 512K? Can you confirm the DS:SI segment:offset? Are you initializing the USB controllers? If so, you'll lose access to a USB boot device that is being emulated by the BIOS as a hard disk. If RBIL is not providing enough information, you can search for the Phoenix Enhanced Disk Drive Specifications. There are a few versions. Rod Pemberton
[toc] | [next] | [standalone]
| From | bilsch <king621@comcast.net> |
|---|---|
| Date | 2016-04-05 05:34 -0700 |
| Message-ID | <ne0b78$m2g$1@dont-email.me> |
| In reply to | #9391 |
On 04/03/2016 02:36 PM, Rod Pemberton wrote:
>
> First, are you doing this in a boot loader at 7C00h,
> or attempting to call from DOS .com or .exe,
> or calling this from an emulator, or calling
> this while using Linux or Windows, or using v86 mode?
Rod, thanks for your comments.
First, good news: I revised the program (see listing below), and for the
first time ah=0x48 returns CF=0 (success) and ah=0. But the number of
sectors doesn't work out right. It says EAB025420000FFFF. Backwards
EAB02542 is 24520BAE is 609356718 decimal, times 512 is 311,990,639,616
bytes. But that doesn't take little endian into account. GPARTED says
320,071,700,616 bytes.
To answer your questions: The program (code & data) fills one sector. I
use org 7c00. I write it to the boot sector of a partition with boot
flag set, or I write it to the boot sector of a partition and chain load
it using GRUB - depending on which computer I use.
It has one 'section': text. The segment registers: when I do set them,
I use the following, which makes no difference in the output:
mov ax, 0 ; set up segments
mov ds, ax
mov es, ax
mov ss, ax ; setup stack
mov sp, 0x7C00 ; stack grows downwards from 0x7C00
> The buffer value is not necessarily 0x42. It might be
> some other value. You should call Int 13h, AH=41h, BX=55AAh
> to get the version number in register AH. The AH byte needs
> to be zero-extended to word AX and stored at DS:SI.
>
> You also need to check the supported function bitmap
> returned in register CX from Int 13h, AH=41h, BX=55AAh
> to determine if the 48h call is even supported. Also,
> it might be supported, but just not for your device.
I revised my code (listed below): it now reports version and bitmap. On
this PC it reports version 3.0 and bitmap says bits 0 and 2 set (ah=0x48
is supported).
>
> Yes, I see that you're attempting to use the most recent
> values for modern machines which should in theory work.
> However, each BIOS is different. It's better to implement
> it fully to get things working. Then, find out why the
> abbreviated version doesn't work.
>
>> And the following would be the correct way to read the sectors info:
>>
>> mov di,0x10 ;offset into sxbuf
>> getbuf:
>> mov ax,[sxbuf+di]
>
> Location +0x10 is a QWORD or 8 bytes.
>
> AH and AL are 1 byte (available in all modes)
> AX is two bytes (available in 16-bit mode) WORD
> EAX is four bytes (available in 32-bit mode) DWORD
> RAX is eight bytes (available int 64-bit mode) QWORD
>
>> inc di
>
> DI is not scaled by the size of AX like a C variable.
>
> I.e., 'inc di' increments DI by one (1). So, you're
> loading two bytes into AX, but moving DI by only one
> byte at a time ... You probably want another 'inc'
> instruction here.
>
>> cmp di,4
>
> With two 'inc' instructions, you'd need ,8 here.
>
>> je done
>> jmp getbuf
>> <code>
>
> While you are loading AX with values, I don't see code
> to save or use AX within the loop. IIRC, you called
> a print loop in your CLAX post.
Please see revised code below, all these points are addressed.
>
>> but it doesn't work. The call returns:
>> CF=1 (failed)
>> ah=01 (invalid parameter)
>> ax = 0000, 0000, 0000, 0000
>
> I would assume that this is because the 0x42h in DS:SI
> buffer is not the correct value, or that DS:SI is not
> accessable by the BIOS, or that hard drive 80h is not
> actually present.
>
> Perhaps, you're attempting to access a floppy or USB
> device or CD-ROM/DVD-ROM?
>
> A floppy device can't be on 80h or higher. A USB device
> can only be 80h if it was the boot device and is being
> emulated by BIOS as a hard disk. IIRC, a CD-ROM or
> DVD-ROM can never be 80h, it must be secondary, e.g., 81h.
>
> Also, note that some BIOS calls need you to explicitly
> set CF via STC before being called. Another option would
> be that AH or other register is being corrupted somehow,
> e.g., use of a debugger or emulator.
>
>> I've tried variations, but none work. I've tried it on five
>> relatively new (last 5 years) computers - never works.
>>
>> How do you do it?
>
> I haven't, but some on alt.os.development have recently.
> There was a short competition, IIRC, which used Int 13h
> BIOS disk routines. I added AOD to the reply newsgroups.
>
>
> Other questions:
>
> What value does Int 13h, AH=41h, BX=55AAh
> return in in register CX?
>
> This word value has a bitmap which indicates
> which "IBM/MS INT 13 Extensions" are supported
> by the BIOS. Bit 1, 2, and 3 are listed as
> extended, removable, and enhanced, respectively.
> 48h is listed for all three. 48h description
> is as an extension, so, I'd suspect bit 1 to
> be set.
>
>
> What value does Int 13h, AH=41h, BX=55AAh
> return in in register AH?
>
> This byte value should be filled in to the first
> word of the DS:SI buffer for Int 13h, AH=48h.
>
>
> Int 13h, AH=48h, indicates that some BIOSes
> need word at DS:[SI+2] set to 0000h. So, you
> should set both the version number word and
> clear the next word in 'sxbuf'.
>
>
> Is your DS:SI buffer placed below 1MB, preferably
> below 640K or 512K? Can you confirm the DS:SI
> segment:offset?
>
>
> Are you initializing the USB controllers? If so,
> you'll lose access to a USB boot device that is
> being emulated by the BIOS as a hard disk.
>
>
> If RBIL is not providing enough information,
> you can search for the Phoenix Enhanced Disk
> Drive Specifications. There are a few versions.
>
>
> Rod Pemberton
>
<code>
;kern1.asm nasm -f bin kern1.asm -o kern1.bin
;reads an 8 byte buffer containing number of sectors info; buffer begins
at ds:si + 0x10
org 0x7c00
bits 16
SECTION .text
mov ax, 0 ; set up segments
mov ds, ax
mov es, ax
mov ss, ax ; setup stack
mov sp, 0x7C00 ; stack grows downwards from 0x7C00
mov si,msg41
call print_string
mov bx,0x55aa
mov dl, 0x80
mov ah,0x41
int 0x13
push cx
push ax
cmp ah,0x10 ;ver 1.x
mov word[bsiz],0x1a
cmp ah,0x20 ;ver 2.0
mov word[bsiz],0x1e
cmp ah,0x21 ;ver 2.1
mov word[bsiz],0x1e
cmp ah,0x30 ;ver 3.0
mov word[bsiz],0x42
mov si,ahmsg41 ;'ah41 = '
call print_string
mov bx,i2xt
xor cx,cx ;cx counts to 1
pop ax
lup1: ;here ax is data from ah=0x41
rol ax,4 ;put hi hex digit on right
push ax ;rol'd version
and al,0x0f ;digit in al, is index into i2xt
xlat ;table result in al, bx already points i2xt
mov ah,0xe
int 0x10 ;write
pop ax
cmp cx,1
je api ;cx=1 then done w/ah
inc cx
jmp lup1
api:
mov si,apimsg ;'api = '
call print_string
pop cx
mov al,cl
xlat ;table result in al, bx already points i2xt
mov ah,0xe
int 0x10 ;write
mov si, msg48 ;display BIOS call
call print_string
clc ;clear CF
mov si,sxbuf ;bufr for BIOS to fill
mov di,word[bsiz]
mov [sxbuf],di ;bufr size for BIOS call
mov ah,0x48
mov dl,0x80 ;bit 7 = hd
int 0x13
push ax
jc cf1
mov si, cfzro
call print_string
jmp ah48
cf1:
mov si, cfone
call print_string
ah48:
mov si,ahmsg48 ;'ah='
call print_string
xor cx,cx ;cx counts to 1
pop ax
lup2: ;here ax is data from ah=0x48
rol ax,4 ;put hi hex digit on right
push ax ;rol'd version
and al,0x0f ;digit in al, is index into i2xt
xlat ;table result in al, bx already points i2xt
mov ah,0xe
int 0x10 ;write
pop ax
cmp cx,1
je dsxinfo ;cx=1 then done w/ah
inc cx
jmp lup2
dsxinfo:
mov si, sxmsg ;'hex # sectors = '
call print_string
xor cx,cx
xor dx,dx
xor di,di
add di,0x10 ;offset into sxbuf
get4hex:
add di,dx
add di,dx ;di=2*dx, dx counts words, di counts bytes
mov ax,[sxbuf+di]
outdig:
rol ax,4 ;put hi hex digit on right
push ax ;save rol'd ax
and al,0x0f ;digit in al, is index into i2xt
xlat ;table result in al
mov ah,0xe
int 0x10 ;write
pop ax ;rol'd version of ax
inc cx
cmp cx,4 ;cx is inner loop counter
jne outdig ;4 digit loop - 1 nibble/loop
xor cx,cx
inc dx ;dx counts words
cmp dx,4 ;4 word loop - 1 word/loop
je nend
jmp get4hex ;get next 4 hex digits
nend:
mov si, tstamp ;date & time (manual)
call print_string
jmp $ ;jmp here infinite loop
msg41 db 0xd,0xa,'int 13h, ah=41h', 0xd, 0xa, 0
msg48 db 0xd,0xa,'int 13h, ah=48h', 0xd, 0xa, 0
bsiz dw 0
sxbuf times 0x42 db 0 ;bufr for BIOS to fill
ahmsg41 db 'ah = ', 0
apimsg db ' api = ', 0
cfzro db 'CF=0. success.', 0xd, 0xa, 0
cfone db 'CF=1. failed.', 0xd, 0xa, 0
ahmsg48 db 'ah>0 is error code. ah = ', 0
sxmsg db 0xd, 0xa ,'L-endian sectors = ', 0
tstamp db 0xd, 0xa ,'date: 4/05/16 1:00 am', 0
i2xt db '0123456789ABCDEF'
; ===============================================================
; calls start here
; ===============================================================
print_string:
push ax ;preserve ax
.lup:
lodsb ; grab a byte from si
or al, al ; logical or al by itself
jz .done ; if the result is zero, get out
mov ah, 0xe
int 0x10 ; otherwise, print out the character!
jmp .lup
.done:
pop ax ;preserve ax
ret
times 510-($-$$) db 0
dw 0xAA55
<code>
[toc] | [prev] | [next] | [standalone]
| From | "Benjamin David Lunt" <zfysz@fysnet.net> |
|---|---|
| Date | 2016-04-05 12:53 -0700 |
| Message-ID | <ne1541$17fa$1@gioia.aioe.org> |
| In reply to | #9403 |
"bilsch" <king621@comcast.net> wrote in message news:ne0b78$m2g$1@dont-email.me... > On 04/03/2016 02:36 PM, Rod Pemberton wrote: Hi bilsch, Hi guys, I just have a few comments on your code, if you don't mind. > <code> > ;kern1.asm nasm -f bin kern1.asm -o kern1.bin > > ;reads an 8 byte buffer containing number of sectors info; buffer begins > at ds:si + 0x10 > > org 0x7c00 > bits 16 > SECTION .text > > mov ax, 0 ; set up segments ; in boot sectors, space is sometimes an issue. Every byte ; counts, so I would change the above to ; xor ax,ax ; saves a byte > mov ds, ax > mov es, ax > mov ss, ax ; setup stack > mov sp, 0x7C00 ; stack grows downwards from 0x7C00 > > mov si,msg41 > call print_string > mov bx,0x55aa > mov dl, 0x80 > mov ah,0x41 > int 0x13 ; on return: ; carry set if error ; jc short to_some_error_handler ; carry clear if successful ; cmp bx,0xAA55 ; jne short to_some_error_handler > push cx > push ax > cmp ah,0x10 ;ver 1.x > mov word[bsiz],0x1a > cmp ah,0x20 ;ver 2.0 > mov word[bsiz],0x1e > cmp ah,0x21 ;ver 2.1 > mov word[bsiz],0x1e > cmp ah,0x30 ;ver 3.0 > mov word[bsiz],0x42 ; the above code will *always* put a value of 0x42 in the ; [bsiz] address. You need some 'jcc' in there somewhere. > mov si,ahmsg41 ;'ah41 = ' > call print_string > mov bx,i2xt > xor cx,cx ;cx counts to 1 > pop ax > lup1: ;here ax is data from ah=0x41 > rol ax,4 ;put hi hex digit on right > push ax ;rol'd version > and al,0x0f ;digit in al, is index into i2xt > xlat ;table result in al, bx already points i2xt > mov ah,0xe int 0x10 ;write > pop ax > cmp cx,1 > je api ;cx=1 then done w/ah > inc cx > jmp lup1 ; I noticed that you use this print code a few times ; within your listing here. Can you call a routine ; to do this? Rather than listing it numerous times, ; which takes up space, you can just call a function ; to do it. Also, I would change it a bit. ; ; first comment: ; Setting CX to 0, then comparing it with a non-zero ; value adds code, specifically an extra 'cmp' and 'jcc' ; instruction. Slower and larger. ; ; mov cx,2 ; @@: ; ; do something here ; ; dec cx ; jnz short @b ; or change the above to just the 'loop' instruction ; loop @b ; ; Saves time and space. ; the code above now becomes ; mov bx,i2xt ; mov cx,2 ; printing 2 nibbles ; pop ax ; lup1: ; here ax is data from ah=0x41 ; rol ax,4 ; put hi hex digit on right ; push ax ; rol'd version ; and al,0x0f ; digit in al, is index into i2xt ; xlat ; table result in al, bx already points i2xt ; mov ah,0xe ; int 0x10 ; write ; pop ax ; loop lup1 ; ; (It is easier on the eyes if you align the colums of code ; and comments. i.e.: which is easier to read, your code ; above, or my code here?) ; ; Second comment: ; printing hex digits is something everyone has done so ; there is a lot of code around. A few years ago, more than ; I would like to admit, a regular in c.l.a.x passed away. ; However, he left us with a very nice hex printing routine. ; http://www.fysnet.net/prthex.htm#crayne ; It uses 32-bit registers and prints to a string, but you ; should be able to modify it to use 16-bit registers and ; directly to the screen. ; > api: > mov si,apimsg ;'api = ' > call print_string > pop cx > mov al,cl ; As you probably know, the push instruction does push ; the register, it pushes the contents of the register. ; Therefore, you don't have to use the same register ; when you pop the value. You can easily use a different ; register. Changing the above to ; pop ax ; removes the 'mov' instruction. Save space and time! > xlat ;table result in al, bx already points i2xt > mov ah,0xe int 0x10 ;write > > mov si, msg48 ;display BIOS call > call print_string > clc ;clear CF > mov si,sxbuf ;bufr for BIOS to fill > mov di,word[bsiz] > mov [sxbuf],di ;bufr size for BIOS call > mov ah,0x48 > mov dl,0x80 ;bit 7 = hd > int 0x13 push ax > > jc cf1 > mov si, cfzro > call print_string > jmp ah48 > cf1: > mov si, cfone > call print_string > ah48: > mov si,ahmsg48 ;'ah=' > call print_string > xor cx,cx ;cx counts to 1 > pop ax > lup2: ;here ax is data from ah=0x48 > rol ax,4 ;put hi hex digit on right > push ax ;rol'd version > and al,0x0f ;digit in al, is index into i2xt > xlat ;table result in al, bx already points i2xt > mov ah,0xe int 0x10 ;write > pop ax > cmp cx,1 > je dsxinfo ;cx=1 then done w/ah > inc cx > jmp lup2 > > dsxinfo: > mov si, sxmsg ;'hex # sectors = ' > call print_string > xor cx,cx > xor dx,dx > xor di,di > add di,0x10 ;offset into sxbuf ; mov di,0x10 ; (but I'm sure you are not worried about it at the ; moment. You just want the value printed) > get4hex: > add di,dx > add di,dx ;di=2*dx, dx counts words, di counts bytes > mov ax,[sxbuf+di] outdig: > rol ax,4 ;put hi hex digit on right > push ax ;save rol'd ax > and al,0x0f ;digit in al, is index into i2xt > xlat ;table result in al > mov ah,0xe int 0x10 ;write > pop ax ;rol'd version of ax > inc cx > cmp cx,4 ;cx is inner loop counter > jne outdig ;4 digit loop - 1 nibble/loop > xor cx,cx > inc dx ;dx counts words > cmp dx,4 ;4 word loop - 1 word/loop > je nend > jmp get4hex ;get next 4 hex digits ; I would change the above to use SI and 'lodsb' ; mov cx,8 ; 8 bytes ; lea si,[sxbuf+0x10] ; @@: ; lodsb ; call hexdb ; Crayne's print nibble ; loop @b Please note that your code all prints the hex digits backwards. Which through your comments, I think you realize this. :-) Anyway, just a few comments. I know it is C code instead of assembly, but I have source code at http://www.fysnet.net/syscore_help.htm that will show you how to get all of the information from the drive, including total sector count. Hope this helps, Ben
[toc] | [prev] | [next] | [standalone]
| From | bilsch <king621@comcast.net> |
|---|---|
| Date | 2016-04-09 14:09 -0700 |
| Subject | THANKS FOR INFO & SUGGESTIONS |
| Message-ID | <nebqrl$8it$1@dont-email.me> |
| In reply to | #9406 |
On 04/05/2016 12:53 PM, Benjamin David Lunt wrote:
> "bilsch" <king621@comcast.net> wrote in message
> news:ne0b78$m2g$1@dont-email.me...
>> On 04/03/2016 02:36 PM, Rod Pemberton wrote:
>
> Hi bilsch, Hi guys,
>
> I just have a few comments on your code, if you don't mind.
>
>> <code>
>> ;kern1.asm nasm -f bin kern1.asm -o kern1.bin
>>
>> ;reads an 8 byte buffer containing number of sectors info; buffer begins
>> at ds:si + 0x10
>>
>> org 0x7c00
>> bits 16
>> SECTION .text
>>
>> mov ax, 0 ; set up segments
>
> ; in boot sectors, space is sometimes an issue. Every byte
> ; counts, so I would change the above to
> ; xor ax,ax ; saves a byte
>
>> mov ds, ax
>> mov es, ax
>> mov ss, ax ; setup stack
>> mov sp, 0x7C00 ; stack grows downwards from 0x7C00
>>
>> mov si,msg41
>> call print_string
>> mov bx,0x55aa
>> mov dl, 0x80
>> mov ah,0x41
>> int 0x13
>
> ; on return:
> ; carry set if error
> ; jc short to_some_error_handler
> ; carry clear if successful
> ; cmp bx,0xAA55
> ; jne short to_some_error_handler
>
>> push cx
>> push ax
>> cmp ah,0x10 ;ver 1.x
>> mov word[bsiz],0x1a
>> cmp ah,0x20 ;ver 2.0
>> mov word[bsiz],0x1e
>> cmp ah,0x21 ;ver 2.1
>> mov word[bsiz],0x1e
>> cmp ah,0x30 ;ver 3.0
>> mov word[bsiz],0x42
>
> ; the above code will *always* put a value of 0x42 in the
> ; [bsiz] address. You need some 'jcc' in there somewhere.
>
>> mov si,ahmsg41 ;'ah41 = '
>> call print_string
>
>> mov bx,i2xt
>> xor cx,cx ;cx counts to 1
>> pop ax
>> lup1: ;here ax is data from ah=0x41
>> rol ax,4 ;put hi hex digit on right
>> push ax ;rol'd version
>> and al,0x0f ;digit in al, is index into i2xt
>> xlat ;table result in al, bx already points i2xt
>> mov ah,0xe int 0x10 ;write
>> pop ax
>> cmp cx,1
>> je api ;cx=1 then done w/ah
>> inc cx
>> jmp lup1
>
> ; I noticed that you use this print code a few times
> ; within your listing here. Can you call a routine
> ; to do this? Rather than listing it numerous times,
> ; which takes up space, you can just call a function
> ; to do it. Also, I would change it a bit.
> ;
> ; first comment:
> ; Setting CX to 0, then comparing it with a non-zero
> ; value adds code, specifically an extra 'cmp' and 'jcc'
> ; instruction. Slower and larger.
> ;
> ; mov cx,2
> ; @@:
> ; ; do something here
> ;
> ; dec cx
> ; jnz short @b
> ; or change the above to just the 'loop' instruction
> ; loop @b
> ;
> ; Saves time and space.
>
> ; the code above now becomes
> ; mov bx,i2xt
> ; mov cx,2 ; printing 2 nibbles
> ; pop ax
> ; lup1: ; here ax is data from ah=0x41
> ; rol ax,4 ; put hi hex digit on right
> ; push ax ; rol'd version
> ; and al,0x0f ; digit in al, is index into i2xt
> ; xlat ; table result in al, bx already points i2xt
> ; mov ah,0xe
> ; int 0x10 ; write
> ; pop ax
> ; loop lup1
> ;
> ; (It is easier on the eyes if you align the colums of code
> ; and comments. i.e.: which is easier to read, your code
> ; above, or my code here?)
> ;
> ; Second comment:
> ; printing hex digits is something everyone has done so
> ; there is a lot of code around. A few years ago, more than
> ; I would like to admit, a regular in c.l.a.x passed away.
> ; However, he left us with a very nice hex printing routine.
> ; http://www.fysnet.net/prthex.htm#crayne
> ; It uses 32-bit registers and prints to a string, but you
> ; should be able to modify it to use 16-bit registers and
> ; directly to the screen.
> ;
>> api:
>> mov si,apimsg ;'api = '
>> call print_string
>> pop cx
>> mov al,cl
>
> ; As you probably know, the push instruction does push
> ; the register, it pushes the contents of the register.
> ; Therefore, you don't have to use the same register
> ; when you pop the value. You can easily use a different
> ; register. Changing the above to
> ; pop ax
> ; removes the 'mov' instruction. Save space and time!
>
>> xlat ;table result in al, bx already points i2xt
>> mov ah,0xe int 0x10 ;write
>>
>> mov si, msg48 ;display BIOS call
>> call print_string
>> clc ;clear CF
>> mov si,sxbuf ;bufr for BIOS to fill
>> mov di,word[bsiz]
>> mov [sxbuf],di ;bufr size for BIOS call
>> mov ah,0x48
>> mov dl,0x80 ;bit 7 = hd
>> int 0x13 push ax
>>
>> jc cf1
>> mov si, cfzro
>> call print_string
>> jmp ah48
>> cf1:
>> mov si, cfone
>> call print_string
>> ah48:
>> mov si,ahmsg48 ;'ah='
>> call print_string
>> xor cx,cx ;cx counts to 1
>> pop ax
>> lup2: ;here ax is data from ah=0x48
>> rol ax,4 ;put hi hex digit on right
>> push ax ;rol'd version
>> and al,0x0f ;digit in al, is index into i2xt
>> xlat ;table result in al, bx already points i2xt
>> mov ah,0xe int 0x10 ;write
>> pop ax
>> cmp cx,1
>> je dsxinfo ;cx=1 then done w/ah
>> inc cx
>> jmp lup2
>>
>> dsxinfo:
>> mov si, sxmsg ;'hex # sectors = '
>> call print_string
>> xor cx,cx
>> xor dx,dx
>> xor di,di
>> add di,0x10 ;offset into sxbuf
>
> ; mov di,0x10
> ; (but I'm sure you are not worried about it at the
> ; moment. You just want the value printed)
>
>> get4hex:
>> add di,dx
>> add di,dx ;di=2*dx, dx counts words, di counts bytes
>> mov ax,[sxbuf+di] outdig:
>> rol ax,4 ;put hi hex digit on right
>> push ax ;save rol'd ax
>> and al,0x0f ;digit in al, is index into i2xt
>> xlat ;table result in al
>> mov ah,0xe int 0x10 ;write
>> pop ax ;rol'd version of ax
>> inc cx
>> cmp cx,4 ;cx is inner loop counter
>> jne outdig ;4 digit loop - 1 nibble/loop
>> xor cx,cx
>> inc dx ;dx counts words
>> cmp dx,4 ;4 word loop - 1 word/loop
>> je nend
>> jmp get4hex ;get next 4 hex digits
>
>
> ; I would change the above to use SI and 'lodsb'
> ; mov cx,8 ; 8 bytes
> ; lea si,[sxbuf+0x10]
> ; @@:
> ; lodsb
> ; call hexdb ; Crayne's print nibble
> ; loop @b
>
> Please note that your code all prints the hex digits
> backwards. Which through your comments, I think you
> realize this. :-)
>
> Anyway, just a few comments.
>
> I know it is C code instead of assembly, but I have
> source code at
> http://www.fysnet.net/syscore_help.htm
> that will show you how to get all of the information from
> the drive, including total sector count.
>
> Hope this helps,
> Ben
>
>
OK, I've got it how I want it. Your suggestions about saving space were
good, as I ran out of room at one point. Code is more efficient and
compact now. The program is listed below if anybody is interested.
Thanks. Bill S.
<code>
org 0x7c00
bits 16
SECTION .text
xor ax,ax ; set up segments
mov ds, ax
mov es, ax
mov ss, ax ; setup stack
mov sp, 0x7c00 ; stack grows downwards from 0x7c00
mov si,msg41
call print_string
mov bx,0x55aa
mov dl,0x80
mov ah,0x41
int 0x13
push cx
cmp ah,0x10 ;ver 1.x
jne ver20
mov word[bsiz],0x1a
ver20:
cmp ah,0x20 ;ver 2.0
jne ver21
mov word[bsiz],0x1e
ver21:
cmp ah,0x21 ;ver 2.1
jne ver30
mov word[bsiz],0x1e
ver30:
cmp ah,0x30 ;ver 3.0
jne ckbsiz
mov word[bsiz],0x42
ckbsiz:
cmp word[bsiz],0
jne ah41
mov si,noext ;no int 13h ext
call print_string
jmp nend ;w/o bsiz we're going nowhere
ah41:
mov si,ahmsg41 ;ah =
call print_string
mov bx,i2xt
mov cx,2 ;cx = # of digits to translate
call b2xa
api:
mov si,apimsg ;'api = '
call print_string
pop ax ;this is pushed cx
xlat ;table result in al, bx already points i2xt
mov ah,0xe
int 0x10 ;write
ah48:
mov si, msg48 ;display BIOS call
call print_string
clc ;clear CF
mov si,sxbuf ;bufr for BIOS to fill
mov di,word[bsiz]
mov [sxbuf],di ;bufr size for BIOS call
mov ah,0x48
mov dl,0x80 ;bit 7 = hd
int 0x13
jc cf1
mov si, cfzro
call print_string
jmp ah48m
cf1:
mov si, cfone
call print_string
ah48m:
mov si,ahmsg48 ;'ah='
call print_string
mov cx,2 ;cx = # of digits to translate
call b2xa
dsxinfo:
mov si, sxmsg ;'hex # sectors = '
call print_string
mov di,0x16 ;start w/bytes 0x16 & 0x17
get4digit:
mov cx,4 ;cx counts 4 nibbles/word
mov ax,[sxbuf+di]
outdigit:
rol ax,4 ;put hi hex digit on right
push ax ;save rol'd ax
and al,0x0f ;digit in al, is index into i2xt
xlat ;table result in al
mov ah,0xe
int 0x10 ;write
pop ax ;rol'd version of ax
dec cx
jnz outdigit ;4 digit loop - 1 nibble/loop
dec di
dec di
cmp di,0xe ;end w/bytes 0x10 & 0x11
jnz get4digit ;get next 4 hex digits
nend:
mov si, tstamp ;date & time (manual)
call print_string
jmp $ ;jmp here infinite loop
msg41 db 0xd,0xa,'int 13h, ah=41h', 0xd, 0xa, 0
msg48 db 0xd,0xa,'int 13h, ah=48h', 0xd, 0xa, 0
ahmsg41 db 'ah = ', 0
noext db ' no int 13h ext', 0
apimsg db ' api = ', 0
cfzro db 'CF=0=success.', 0xd, 0xa, 0
cfone db 'CF=1=failed.', 0xd, 0xa, 0
ahmsg48 db 'ah>0 is an error code. ah = ', 0
sxmsg db 0xd, 0xa ,'# of sectors = ', 0
tstamp db 0xd, 0xa ,'4/08/16 7:00 am', 0
i2xt db '0123456789ABCDEF'
bsiz dw 0
sxbuf times 0x42 db 0 ;bufr for BIOS to fill
; ===============================================================
; calls start here
; ===============================================================
print_string:
push ax ;preserve ax
.lup:
lodsb ; grab a byte from si
or al, al ; logical or al by itself
jz .done ; if the result is zero, get out
mov ah, 0xe
int 0x10 ; otherwise, print out the character!
jmp .lup
.done:
pop ax ;preserve ax
ret
b2xa: ;ax has data, cx has # nibs to translate
rol ax,4 ;put hi hex digit on right
push ax ;rol'd version
and al,0x0f ;digit in al, is index into i2xt
xlat ;table result in al, bx already points i2xt
mov ah,0xe
int 0x10 ;write
pop ax
dec cx
jnz b2xa
ret
times 510-($-$$) db 0
dw 0xAA55
</code>
[toc] | [prev] | [next] | [standalone]
| From | "Mike Gonta" <mikegonta@gmail.com> |
|---|---|
| Date | 2016-04-09 18:42 -0400 |
| Subject | Re: THANKS FOR INFO & SUGGESTIONS |
| Message-ID | <nec0hn$75a$1@gioia.aioe.org> |
| In reply to | #9416 |
"bilsch" wrote: > OK, I've got it how I want it. Your suggestions about > saving space were good, as I ran out of room at one point. > Code is more efficient and compact now. The program is > listed below if anybody is interested. > .... > mov bx,0x55aa > mov dl,0x80 > .... Best practice is not to assume the drive ID. At this point in the code the BIOS has the boot drive ID in DL (which should be used (and saved for later use as well). > .... > print_string: > push ax ;preserve ax > .lup: > lodsb ; grab a byte from si > or al, al ; logical or al by itself > jz .done ; if the result is zero, get out > mov ah, 0xe > int 0x10 ; otherwise, print out the character! > jmp .lup > .done: > pop ax ;preserve ax > ret > .... BIOS INT 0x10, AH=0x0E expects a BH="video page" (typically this is BH=0, simply use the first "video page"). Oh, and you spelled loop wrong - the correct spelling should be "lupe". Mike Gonta look and see - many look but few see http://mikegonta.com http://tawk.to/mikegonta
[toc] | [prev] | [next] | [standalone]
| From | Rod Pemberton <NoHaveNotOne@bcczxcfre.cmm> |
|---|---|
| Date | 2016-04-10 04:02 -0400 |
| Subject | Re: THANKS FOR INFO & SUGGESTIONS |
| Message-ID | <20160410040225.725af127@_> |
| In reply to | #9417 |
On Sat, 9 Apr 2016 18:42:51 -0400 "Mike Gonta" <mikegonta@gmail.com> wrote: > > .lup: > > Oh, and you spelled loop wrong - the correct > spelling should be "lupe". Huh? Rod Pemberton
[toc] | [prev] | [next] | [standalone]
| From | "Alexei A. Frounze" <alexfrunews@gmail.com> |
|---|---|
| Date | 2016-04-10 01:31 -0700 |
| Subject | Re: THANKS FOR INFO & SUGGESTIONS |
| Message-ID | <67bcfb85-b8df-46e2-a5ee-0d7b4046ed50@googlegroups.com> |
| In reply to | #9420 |
On Sunday, April 10, 2016 at 1:01:47 AM UTC-7, Rod Pemberton wrote: > On Sat, 9 Apr 2016 18:42:51 -0400 > "Mike Gonta" <...@gmail.com> wrote: > > > > .lup: > > > > Oh, and you spelled loop wrong - the correct > > spelling should be "lupe". > > Huh? Italian for female wolves. With some imagination it could become Guadalupe or lupus. Just kiddin'. Alex
[toc] | [prev] | [next] | [standalone]
| From | "Benjamin David Lunt" <zfysz@fysnet.net> |
|---|---|
| Date | 2016-04-09 21:28 -0700 |
| Subject | Re: THANKS FOR INFO & SUGGESTIONS |
| Message-ID | <neckpi$1f0k$1@gioia.aioe.org> |
| In reply to | #9416 |
"bilsch" <king621@comcast.net> wrote in message
news:nebqrl$8it$1@dont-email.me...
> OK, I've got it how I want it. Your suggestions about saving space were
> good, as I ran out of room at one point. Code is more efficient and
> compact now. The program is listed below if anybody is interested.
> Thanks. Bill S.
Glad to help. I'll make a few more suggestions.
> <code>
> org 0x7c00
> bits 16
> SECTION .text
>
> xor ax,ax ; set up segments
> mov ds, ax
> mov es, ax
> mov ss, ax ; setup stack
> mov sp, 0x7c00 ; stack grows downwards from 0x7c00
>
> mov si,msg41
> call print_string
> mov bx,0x55aa
> mov dl,0x80
; As Mike noted, DL is passed to your code.
mov [saved_dl],dl
; and comment out the line you used above,
; being sure not to modify DL beforehand.
> mov ah,0x41
> int 0x13
> push cx
> cmp ah,0x10 ;ver 1.x
> jne ver20
> mov word[bsiz],0x1a
> ver20:
> cmp ah,0x20 ;ver 2.0
> jne ver21
> mov word[bsiz],0x1e
> ver21:
> cmp ah,0x21 ;ver 2.1
> jne ver30
> mov word[bsiz],0x1e
> ver30:
> cmp ah,0x30 ;ver 3.0
> jne ckbsiz
> mov word[bsiz],0x42
> ckbsiz:
> cmp word[bsiz],0
> jne ah41
> mov si,noext ;no int 13h ext
> call print_string
> jmp nend ;w/o bsiz we're going nowhere
> ah41:
Depending on how you look at it, the above
code is missing some 'jmp's or in the case
I show below, has way too many :-)
First, in the code above, even after you put the
correct value into [bsiz], you still cmp ah for
each additional check. No problem, except that
it is slower code and larger code. How about
something like this:
mov word[bsiz],0x1a
cmp ah,0x10 ;ver 1.x
je ah41
mov word[bsiz],0x1e
cmp ah,0x20 ;ver 2.0
je ah41
; mov word[bsiz],0x1e
cmp ah,0x21 ;ver 2.1
je ah41
mov word[bsiz],0x42
cmp ah,0x30 ;ver 3.0
je ah41
mov si,noext ;no int 13h ext
call print_string
jmp nend ;w/o bsiz we're going nowhere
ah41:
Less code, fewer jumps.
> mov si,ahmsg41 ;ah =
> call print_string
> mov bx,i2xt
> mov cx,2 ;cx = # of digits to translate
> call b2xa
> api:
> mov si,apimsg ;'api = '
> call print_string
> pop ax ;this is pushed cx
> xlat ;table result in al, bx already points i2xt
> mov ah,0xe
> int 0x10 ;write
Also as Mike said, bh should be zero before the
interrupt call above.
> ah48:
> mov si, msg48 ;display BIOS call
> call print_string
> clc ;clear CF
> mov si,sxbuf ;bufr for BIOS to fill
> mov di,word[bsiz]
> mov [sxbuf],di ;bufr size for BIOS call
> mov ah,0x48
> mov dl,0x80 ;bit 7 = hd
> int 0x13
> jc cf1
> mov si, cfzro
> call print_string
> jmp ah48m
> cf1:
> mov si, cfone
> call print_string
> ah48m:
Again, the 'mov' instruction does not modify the
flags register, so you can do a mov before the
carry check:
mov si, cfone
jc cf1
mov si, cfzro
cf1:
call print_string
; less code, fewer jumps
> mov si,ahmsg48 ;'ah='
> call print_string
> mov cx,2 ;cx = # of digits to translate
> call b2xa
> dsxinfo:
> mov si, sxmsg ;'hex # sectors = '
> call print_string
> mov di,0x16 ;start w/bytes 0x16 & 0x17
> get4digit:
> mov cx,4 ;cx counts 4 nibbles/word
> mov ax,[sxbuf+di]
> outdigit:
> rol ax,4 ;put hi hex digit on right
> push ax ;save rol'd ax
> and al,0x0f ;digit in al, is index into i2xt
> xlat ;table result in al
> mov ah,0xe
xor bh,bh
> int 0x10 ;write
> pop ax ;rol'd version of ax
> dec cx
> jnz outdigit ;4 digit loop - 1 nibble/loop
> dec di
> dec di
> cmp di,0xe ;end w/bytes 0x10 & 0x11
> jnz get4digit ;get next 4 hex digits
> nend:
> mov si, tstamp ;date & time (manual)
> call print_string
> jmp $ ;jmp here infinite loop
>
> msg41 db 0xd,0xa,'int 13h, ah=41h', 0xd, 0xa, 0
> msg48 db 0xd,0xa,'int 13h, ah=48h', 0xd, 0xa, 0
> ahmsg41 db 'ah = ', 0
> noext db ' no int 13h ext', 0
> apimsg db ' api = ', 0
> cfzro db 'CF=0=success.', 0xd, 0xa, 0
> cfone db 'CF=1=failed.', 0xd, 0xa, 0
> ahmsg48 db 'ah>0 is an error code. ah = ', 0
> sxmsg db 0xd, 0xa ,'# of sectors = ', 0
> tstamp db 0xd, 0xa ,'4/08/16 7:00 am', 0
> i2xt db '0123456789ABCDEF'
> bsiz dw 0
> sxbuf times 0x42 db 0 ;bufr for BIOS to fill
> ; ===============================================================
> ; calls start here
> ; ===============================================================
>
> print_string:
> push ax ;preserve ax
> .lup:
> lodsb ; grab a byte from si
> or al, al ; logical or al by itself
> jz .done ; if the result is zero, get out
> mov ah, 0xe
> int 0x10 ; otherwise, print out the character!
> jmp .lup
> .done:
> pop ax ;preserve ax
> ret
>
> b2xa: ;ax has data, cx has # nibs to translate
> rol ax,4 ;put hi hex digit on right
> push ax ;rol'd version
> and al,0x0f ;digit in al, is index into i2xt
> xlat ;table result in al, bx already points i2xt
> mov ah,0xe
> int 0x10 ;write
> pop ax
> dec cx
> jnz b2xa
> ret
>
> times 510-($-$$) db 0
> dw 0xAA55
> </code>
I didn't go through it with as much detail, but it does
look better. Good job. Isn't learning fun :-)
Ben
[toc] | [prev] | [next] | [standalone]
| From | bilsch <king621@comcast.net> |
|---|---|
| Date | 2016-04-13 17:30 -0700 |
| Subject | Re: THANKS FOR INFO & SUGGESTIONS |
| Message-ID | <nemo4f$j4c$1@dont-email.me> |
| In reply to | #9419 |
>> mov si,msg41 >> call print_string >> mov bx,0x55aa >> mov dl,0x80 > > ; As Mike noted, DL is passed to your code. > mov [saved_dl],dl > ; and comment out the line you used above, > ; being sure not to modify DL beforehand. I don't understand this comment. Ralph Brown shows dl is a value that you must provide when calling int13 ah=41 bx=55aa. dl can't contain the drive number BEFORE I call int13. Also RBIL doesn't show dl as a returned value.
[toc] | [prev] | [next] | [standalone]
| From | Rod Pemberton <NoHaveNotOne@bcczxcfre.cmm> |
|---|---|
| Date | 2016-04-13 22:09 -0400 |
| Subject | Re: THANKS FOR INFO & SUGGESTIONS |
| Message-ID | <20160413220915.344a543a@_> |
| In reply to | #9433 |
On Wed, 13 Apr 2016 17:30:12 -0700 bilsch <king621@comcast.net> wrote: > >> mov si,msg41 > >> call print_string > >> mov bx,0x55aa > >> mov dl,0x80 > > > > ; As Mike noted, DL is passed to your code. > > mov [saved_dl],dl > > ; and comment out the line you used above, > > ; being sure not to modify DL beforehand. > > > I don't understand this comment. Ralph Brown shows dl is a value > that you must provide when calling int13 ah=41 bx=55aa. dl can't > contain the drive number BEFORE I call int13. Also RBIL doesn't show > dl as a returned value. 7C00 start up code is called from Int 19h with some entry values set in registers. RBIL documents some of them. 7C00 entry values http://www.delorie.com/djgpp/doc/rbinter/it/53/6.html INT 19 http://www.delorie.com/djgpp/doc/rbinter/id/79/22.html INT 18 http://www.delorie.com/djgpp/doc/rbinter/id/50/22.html Additional values were added per later BIOS and drive specifications and are not documented by RBIL. Later specifications also changed boot order to include INT 18h. None of that is in RBIL. I don't recall where those are at the moment, perhaps Phoenix EDD specifications or maybe IDE or maybe BIOS Boot specification or maybe PCI specifications. I can look up my old posts or this info if you need it. Ben or someone else might recall. Rod Pemberton
[toc] | [prev] | [next] | [standalone]
| From | "wolfgang kern" <nowhere@never.at> |
|---|---|
| Date | 2016-04-10 11:02 +0200 |
| Subject | Re: THANKS FOR INFO & SUGGESTIONS |
| Message-ID | <ned4qn$6ov$1@gioia.aioe.org> |
| In reply to | #9416 |
bilsch posted: [about] seems you are on the right track yet, well done so far. Ben already showed you possible shorter code solutions, and here is what I'd do to save some more bytes: I commented out ~175 bytes and added ~ 75. Hope that I didn't make too many typos here ;) __ wolfgang > <code> > org 0x7c00 > bits 16 > SECTION .text > > xor ax,ax ; set up segments > mov ds, ax > mov es, ax > mov ss, ax ; setup stack > mov sp, 0x7c00 ; stack grows downwards from 0x7c00 > > mov si,msg41 > call print_string > mov bx,0x55aa > mov dl,0x80 > mov ah,0x41 > int 0x13 * jc errr ;could be not supported * mov bx,0x7e00 ;points to your buffer now > push cx > cmp ah,0x10 ;ver 1.x * mov al,0x1a * je ah41 ;> jne ver20 ;> mov word[bsiz],0x1a ;> ver20: > cmp ah,0x20 ;ver 2.0 * ver21: * mov al,0x1e * je ah41 ;> jne ver21 ;> mov word[bsiz],0x1e ;> ver21: > cmp ah,0x21 ;ver 2.1 * je ver21 ;> jne ver30 ;> mov word[bsiz],0x1e ;> ver30: > cmp ah,0x30 ;ver 3.0 * mov al,0x42 * je ah41 ;> jne ckbsiz ;> mov word[bsiz],0x42 ;> ckbsiz: ;> cmp word[bsiz],0 ;> jne ah41 errr: > mov si,noext ;no int 13h ext > call print_string > jmp nend ;w/o bsiz we're going nowhere > ah41: * mov word[bsiz],al > mov si,ahmsg41 ;ah = > call print_string ;> mov bx,i2xt ;> mov cx,2 ;cx = # of digits to translate ;> call b2xa * call hex2ah ;AH 2 hex digits Yeah, nibble based hex-print routines are fine. But the XLAT method isn't short nor fast, I use eax/ebx (you can use it too also within 16-bit code) to hold up to 8 nibbles for hex dwords display, but see below. > api: > mov si,apimsg ;'api = ' > call print_string > pop ax ;this is pushed cx good, it works even it assumes that the pushed CL < 0x10 ! ;> xlat ;table result in al, bx already points i2xt ;> mov ah,0xe ;> int 0x10 ;write * call hex1al ;use only low nibble of AL > ah48: > mov si, msg48 ;display BIOS call > call print_string > clc ;clear CF ;> mov si,sxbuf ;bufr for BIOS to fill > mov di,word[bsiz] ;> mov [sxbuf],di ;bufr size for BIOS call * mov [bx],di > mov ah,0x48 > mov dl,0x80 ;bit 7 = hd > int 0x13 * mov si, cfone > jc cf1 > mov si, cfzro * cf1: > call print_string ;> jmp ah48m ;>cf1: ;> mov si, cfone ;> call print_string ;>ah48m: > mov si,ahmsg48 ;'ah=' > call print_string ;> mov cx,2 ;cx = # of digits to translate ;> call b2xa * call hex2ah ;AH > dsxinfo: > mov si, sxmsg ;'hex # sectors = ' > call print_string > mov di,0x16 ;start w/bytes 0x16 & 0x17 > get4digit: ;> mov cx,4 ;cx counts 4 nibbles/word ;> mov ax,[sxbuf+di] * mov ax,[bx+di] * call hex4ax ;four nibbles ;> outdigit: ;> rol ax,4 ;put hi hex digit on right ;> push ax ;save rol'd ax ;> and al,0x0f ;digit in al, is index into i2xt ;> xlat ;table result in al ;> mov ah,0xe ;> int 0x10 ;write ;> pop ax ;rol'd version of ax ;> dec cx ;> jnz outdigit ;4 digit loop - 1 nibble/loop > dec di > dec di > cmp di,0xe ;end w/bytes 0x10 & 0x11 > jnz get4digit ;get next 4 hex digits Have you got a reason to show it topdown ? :) > nend: > mov si, tstamp ;date & time (manual) > call print_string > jmp $ ;jmp here infinite loop > msg41 db 0xd,0xa,'int 13h, ah=41h', 0xd, 0xa, 0 > msg48 db 0xd,0xa,'int 13h, ah=48h', 0xd, 0xa, 0 > ahmsg41 db 'ah = ', 0 > noext db ' no int 13h ext', 0 > apimsg db ' api = ', 0 > cfzro db 'CF=0=success.', 0xd, 0xa, 0 > cfone db 'CF=1=failed.', 0xd, 0xa, 0 > ahmsg48 db 'ah>0 is an error code. ah = ', 0 > sxmsg db 0xd, 0xa ,'# of sectors = ', 0 > tstamp db 0xd, 0xa ,'4/08/16 7:00 am', 0 ;> i2xt db '0123456789ABCDEF' > bsiz dw 0 ;> sxbuf times 0x42 db 0 ;bufr for BIOS to fill I'd assign this buffer outside see: mov bx,0x7e00 above > ; =============================================================== > ; calls start here > ; =============================================================== > > print_string: > push ax ;preserve ax > .lup: > lodsb ; grab a byte from si > or al, al ; logical or al by itself > jz .done ; if the result is zero, get out > mov ah, 0xe > int 0x10 ; otherwise, print out the character! > jmp .lup > .done: > pop ax ;preserve ax > ret ;> b2xa: ;ax has data, cx has # nibs to translate ;> rol ax,4 ;put hi hex digit on right ;> push ax ;rol'd version ;> and al,0x0f ;digit in al, is index into i2xt ;> xlat ;table result in al, bx already points i2xt ;> mov ah,0xe ;> int 0x10 ;write ;> pop ax ;> dec cx ;> jnz b2xa ;> ret hex4ax: ;4 nibbles from ax push ax call hex2ah pop ax shl ax,8 hex2ah: ;2 digits of AH mov al,ah shr al,4 ;high part first call hex1al mov al,ah hex1al: ;a single nibble from AL push ax and al,0x0f cmp al,0x0a jc hex1 add al,0x07 hex1: add al,0x30 mov ah 0x0e mov bh,0 int 0x10 pop ax ret ;------- my own routine: it always uses ebx and need to be preceded by MOVZX ebx,ah for AH only, but it terminates 'automated' w/o size info. hexout: mov eax,ebx ror eax,4 ;start with MSD and al,0x0f cmp al,0x0a jc itsnum ;skip next instruction add al,0x07 ;if > 9 then 'A..F' itsnum: add al,0x30 ;make it ASCII call charout ;I don't use the BIOS here shl ebx,4 jnz hexout ;until nothing else to print ret ;-------- > > times 510-($-$$) db 0 > dw 0xAA55 > </code>
[toc] | [prev] | [next] | [standalone]
| From | "wolfgang kern" <nowhere@never.at> |
|---|---|
| Date | 2016-04-10 13:31 +0200 |
| Subject | Re: THANKS FOR INFO & SUGGESTIONS |
| Message-ID | <neddj0$kp4$1@gioia.aioe.org> |
| In reply to | #9422 |
I wrote: and forgot to restore BX to 0x7e00 after the BIOS call ! > hex4ax: ;4 nibbles from ax > push ax > call hex2ah > pop ax > shl ax,8 > hex2ah: ;2 digits of AH > mov al,ah > shr al,4 ;high part first > call hex1al > mov al,ah > hex1al: ;a single nibble from AL > push ax > and al,0x0f > cmp al,0x0a > jc hex1 > add al,0x07 > hex1: > add al,0x30 > mov ah 0x0e > mov bh,0 > int 0x10 * mov bx,0x7e00 ;restore buf-ptr > pop ax > ret __ wolfgang
[toc] | [prev] | [next] | [standalone]
| From | Rod Pemberton <NoHaveNotOne@bcczxcfre.cmm> |
|---|---|
| Date | 2016-04-06 00:10 -0400 |
| Message-ID | <20160406001011.196bfc80@_> |
| In reply to | #9403 |
On Tue, 5 Apr 2016 05:34:50 -0700 bilsch <king621@comcast.net> wrote: > First, good news: I revised the program (see listing below), and for > the first time ah=0x48 returns CF=0 (success) and ah=0. Congratulations! Did you find out the issue with the earlier code? ... > But the number of sectors doesn't work out right. > It says EAB025420000FFFF. Ben made a comment on your print routines being backwards. I'm assuming that this value is word correct, but the QWORD word order is reversed, because things seem to work out below ... Technically, then, assuming EAB025420000FFFF is word correct but the QWORD word order is reversed, then the byte order is B0 EA 42 25 00 00 FF FF. So, the QWORD value is FFFF00002542EAB0. > Backwards EAB02542 is 24520BAE is 609356718 decimal, > times 512 is 311,990,639,616 bytes. But that doesn't > take little endian into account. GPARTED says > 320,071,700,616 bytes. "24520BAE" is "incorrectly" reversed from EAB02542. 24520BAE is EAB02542 reversed by nybbles (4-bits). 4225B0EA is EAB02542 reversed by bytes (8-bits). 2542EAB0 is EAB02542 reversed by words (16-bits). I think you want the last value since your code gets AX. 2542EAB0 is 625142448 in decimal which times 512 gives 320,072,933,376. That is only slightly more than the 320,071,700,616 which GPARTED reported. Some programs use 1000 instead of 1024 for a KB (kilobyte). This is especially true for programs which report disk capacity since manufacturers do that. It would seem that GPARTED is using 500 here instead of 512. I.e., the value 311,990,639,616 from GPARTED divided by 625,142,448 (2542EAB0 in hex) gives 499 ... I'll let you track down the off-by-one discrepancy between 499 and 500, which should be around 7.5GB to 8GB on a 300GB to 320GB drive. If using GPARTED, i.e., Linux etc., maybe check 'fdisk -l' for the reported device capacity. > [snip] > > mov bx,i2xt > xor cx,cx ;cx counts to 1 > pop ax > lup1: ;here ax is data from ah=0x41 > rol ax,4 ;put hi hex digit on right > push ax ;rol'd version > and al,0x0f ;digit in al, is index into i2xt > xlat ;table result in al, bx already > points i2xt mov ah,0xe > int 0x10 ;write > pop ax > cmp cx,1 > je api ;cx=1 then done w/ah > inc cx > jmp lup1 You rolled your own hex routine. That's a good start. Is it your first? There is usually a virtual round of applause for your first one on x86! (clap! clap!) There are many other ways to do hex for x86, including some which are faster (larger) and some that are much shorter. E.g., some simply add a value to a nybble, IIRC 0x30, then compare and add seven for the upper hex digits 'A' to 'F'. This eliminates the need for the 'xlat' table. It might be a few bytes shorter. IIRC, some routines use one of the BCD instructions (AAA, AAD, AAM, AAS, DAA, DAS) to unpack nybbles. It might be the AAA instruction ... Rod Pemberton
[toc] | [prev] | [standalone]
Back to top | Article view | alt.os.development
csiph-web